[<< Contents] [<< Prev] [Next >>]
Here we will allow the user to save the simulation data to an XML format file. We will add a menu option and a toolbar icon, and will use KFileDialog functionality to let the user select the filename and location.
In the KSimulate class, we will add a new slot "fileSave" to be associated with a new action "actionSave". We will also add a private pointer to point to the CanvasView outside the constructor.
Use a forward declaration for the CanvasView class rather than including the header file to make the compilation easier and faster.
class CanvasView; |
Add the public slot to receive the signal that the user wants to save.
bool fileSave(); // save current simulation |
Define the private pointer to point to the CanvasView.
private: CanvasView* canvasView; // pointer to canvas view |
Include the header files to give access to the KFileDialog, KUser, QDom, and QDateTime functionality.
#include <kfiledialog.h> #include <kuser.h> #include <qdom.h> #include <qdatetime.h> |
In the constructor, create the new action to encapulsate the save to file action using a standard action definition provided by KStdAction.
KAction *actionSave = KStdAction::save(this, SLOT(fileSave()), 0); |
Add the new action to the File menu.
// add actions to File menu actionSave->plug( menuFile ); |
And add the new action to the toolbar.
actionSave->plug( toolBar() ); |
Modify the statement that creates the CanvasView to use the KSimulate private variable instead of a local variable.
canvasView = new CanvasView( canvas, this ); |
Finally add the slot method to receive the new action signal and to save the simulation data to an XML format file. As mentioned previously we use KFileDialog to get the user to select the filename and location. We then construct an XML document in memory using QDom functionality before writing to the document to the file as a text stream. The function returns true if the simulation is successfully saved, otherwise false.
/******************************** fileSave *********************************/
bool KSimulate::fileSave()
{
// get user to select filename and location
QString fileName = KFileDialog::getSaveFileName();
if (fileName.isEmpty()) return false;
// start the XML document
QDomDocument doc( "KSimulate" );
// create the main data element and station elements
QDomElement data = doc.createElement( "data" );
KUser user(KUser::UseRealUserID);
data.setAttribute( "savedBy", user.loginName() );
data.setAttribute( "savedAt", QDateTime::currentDateTime().toString(Qt::LocalDate) );
doc.appendChild( data );
canvasView->saveStations( &doc, &data );
// open the file and check we can write to it
QFile file(fileName);
if (!file.open(IO_WriteOnly))
{
statusBar()->message(QString("Failed to save '%1'").arg(fileName));
return false;
}
// output the XML document as a text stream to the file
QTextStream ts(&file);
ts << doc.toString();
file.close();
statusBar()->message(QString("Saved to '%1'").arg(fileName));
return true;
}
|
To support the KSimulate fileSave slot, we will provide a new CanvasView method to add the stations to the XML document.
void saveStations( QDomDocument*, QDomElement* ); // save stations to XML document |
In the new method we add an XML element for each station storing its x and y coordinates.
/****************************** saveStations *******************************/
void CanvasView::saveStations(QDomDocument* doc, QDomElement* data)
{
// get list of all stations and add to XML document data element
QCanvasItemList list = canvas()->allItems();
for( QCanvasItemList::iterator it = list.begin(); it != list.end(); ++it )
{
QDomElement stn = doc->createElement( "station" );
stn.setAttribute( "x", (*it)->x() );
stn.setAttribute( "y", (*it)->y() );
data->appendChild( stn );
}
}
|
Lets also take the opportunity to remove the status bar message each time the canvas is resized in "viewportResizeEvent".
// update status bar to say resize happened
sbar->message(QString("Canvas resized to %1,%2").arg(w).arg(h));
|
As the "KFileDialog" class is in the KIO library rather than the standard KDEUI library, we need to tell KDevelop that an extra library is required when linking our application. This is done by using the Automake Manager which is opened using an icon on the far-right of KDevelop. Open the Automake Manager and click the "Show options" icon (its the lower of the two icons that looks like a spanner). Select the Libraries tab, press the Add button and enter "$(LIB_KIO)". Press OK and OK.
The new code will be compile successfully using KDevelop. Investigate how the application behaves and the content of the XML files.
[<< Contents] [<< Prev] [Next >>]