![]() |
Home · Overviews · Examples |
The address book example shows how to use proxy models to display different views onto data from a single model.
TableModel is a subclass of QAbstractTableModel that provides the standard model/view API to access data. It also holds a QList of QPairs corresponding to the contacts added. However, this data is not all visible in a single tab. Instead, QTableView is used to provide 9 different views of the same data, according to the alphabet groups.
QSortFilterProxyModel is the class responsible for filtering the contacts for each group of contacts. Each proxy model uses a QRegExp to filter out contacts that do not belong in the corresponding alphabetical group. The AddDialog class is used to obtain information from the user for the address book. This QDialog subclass is instantiated by NewAddressTab to add contacts, and by AddressWidget to add and edit contacts.
We begin by looking at the TableModel implementation. Note: The Q_UNUSED() macro prevents the compiler from generating warnings regarding unused parameters.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The data() function returns either a Name or Address, based on the contents of the model index supplied. The row number stored in the model index is used to reference an item in the list of pairs. Selection is handled by the QItemSelectionModel, which will be explained with AddressWidget.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The headerData() function displays the table's header, Name and Address. If you require numbered entries for your address book, you can use a vertical header which we have hidden in this example (see the AddressWidget implementation).
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The insertRows() function is called before new data is added, otherwise the data will not be displayed. The beginInsertRows() and endInsertRows() functions are called to ensure all connected views are aware of the changes.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The removeRows() function is called to remove data. Again, beginRemoveRows() and endRemoveRows() are called to ensure all connected views are aware of the changes.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The setData() function is the function that inserts data into the table, item by item and not row by row. This means that to fill a row in the address book, setData() must be called twice, as each row has 2 columns. It is important to emit the dataChanged() signal as it tells all connected views to update their displays.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The flags() function returns the item flags for the given index.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
We set the Qt::ItemIsEditable flag because we want to allow the TableModel to be edited. Although for this example we don't use the editing features of the QTableView object, we enable them here so that we can reuse the model in other programs. The last function in TableModel, getList() returns the QList<QPair<QString, QString>> object that holds all the contacts in the address book. We use this function later to obtain the list of contacts to check for existing entries, write the contacts to a file and read them back. Further explanation is given with AddressWidget.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
Each table view's selectionMode is set to QAbstractItemView::SingleSelection and selectionBehavior is set to QAbstractItemView::SelectRows, allowing the user to select all the items in one row at the same time. Each QTableView object is automatically given a QItemSelectionModel that keeps track of the selected indexes.
Missing snippet: itemviews/addressbook/addresswidget.cpp.
The QItemSelectionModel class provides a selectionChanged signal that is connected to AddressWidget's selectionChanged() signal. This signal to signal connection is necessary to enable the Edit Entry... and Remove Entry actions in MainWindow's Tools menu. This connection is further explained in MainWindow's implementation. Each table view in the address book is added as a tab to the QTabWidget with the relevant label, obtained from the QStringList of groups. The first addEntry() function is a slot connected to the MainWindow's Add Entry... action. This function creates an AddDialog object and then calls the second addEntry() function to actually add the contact to table.
Missing snippet: itemviews/addressbook/addresswidget.cpp.
Basic validation is done in the second addEntry() function to prevent duplicate entries in the address book. As mentioned with TableModel, this is part of the reason why we require the getter method getList().
Missing snippet: itemviews/addressbook/addresswidget.cpp.
If the model does not already contain an entry with the same name, we call setData() to insert the name and address into the first and second columns. Otherwise, we display a QMessageBox to inform the user. Note: The newAddressTab is removed once a contact is added as the address book is no longer empty. Editing an entry is a way to update the contact's address only, as the example does not allow the user to change the name of an existing contact. Firstly, we obtain the active tab's QTableView object using QTabWidget::currentWidget(). Then we extract the selectionModel from the tableView to obtain the selected indexes.
Missing snippet: itemviews/addressbook/addresswidget.cpp.
Next we extract data from the row the user intends to edit. This data is displayed in an instance of AddDialog with a different window title. The table is only updated if changes have been made to data in aDialog.
Missing snippet: itemviews/addressbook/addresswidget.cpp.
TableModel Class Definition
The TableModel class provides standard API to access data in its QList of QPairs by subclassing QAbstractTableModel. The basic functions that must be implemented in order to do so are: rowCount(), columnCount(), data(), headerData(). For TableModel to be editable, it has to provide implementations insertRows(), removeRows(), setData() and flags() functions.
Missing snippet: itemviews/addressbook/tablemodel.h.
Two constructors are used, a default constructor which uses TableModel's own QList<QPair<QString, QString>> and one that takes QList<QPair<QString, QString> as an argument, for convenience.TableModel Class Implementation
We implement the two constructors as defined in the header file. The second constructor initializes the list of pairs in the model, with the parameter value.
Missing snippet: itemviews/addressbook/tablemodel.cpp.
The rowCount() and columnCount() functions return the dimensions of the model. Where rowCount()'s value will vary depending on the number of contacts added to the address book, columnCount()'s value is always 2 because we only need space for the Name and Address columns. AddressWidget Class Definition
The AddressWidget class is technically the main class involved in this example as it provides functions to add, edit and remove contacts, to save the contacts to a file and to load them from a file.
Missing snippet: itemviews/addressbook/addresswidget.h.
AddressWidget extends QTabWidget in order to hold 10 tabs (NewAddressTab and the 9 alphabet group tabs) and also manipulates table, the TableModel object, proxyModel, the QSortFilterProxyModel object that we use to filter the entries, and tableView, the QTableView object.AddressWidget Class Implementation
The AddressWidget constructor accepts a parent widget and instantiates NewAddressTab, TableModel and QSortFilterProxyModel. The NewAddressTab object, which is used to indicate that the address book is empty, is added and the rest of the 9 tabs are set up with setupTabs().
Missing snippet: itemviews/addressbook/addresswidget.cpp.
The setupTabs() function is used to set up the 9 alphabet group tabs, table views and proxy models in AddressWidget. Each proxy model in turn is set to filter contact names according to the relevant alphabet group using a case-insensitiveQRegExp object. The table views are also sorted in ascending order using the corresponding proxy model's sort() function.
We provide 2 addEntry() functions: 1 which is intended to be used to accept user input, and the other which performs the actual task of adding new entries to the address book. We divide the responsibility of adding entries into two parts to allow newAddressTab to insert data without having to popup a dialog.
Entries are removed using the removeEntry() function. The selected row is removed by accessing it through the QItemSelectionModel object, selectionModel. The newAddressTab is re-added to the AddressWidget only if the user removes all the contacts in the address book.
Missing snippet: itemviews/addressbook/addresswidget.cpp.
The writeToFile() function is used to save a file containing all the contacts in the address book. The file is saved in a custom .dat format. The contents of the QList of QPairs are written to file using QDataStream. If the file cannot be opened, a QMessageBox is displayed with the related error message.
Missing snippet: itemviews/addressbook/addresswidget.cpp.
The readFromFile() function loads a file containing all the contacts in the address book, previously saved using writeToFile(). QDataStream is used to read the contents of a .dat file into a list of pairs and each of these is added using addEntry().
Missing snippet: itemviews/addressbook/addresswidget.cpp.
NewAddressTab Class Definition
The NewAddressTab class provides an informative tab telling the user that the address book is empty. It appears and disappears according to the contents of the address book, as mentioned in AddressWidget's implementation.
The NewAddressTab class extends QWidget and contains a QLabel and QPushButton.
Missing snippet: itemviews/addressbook/newaddresstab.h.
NewAddressTab Class Implementation
The constructor instantiates the addButton, descriptionLabel and connects the addButton's signal to the addEntry() slot.
Missing snippet: itemviews/addressbook/newaddresstab.cpp.
The addEntry() function is similar to AddressWidget's addEntry() in the sense that both functions instantiate an AddDialog object. Data from the dialog is extracted and sent to AddressWidget's addEntry() slot by emitting the sendDetails() signal.
Missing snippet: itemviews/addressbook/newaddresstab.cpp.
AddDialog Class Definition
The AddDialog class extends QDialog and provides the user with a QLineEdit and a QTextEdit to input data into the address book.
Missing snippet: itemviews/addressbook/adddialog.h.
![]() | ![]() |
The openFile() function allows the user to choose a file with the open file dialog. The chosen file has to be a custom .dat file that contains address book contacts. This function is a slot connected to openAct in the File menu.
Missing snippet: itemviews/addressbook/mainwindow.cpp.
The saveFile() function allows the user to save a file with the save file dialog. This function is a slot connected to saveAct in the File menu.
Missing snippet: itemviews/addressbook/mainwindow.cpp.
The updateActions() function enables and disables Edit Entry... and Remove Entry depending on the contents of the address book. If the address book is empty, these actions are disabled; otherwise, they are enabled. This function is a slot is connected to the AddressWidget's selectionChanged() signal.
Missing snippet: itemviews/addressbook/mainwindow.cpp.
main() Function
The main function for the address book instantiates QApplication and opens a MainWindow before running the event loop.
Missing snippet: itemviews/addressbook/main.cpp.
Copyright © 2008 Trolltech | Trademarks | Qt Jambi 4.4.0_01 |