KDE programming tutorial using KDevelop

Part 9: Saving to a file


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

Saving to an XML file

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.

Updating KSimulate

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.

ksimulate.h

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

ksimulate.cpp

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

Updating CanvasView

canvasview.h

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

canvasview.cpp

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

Linking with new library

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.

Compile and run

The new code will be compile successfully using KDevelop. Investigate how the application behaves and the content of the XML files.


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


Last updated 22-Dec-2004