doc/src/examples/addressbook.qdoc
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the documentation of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \example itemviews/addressbook
       
    44     \title Address Book Example
       
    45 
       
    46     The address book example shows how to use proxy models to display
       
    47     different views onto data from a single model.
       
    48 
       
    49     \image addressbook-example.png Screenshot of the Address Book example
       
    50 
       
    51     This example provides an address book that allows contacts to be
       
    52     grouped alphabetically into 9 groups: ABC, DEF, GHI, ... , VW,
       
    53     ..., XYZ. This is achieved by using multiple views on the same
       
    54     model, each of which is filtered using an instance of the
       
    55     QSortFilterProxyModel class.
       
    56 
       
    57 
       
    58     \section1 Overview
       
    59 
       
    60     The address book contains 5 classes: \c MainWindow,
       
    61     \c AddressWidget, \c TableModel, \c NewAddressTab and
       
    62     \c AddDialog. The \c MainWindow class uses \c AddressWidget as
       
    63     its central widget and provides \gui File and \gui Tools menus.
       
    64 
       
    65     \image addressbook-classes.png Diagram for Address Book Example
       
    66 
       
    67     The \c AddressWidget class is a QTabWidget subclass that is used
       
    68     to manipulate the 10 tabs displayed in the example: the 9
       
    69     alphabet group tabs and an instance of \c NewAddressTab.
       
    70     The \c NewAddressTab class is a subclass of QWidget that
       
    71     is only used whenever the address book is empty, prompting the
       
    72     user to add some contacts. \c AddressWidget also interacts with
       
    73     an instance of \c TableModel to add, edit and remove entries to
       
    74     the address book.
       
    75 
       
    76     \c TableModel is a subclass of QAbstractTableModel that provides
       
    77     the standard model/view API to access data. It also holds a
       
    78     QList of \l{QPair}s corresponding to the contacts added.
       
    79     However, this data is not all visible in a single tab. Instead,
       
    80     QTableView is used to provide 9 different views of the same
       
    81     data, according to the alphabet groups.
       
    82 
       
    83     QSortFilterProxyModel is the class responsible for filtering
       
    84     the contacts for each group of contacts. Each proxy model uses
       
    85     a QRegExp to filter out contacts that do not belong in the
       
    86     corresponding alphabetical group. The \c AddDialog class is
       
    87     used to obtain information from the user for the address book.
       
    88     This QDialog subclass is instantiated by \c NewAddressTab to
       
    89     add contacts, and by \c AddressWidget to add and edit contacts.
       
    90 
       
    91     We begin by looking at the \c TableModel implementation.
       
    92 
       
    93 
       
    94     \section1 TableModel Class Definition
       
    95 
       
    96     The \c TableModel class provides standard API to access data in
       
    97     its QList of \l{QPair}s by subclassing QAbstractTableModel. The
       
    98     basic functions that must be implemented in order to do so are:
       
    99     \c rowCount(), \c columnCount(), \c data(), \c headerData().
       
   100     For TableModel to be editable, it has to provide implementations
       
   101     \c insertRows(), \c removeRows(), \c setData() and \c flags()
       
   102     functions.
       
   103 
       
   104     \snippet itemviews/addressbook/tablemodel.h 0
       
   105 
       
   106     Two constructors are used, a default constructor which uses
       
   107     \c TableModel's own \c {QList<QPair<QString, QString>>} and one
       
   108     that takes \c {QList<QPair<QString, QString>} as an argument,
       
   109     for convenience.
       
   110 
       
   111 
       
   112     \section1 TableModel Class Implementation
       
   113 
       
   114     We implement the two constructors as defined in the header file.
       
   115     The second constructor initializes the list of pairs in the
       
   116     model, with the parameter value.
       
   117 
       
   118     \snippet itemviews/addressbook/tablemodel.cpp 0
       
   119 
       
   120     The \c rowCount() and \c columnCount() functions return the
       
   121     dimensions of the model. Whereas, \c rowCount()'s value will vary
       
   122     depending on the number of contacts added to the address book,
       
   123     \c columnCount()'s value is always 2 because we only need space
       
   124     for the \bold Name and \bold Address columns.
       
   125 
       
   126     \note The \c Q_UNUSED() macro prevents the compiler from
       
   127     generating warnings regarding unused parameters.
       
   128 
       
   129     \snippet itemviews/addressbook/tablemodel.cpp 1
       
   130 
       
   131     The \c data() function returns either a \bold Name or
       
   132     \bold {Address}, based on the contents of the model index
       
   133     supplied. The row number stored in the model index is used to
       
   134     reference an item in the list of pairs. Selection is handled
       
   135     by the QItemSelectionModel, which will be explained with
       
   136     \c AddressWidget.
       
   137 
       
   138     \snippet itemviews/addressbook/tablemodel.cpp 2
       
   139 
       
   140     The \c headerData() function displays the table's header,
       
   141     \bold Name and \bold Address. If you require numbered entries
       
   142     for your address book, you can use a vertical header which we
       
   143     have hidden in this example (see the \c AddressWidget
       
   144     implementation).
       
   145 
       
   146     \snippet itemviews/addressbook/tablemodel.cpp 3
       
   147 
       
   148     The \c insertRows() function is called before new data is added,
       
   149     otherwise the data will not be displayed. The
       
   150     \c beginInsertRows() and \c endInsertRows() functions are called
       
   151     to ensure all connected views are aware of the changes.
       
   152 
       
   153     \snippet itemviews/addressbook/tablemodel.cpp 4
       
   154 
       
   155     The \c removeRows() function is called to remove data. Again,
       
   156     \l{QAbstractItemModel::}{beginRemoveRows()} and
       
   157     \l{QAbstractItemModel::}{endRemoveRows()} are called to ensure
       
   158     all connected views are aware of the changes.
       
   159 
       
   160     \snippet itemviews/addressbook/tablemodel.cpp 5
       
   161 
       
   162     The \c setData() function is the function that inserts data into
       
   163     the table, item by item and not row by row. This means that to
       
   164     fill a row in the address book, \c setData() must be called
       
   165     twice, as each row has 2 columns. It is important to emit the
       
   166     \l{QAbstractItemModel::}{dataChanged()} signal as it tells all
       
   167     connected views to update their displays.
       
   168 
       
   169     \snippet itemviews/addressbook/tablemodel.cpp 6
       
   170 
       
   171     The \c flags() function returns the item flags for the given
       
   172     index.
       
   173 
       
   174     \snippet itemviews/addressbook/tablemodel.cpp 7
       
   175 
       
   176     We set the Qt::ItemIsEditable flag because we want to allow the
       
   177     \c TableModel to be edited. Although for this example we don't
       
   178     use the editing features of the QTableView object, we enable
       
   179     them here so that we can reuse the model in other programs.
       
   180 
       
   181     The last function in \c {TableModel}, \c getList() returns the
       
   182     QList<QPair<QString, QString>> object that holds all the
       
   183     contacts in the address book. We use this function later to
       
   184     obtain the list of contacts to check for existing entries, write
       
   185     the contacts to a file and read them back. Further explanation is
       
   186     given with \c AddressWidget.
       
   187 
       
   188     \snippet itemviews/addressbook/tablemodel.cpp 8
       
   189 
       
   190 
       
   191     \section1 AddressWidget Class Definition
       
   192 
       
   193     The \c AddressWidget class is technically the main class
       
   194     involved in this example as it provides functions to add, edit
       
   195     and remove contacts, to save the contacts to a file and to load
       
   196     them from a file.
       
   197 
       
   198     \snippet itemviews/addressbook/addresswidget.h 0
       
   199 
       
   200     \c AddressWidget extends QTabWidget in order to hold 10 tabs
       
   201     (\c NewAddressTab and the 9 alphabet group tabs) and also
       
   202     manipulates \c table, the \c TableModel object, \c proxyModel,
       
   203     the QSortFilterProxyModel object that we use to filter the
       
   204     entries, and \c tableView, the QTableView object.
       
   205 
       
   206 
       
   207     \section1 AddressWidget Class Implementation
       
   208 
       
   209     The \c AddressWidget constructor accepts a parent widget and
       
   210     instantiates \c NewAddressTab, \c TableModel and
       
   211     QSortFilterProxyModel. The \c NewAddressTab object, which is
       
   212     used to indicate that the address book is empty, is added
       
   213     and the rest of the 9 tabs are set up with \c setupTabs().
       
   214 
       
   215     \snippet itemviews/addressbook/addresswidget.cpp 0
       
   216 
       
   217     The \c setupTabs() function is used to set up the 9 alphabet
       
   218     group tabs, table views and proxy models in
       
   219     \c AddressWidget. Each proxy model in turn is set to filter
       
   220     contact names according to the relevant alphabet group using a
       
   221     \l{Qt::CaseInsensitive}{case-insensitive} QRegExp object. The
       
   222     table views are also sorted in ascending order using the
       
   223     corresponding proxy model's \l{QSortFilterProxyModel::}{sort()}
       
   224     function.
       
   225 
       
   226     Each table view's \l{QTableView::}{selectionMode} is set to
       
   227     QAbstractItemView::SingleSelection and
       
   228     \l{QTableView::}{selectionBehavior} is set to
       
   229     QAbstractItemView::SelectRows, allowing the user to select
       
   230     all the items in one row at the same time. Each QTableView object
       
   231     is automatically given a QItemSelectionModel that keeps track
       
   232     of the selected indexes.
       
   233 
       
   234     \snippet itemviews/addressbook/addresswidget.cpp 1
       
   235 
       
   236     The QItemSelectionModel class provides a
       
   237     \l{QItemSelectionModel::selectionChanged()}{selectionChanged}
       
   238     signal that is connected to \c{AddressWidget}'s
       
   239     \c selectionChanged() signal. This signal to signal connection
       
   240     is necessary to enable the \gui{Edit Entry...} and
       
   241     \gui{Remove Entry} actions in \c MainWindow's Tools menu. This
       
   242     connection is further explained in \c MainWindow's
       
   243     implementation.
       
   244 
       
   245     Each table view in the address book is added as a tab to the
       
   246     QTabWidget with the relevant label, obtained from the QStringList
       
   247     of groups.
       
   248 
       
   249     \image addressbook-signals.png Signals and Slots Connections
       
   250 
       
   251     We provide 2 \c addEntry() functions: 1 which is intended to be
       
   252     used to accept user input, and the other which performs the actual
       
   253     task of adding new entries to the address book. We divide the
       
   254     responsibility of adding entries into two parts to allow
       
   255     \c newAddressTab to  insert data without having to popup a dialog.
       
   256 
       
   257     The first \c addEntry() function is a slot connected to the
       
   258     \c MainWindow's \gui{Add Entry...} action. This function creates an
       
   259     \c AddDialog object and then calls the second \c addEntry()
       
   260     function to actually add the contact to \c table.
       
   261 
       
   262     \snippet itemviews/addressbook/addresswidget.cpp 2
       
   263 
       
   264     Basic validation is done in the second \c addEntry() function to
       
   265     prevent duplicate entries in the address book. As mentioned with
       
   266     \c TableModel, this is part of the reason why we require the
       
   267     getter method \c getList().
       
   268 
       
   269     \snippet itemviews/addressbook/addresswidget.cpp 3
       
   270 
       
   271     If the model does not already contain an entry with the same name,
       
   272     we call \c setData() to insert the name and address into the
       
   273     first and second columns. Otherwise, we display a QMessageBox
       
   274     to inform the user.
       
   275 
       
   276     \note The \c newAddressTab is removed once a contact is added
       
   277     as the address book is no longer empty.
       
   278 
       
   279     Editing an entry is a way to update the contact's address only,
       
   280     as the example does not allow the user to change the name of an
       
   281     existing contact.
       
   282 
       
   283     Firstly, we obtain the active tab's QTableView object using
       
   284     QTabWidget::currentWidget(). Then we extract the
       
   285     \c selectionModel from the \c tableView to obtain the selected
       
   286     indexes.
       
   287 
       
   288     \snippet itemviews/addressbook/addresswidget.cpp 4a
       
   289 
       
   290     Next we extract data from the row the user intends to 
       
   291     edit. This data is displayed in an instance of \c AddDialog
       
   292     with a different window title. The \c table is only
       
   293     updated if changes have been made to data in \c aDialog.
       
   294 
       
   295     \snippet itemviews/addressbook/addresswidget.cpp 4b
       
   296 
       
   297     \image addressbook-editdialog.png Screenshot of Dialog to Edit a Contact
       
   298 
       
   299     Entries are removed using the \c removeEntry() function.
       
   300     The selected row is removed by accessing it through the
       
   301     QItemSelectionModel object, \c selectionModel. The
       
   302     \c newAddressTab is re-added to the \c AddressWidget only if
       
   303     the user removes all the contacts in the address book.
       
   304 
       
   305     \snippet itemviews/addressbook/addresswidget.cpp 5
       
   306 
       
   307     The \c writeToFile() function is used to save a file containing
       
   308     all the contacts in the address book. The file is saved in a
       
   309     custom \c{.dat} format. The contents of the QList of \l{QPair}s
       
   310     are written to \c file using QDataStream. If the file cannot be
       
   311     opened, a QMessageBox is displayed with the related error message.
       
   312 
       
   313     \snippet itemviews/addressbook/addresswidget.cpp 6
       
   314 
       
   315     The \c readFromFile() function loads a file containing all the
       
   316     contacts in the address book, previously saved using
       
   317     \c writeToFile(). QDataStream is used to read the contents of a
       
   318     \c{.dat} file into a list of pairs and each of these is added
       
   319     using \c addEntry().
       
   320 
       
   321     \snippet itemviews/addressbook/addresswidget.cpp 7
       
   322 
       
   323 
       
   324     \section1 NewAddressTab Class Definition
       
   325 
       
   326     The \c NewAddressTab class provides an informative tab telling
       
   327     the user that the address book is empty. It appears and
       
   328     disappears according to the contents of the address book, as
       
   329     mentioned in \c{AddressWidget}'s implementation.
       
   330 
       
   331     \image addressbook-newaddresstab.png Screenshot of NewAddressTab
       
   332 
       
   333     The \c NewAddressTab class extends QWidget and contains a QLabel
       
   334     and QPushButton.
       
   335 
       
   336     \snippet itemviews/addressbook/newaddresstab.h 0
       
   337 
       
   338 
       
   339     \section1 NewAddressTab Class Implementation
       
   340 
       
   341     The constructor instantiates the \c addButton,
       
   342     \c descriptionLabel and connects the \c{addButton}'s signal to
       
   343     the \c{addEntry()} slot.
       
   344 
       
   345     \snippet itemviews/addressbook/newaddresstab.cpp 0
       
   346 
       
   347     The \c addEntry() function is similar to \c AddressWidget's
       
   348     \c addEntry() in the sense that both functions instantiate an
       
   349     \c AddDialog object. Data from the dialog is extracted and sent
       
   350     to \c AddressWidget's \c addEntry() slot by emitting the
       
   351     \c sendDetails() signal.
       
   352 
       
   353     \snippet itemviews/addressbook/newaddresstab.cpp 1
       
   354 
       
   355     \image signals-n-slots-aw-nat.png
       
   356 
       
   357 
       
   358     \section1 AddDialog Class Definition
       
   359 
       
   360     The \c AddDialog class extends QDialog and provides the user
       
   361     with a QLineEdit and a QTextEdit to input data into the
       
   362     address book.
       
   363 
       
   364     \snippet itemviews/addressbook/adddialog.h 0
       
   365 
       
   366     \image addressbook-adddialog.png
       
   367 
       
   368 
       
   369     \section1 AddDialog Class Implementation
       
   370 
       
   371     The \c AddDialog's constructor sets up the user interface,
       
   372     creating the necessary widgets and placing them into layouts.
       
   373 
       
   374     \snippet itemviews/addressbook/adddialog.cpp 0
       
   375 
       
   376     To give the dialog the desired behavior, we connect the \gui OK
       
   377     and \gui Cancel buttons to the dialog's \l{QDialog::}{accept()} and
       
   378     \l{QDialog::}{reject()} slots. Since the dialog only acts as a
       
   379     container for name and address information, we do not need to
       
   380     implement any other functions for it.
       
   381 
       
   382 
       
   383     \section1 MainWindow Class Definition
       
   384 
       
   385     The \c MainWindow class extends QMainWindow and implements the
       
   386     menus and actions necessary to manipulate the address book.
       
   387 
       
   388     \table
       
   389     \row \o \inlineimage addressbook-filemenu.png
       
   390          \o \inlineimage addressbook-toolsmenu.png
       
   391     \endtable
       
   392 
       
   393     \snippet itemviews/addressbook/mainwindow.h 0
       
   394 
       
   395     The \c MainWindow class uses an \c AddressWidget as its central
       
   396     widget and provides the File menu with \gui Open, \gui Close and
       
   397     \gui Exit actions, as well as the \gui Tools menu with
       
   398     \gui{Add Entry...}, \gui{Edit Entry...} and \gui{Remove Entry}
       
   399     actions.
       
   400 
       
   401 
       
   402     \section1 MainWindow Class Implementation
       
   403 
       
   404     The constructor for \c MainWindow instantiates AddressWidget,
       
   405     sets it as its central widget and calls the \c createMenus()
       
   406     function.
       
   407 
       
   408     \snippet itemviews/addressbook/mainwindow.cpp 0
       
   409 
       
   410     The \c createMenus() function sets up the \gui File and
       
   411     \gui Tools menus, connecting the actions to their respective slots.
       
   412     Both the \gui{Edit Entry...} and \gui{Remove Entry} actions are
       
   413     disabled by default as such actions cannot be carried out on an empty
       
   414     address book. They are only enabled when one or more contacts
       
   415     are added.
       
   416 
       
   417     \snippet itemviews/addressbook/mainwindow.cpp 1a
       
   418     \dots
       
   419     \codeline
       
   420     \snippet itemviews/addressbook/mainwindow.cpp 1b
       
   421 
       
   422     Apart from connecting all the actions' signals to their
       
   423     respective slots, we also connect \c AddressWidget's
       
   424     \c selectionChanged() signal to its \c updateActions() slot.
       
   425 
       
   426     The \c openFile() function allows the user to choose a file with
       
   427     the \l{QFileDialog::getOpenFileName()}{open file dialog}. The chosen
       
   428     file has to be a custom \c{.dat} file that contains address book
       
   429     contacts. This function is a slot connected to \c openAct in the
       
   430     \gui File menu.
       
   431 
       
   432     \snippet itemviews/addressbook/mainwindow.cpp 2
       
   433 
       
   434     The \c saveFile() function allows the user to save a file with
       
   435     the \l{QFileDialog::getSaveFileName()}{save file dialog}. This function
       
   436     is a slot connected to \c saveAct in the \gui File menu.
       
   437 
       
   438     \snippet itemviews/addressbook/mainwindow.cpp 3
       
   439 
       
   440     The \c updateActions() function enables and disables
       
   441     \gui{Edit Entry...} and \gui{Remove Entry} depending on the contents of
       
   442     the address book. If the address book is empty, these actions
       
   443     are disabled; otherwise, they are enabled. This function is a slot
       
   444     is connected to the \c AddressWidget's \c selectionChanged()
       
   445     signal.
       
   446 
       
   447     \snippet itemviews/addressbook/mainwindow.cpp 4
       
   448 
       
   449 
       
   450     \section1 main() Function
       
   451 
       
   452     The main function for the address book instantiates QApplication
       
   453     and opens a \c MainWindow before running the event loop.
       
   454 
       
   455     \snippet itemviews/addressbook/main.cpp 0
       
   456 */