source: trunk/doc/src/examples/addressbook.qdoc@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 18.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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*/
Note: See TracBrowser for help on using the repository browser.