This chapter covers the file handling features of Qt that is used to write loading and saving routines for the address book application.
Although browsing and searching for contacts are useful features, your address book is not really ready for use until you can save existing contacts and load them again at a later time. Qt provides a number of classes for input and output, but you have chosen to use two which are simple to use in combination: QFile and QDataStream.
A QFile object represents a file on disk that can be read from and written to. QFile is a subclass of the more general QIODevice class which represents many different kinds of devices.
A QDataStream object is used to serialize binary data so that it can be stored in a QIODevice and retrieved again later. Reading from a QIODevice and writing to it is as simple as opening the stream - with the respective device as a parameter - and reading from or writing to it.
To load and save files containing contact details, you need two push buttons. Drag them and name them accordingly. Their objectName properties should be loadButton and saveButton, respectively. Then, similar to Chapter 5, place these buttons in our layout simply by dragging and dropping them.
The text property of our push buttons are Load... and Save... respectively. Ideally, it would be more user-friendly to set the push buttons' labels to Load contacts from file and Save contacts to file. However, due to the size of our push buttons, set the labels to Load... and Save... instead.
Fortunately, Qt Creator's Qt Designer plugin provides a simple way to set tooltips with the toolTip property. So, set your buttons' tooltips to Load contacts from file and Save contacts to file respectively. To test your tooltip, use Alt+Shift+R and hover your mouse cursor on the push buttons.
Declare two public slots, saveToFile() and loadFromFile().
Now lets look at the saveToFile() and loadFromFile() functions in detail.
To save a contact, first obtain fileName using QFileDialog::getSaveFileName(). This is a convenience function provided by QFileDialog, which pops up a modal file dialog and allows you to enter a file name or select any existing .abk file. The .abk file is our Address Book extension that you create when you save contacts.
The file dialog that pops up is displayed in the screenshot below:
If fileName is not empty, create a QFile object, file, with fileName. The QFile object works with QDataStream as QFile is a QIODevice.
Next, attempt to open the file in WriteOnly mode. If this is unsuccessful, display a QMessageBox to inform the user.
Otherwise, instantiate a QDataStream object, out, to write the open file. QDataStream requires that the same version of the stream is used for reading and writing. Ensure that this is the case by setting the version used to the version introduced with Qt 4.5 before serializing the data into file.
To load a contact, also obtain fileName using QFileDialog::getOpenFileName(). This function, the counterpart to QFileDialog::getSaveFileName(), also pops up the modal file dialog and allows you to enter a file name or select any existing .abk file to load it into the address book.
On Windows, for example, this function pops up a native file dialog, as shown in the following screenshot.
If fileName is not empty, again, use a QFile object, file, and attempt to open it in ReadOnly mode. Similar to your implementation of saveToFile(), if this attempt is unsuccessful, display a QMessageBox to inform the user.
Otherwise, instantiate a QDataStream object, in, set its version as above and read the serialized data into hte contacts data structure. The contacts object is emptied before data is read into it to simplify the file reading process. A more advanced method would be to read the contacts into a temporary QMap object, and copy over non-duplicate contacts into contacts.
To display the contacts that have been read from the file, you must first validate the data obtained to ensure that the file you read from actually contains address book contacts. If it does, display the first contact; otherwise, display a QMessageBox to inform you about the problem. Lastly, connect the clicked() signal of the push buttons with the loadFromFile() and saveToFile():