Implementing the AddressBook Class
In our constructor, we instantiate loadButton and saveButton. Ideally, it would be more user-friendly to set the push buttons' labels to "Load contacts from a file" and "Save contacts to a file". However, due to the size of our other push buttons, we set the labels to Load... and Save.... Fortunately, Qt provides a simple way to set tooltips with setToolTip() and we use it in the following way for our push buttons:
loadButton->setToolTip(tr("Load contacts from a file"));
...
saveButton->setToolTip(tr("Save contacts to a file"));
Although it is not shown here, just like the other features we implemented, we add the push buttons to the layout panel on the right, button1Layout, and we connect the push buttons' clicked() signals to their respective slots.
For the saving feature, we first obtain fileName using QFileDialog::getSaveFileName(). This is a convenience function provided by QFileDialog, which pops up a modal file dialog and allows the user to enter a file name or select any existing .abk file. The .abk file is our Address Book extension that we create when we save contacts.
void AddressBook::saveToFile()
{
QString fileName = QFileDialog::getSaveFileName(this,
tr("Save Address Book"), "",
tr("Address Book (*.abk);;All Files (*)"));
The file dialog that pops up is displayed in the screenshot below:
If fileName is not empty, we create a QFile object, file with fileName. QFile works with QDataStream as QFile is a QIODevice.
Next, we attempt to open the file in WriteOnly mode. If this is unsuccessful, we display a QMessageBox to inform the user.
if (fileName.isEmpty())
return;
else {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::information(this, tr("Unable to open file"),
file.errorString());
return;
}
Otherwise, we instantiate a QDataStream object, out, the read the open file. QDataStream requires that the same version of the stream is used for reading and writing. We ensure that this is the case by setting the version used to the version introduced with Qt 4.3 before serializing the data to file.
QDataStream out(&file);
out.setVersion(QDataStream::Qt_4_3);
out << contacts;
}
}
For the loading feature, we also obtain fileName using QFileDialog::getOpenFileName(). This function, the counterpart to QFileDialog::getSaveFileName(), also pops up the modal file dialog and allows the user to enter a file name or select any existing .abk file to load it into the address book.
void AddressBook::loadFromFile()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Address Book"), "",
tr("Address Book (*.abk);;All Files (*)"));
On Windows, for example, this function pops up a native file dialog, as shown in the following screenshot.
If fileName is not empty, again, we use a QFile object, file, and attempt to open it in ReadOnly mode. In a similar way to our implementation of saveToFile(), if this attempt is unsuccessful, we display a QMessageBox to inform the user.
if (fileName.isEmpty())
return;
else {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::information(this, tr("Unable to open file"),
file.errorString());
return;
}
QDataStream in(&file);
in.setVersion(QDataStream::Qt_4_3);
contacts.empty();
in >> contacts;
Otherwise, we instantiate a QDataStream object, in, set its version as above and read the serialized data into the contacts data structure. Note that we empty contacts before reading data into it to simplify the file reading process. A more advanced method would be to read the contacts into temporary QMap object, and copy only the contacts that do not already exist in contacts.
if (contacts.isEmpty()) {
QMessageBox::information(this, tr("No contacts in file"),
tr("The file you are attempting to open contains no contacts."));
} else {
QMap<QString, QString>::iterator i = contacts.begin();
nameLine->setText(i.key());
addressText->setText(i.value());
}
}
updateInterface(NavigationMode);
}
To display the contacts that have been read from the file, we must first validate the data obtained to ensure that the file we read from actually contains address book contacts. If it does, we display the first contact; otherwise, we display a QMessageBox to inform the user about the problem. Lastly, we update the interface to enable and disable the push buttons accordingly.
[Previous: Address Book 5 - Adding a Find Function]
[Contents]
[Next: Chapter 7]