KDE programming tutorial using KDevelop

Part 10: Loading from a file


[<< Contents] [<< Prev] [Next >>]

Loading from an XML file

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.

Updating KSimulate

In the KSimulate class, we will add a new slot "fileOpen" to be associated with a new action "actionOpen".

ksimulate.h

Add the public slot to receive the signal that the user wants to open a file.

  bool fileOpen();                             // open previously saved simulation

ksimulate.cpp

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;
}

Updating CanvasView

canvasview.h

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

canvasview.cpp

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();
}

Compile and run

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 >>]


Last updated 22-Dec-2004