Part 10: Saving to a file

Part 10: Saving to a file


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

Saving to an XML file

Here we enable the user to save their simulation data to an XML format file. We add a new File menu action "Save As ...", use QFileDialog functionality to let the user select the filename and location, and use QXmlStreamWriter functionality to write the XML file.

Enhancing the MainWindow

mainwindow.h

We need to add a public slot to receive the signal when user selects the new menu action.

  bool fileSaveAs();                  // save simulation to file returning true if successful

mainwindow.cpp

Include the header files for the QFileDialog, QXmlStreamWriter, and QDateTime functionality.

#include <QFileDialog>
#include <QXmlStreamWriter>
#include <QDateTime>

In the constructor update the line that creates the File menu to store the returned pointer in a local variable.

  QMenu*  fileMenu = menuBar()->addMenu( "&File" );

Still in the constructor we create and add the new save action to the File menu.

  // create file menu options
  QAction* saveAction    = fileMenu->addAction( "&Save As...",       this, SLOT(fileSaveAs()) );
  saveAction->setShortcut( QKeySequence::Save );

Finally we add the code for the new public slot. In this slot we ask the user for the filename and location for the file, check we can write to the file, and then create the XML file using QXmlStreamWriter functionality. Inside the XML file we create a "qsimulate" element with some informative attributes, and then call a new scene method to add further details. The slot returns true if a XML file was successfully produced, otherwise it returns false.

/************************************ fileSaveAs *************************************/

bool  MainWindow::fileSaveAs()
{
  // get user to select filename and location
  QString filename = QFileDialog::getSaveFileName();
  if ( filename.isEmpty() ) return false;

  // open the file and check we can write to it
  QFile file( filename );
  if ( !file.open( QIODevice::WriteOnly ) )
  {
    showMessage( QString("Failed to write to '%1'").arg(filename) );
    return false;
  }

  // open an xml stream writer and write simulation data
  QXmlStreamWriter  stream( &file );
  stream.setAutoFormatting( true );
  stream.writeStartDocument();
  stream.writeStartElement( "qsimulate" );
  stream.writeAttribute( "version", "2008-06" );
  stream.writeAttribute( "user", QString(getenv("USER")) );
  stream.writeAttribute( "when", QDateTime::currentDateTime().toString(Qt::ISODate) );
  m_scene->writeStream( &stream );
  stream.writeEndDocument();

  // close the file and display useful message
  file.close();
  showMessage( QString("Saved to '%1'").arg(filename) );
  return true;
}

Enhancing the Scene

scene.h

Add a forward declaration for the QXmlStreamWriter class.

class QXmlStreamWriter;

Add the declaration for the new public scene method that writes simulation data to a QXmlStreamWriter.

  void  writeStream( QXmlStreamWriter* );                    // write scene data to xml stream

scene.cpp

Include the header file for QXmlStreamWriter.

#include <QXmlStreamWriter>

Add the code for our new scene method. This method creates a new "station" element for each station on the scene with attributes giving its x & y coordinates.

/************************************ writeStream ************************************/

void  Scene::writeStream( QXmlStreamWriter* stream )
{
  // write station data to xml stream
  foreach( QGraphicsItem*  item, items() )
  {
    Station*  station = dynamic_cast<Station*>( item );
    if ( station )
    {
      stream->writeEmptyElement( "station" );
      stream->writeAttribute( "x", QString("%1").arg(station->x()) );
      stream->writeAttribute( "y", QString("%1").arg(station->y()) );
    }
  }
}

Compile and run

The new code will automatically re-compile when you attempt to run the application. Play with the application, save a few files and investigate the file contents.

Here is an example small file saved by our application.

<?xml version="1.0" encoding="UTF-8"?>
<qsimulate version="2008-06" user="dazzle" when="2008-06-21T08:58:16">
    <station x="69" y="124"/>
    <station x="109" y="56"/>
    <station x="159" y="95"/>
    <station x="213" y="61"/>
    <station x="208" y="128"/>
    <station x="284" y="108"/>
</qsimulate>

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


Last updated 21-Jul-2008