[<< Contents] [<< Prev] [Next >>]
Here we will allow the user to load simulation data from a previously saved 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 "fileOpen" to be associated with a new action "actionOpen".
Add the public slot to receive the signal that the user wants to open a file.
bool fileOpen(); // open previously saved simulation |
In the constructor, create the new action to encapulsate the open file action using a standard action definition provided by KStdAction.
KAction *actionOpen = KStdAction::open(this, SLOT(fileOpen()), 0); |
Add the new action to the File menu.
actionOpen->plug( menuFile ); |
And add the new action to the toolbar.
actionOpen->plug( toolBar() ); |
Finally add the slot method to receive the new action signal and to load the simulation data from an XML format file. As mentioned previously we use KFileDialog to get the user to select the filename and location. We then load the XML document into memory using QDom functionality before processing and creating the new stations. The function returns true if the simulation is successfully loaded, otherwise false.
/******************************** fileOpen **********************************/
bool KSimulate::fileOpen()
{
// get user to select filename and location
QString fileName = KFileDialog::getOpenFileName();
if (fileName.isEmpty()) return false;
// create an empty XML document
QDomDocument doc( "KSimulate" );
// open the file and check we can read from it
QFile file(fileName);
if (!file.open(IO_ReadOnly))
{
statusBar()->message(QString("Failed to open '%1'").arg(fileName));
return false;
}
// read the XML document from the file
if (!doc.setContent(&file))
{
file.close();
statusBar()->message(QString("Failed to read '%1'").arg(fileName));
return false;
}
file.close();
// check the document type is correct
if (doc.doctype().name() != "KSimulate")
{
statusBar()->message(QString("Invalid '%1'").arg(fileName));
return false;
}
// read the XML elements to create the stations
QDomElement data = doc.documentElement();
canvasView->loadStations( &data );
statusBar()->message(QString("Loaded '%1'").arg(fileName));
return true;
}
|
To support the KSimulate fileOpen slot, we will provide a new CanvasView method to read the XML document and create the stations.
void loadStations( QDomElement* ); // create stations from XML |
In the new method we start by deleting any old stations and resetting the minimum canvas size before going on to read the XML document. For each station element we create a new Station checking its position and minimum canvas size. Finally we resize the canvas and update the display.
/****************************** openStations *******************************/
void CanvasView::loadStations( QDomElement* data )
{
// delete existing stations
QCanvasItemList list = canvas()->allItems();
for( QCanvasItemList::iterator it = list.begin(); it != list.end(); ++it )
delete *it;
// reset minimum canvas size
minCanvasW = MIN_CANVAS_W;
minCanvasH = MIN_CANVAS_H;
// read XML document and create new stations
for ( QDomNode node = data->firstChild(); !node.isNull(); node = node.nextSibling() )
{
QDomElement stn = node.toElement();
int x = stn.attribute("x").toInt();
int y = stn.attribute("y").toInt();
// ensure station position and minimum canvas size updated as necessary
if ( x < 10 ) x = 10;
if ( y < 10 ) y = 10;
if ( x+10 > minCanvasW ) minCanvasW = x+10;
if ( y+10 > minCanvasH ) minCanvasH = y+10;
new Station( &stationSprite, canvas(), x, y );
}
// resize and update canvas so new stations are displayed
int w = visibleWidth();
int h = visibleHeight();
if ( w < minCanvasW ) w = minCanvasW;
if ( h < minCanvasH ) h = minCanvasH;
canvas()->resize( w, h );
canvas()->update();
}
|
The new code will be compiled automatically when you next attempt to re-run the application using KDevelop. Investigate how the application behaves.
[<< Contents] [<< Prev] [Next >>]