addressbook-sdk.qdoc 43.3 KB
Newer Older
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
8
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11
12
13
14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15
16
**
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
24
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
con's avatar
con committed
25
26
27
28
29
30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
31
**
32
**************************************************************************/
33
34
35
36
37

/*!
    \page tutorials-addressbook-sdk.html

    \startpage {index.html}{Qt Reference Documentation}
38
    \nextpage {examples/addressbook-sdk/part1}{Chapter 1}
39
40
41
42
43
44
45
46

    \title Address Book Tutorial
    \brief An introduction to GUI programming with Qt and Qt Creator,
    describing in detail how to put together a simple yet fully-
    functioning application.

    This tutorial gives an introduction to GUI programming using the Qt SDK.

47
    \image addressbook-tutorial-screenshot.png
48

49
    In the process, you will learn about some basic technologies provided by
50
51
52
53
54
55
56
57
58
    Qt, such as:

    \list
        \o  Widgets and layout managers
        \o  Container classes
        \o  Signals and slots
        \o  Input and output devices
    \endlist

59
60
61
    All these technologies will be introduced via the Qt Creator Integrated
    Development Environment (IDE).

62
63
64
65
66
67
68
69
70
    If you are completely new to Qt, please read \l{How to Learn Qt} if you
    have not already done so.

    The tutorial's source code is located in Qt's
    \c{examples/tutorials/addressbook} directory.

    Tutorial chapters:

    \list 1
71
72
73
74
75
76
77
        \o \l{examples/addressbook-sdk/part1}{Designing the User Interface}
        \o \l{examples/addressbook-sdk/part2}{Adding Addresses}
        \o \l{examples/addressbook-sdk/part3}{Navigating between Entries}
        \o \l{examples/addressbook-sdk/part4}{Editing and Removing Addresses}
        \o \l{examples/addressbook-sdk/part5}{Adding a Find Function}
        \o \l{examples/addressbook-sdk/part6}{Loading and Saving}
        \o \l{examples/addressbook-sdk/part7}{Additional Features}
78
79
80
81
82
83
84
85
    \endlist

    Although this little application does not look much like a fully-fledged
    modern GUI application, it uses many of the basic techniques that are used
    in more complex applications. After you have worked through it, we
    recommend checking out the \l{mainwindows/application}{Application}
    example, which presents a small GUI application, with menus, toolbars, a
    status bar, and so on.
86

87
88
89
90
91
92
*/


/*!
    \page tutorials-addressbook-sdk-part1.html
    \contentspage {Address Book Tutorial}{Contents}
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
93
    \nextpage {examples/addressbook-sdk/part2}{Chapter 2}
94
    \example examples/addressbook-sdk/part1
95

96
97
98
    \title Address Book 1 - Designing the User Interface

    The first part of this tutorial covers the design of the basic graphical
99
    user interface (GUI) you use for the Address Book application.
100
101

    The first step to creating a GUI program is to design the user interface.
102
    In this chapter, your goal is to set up the labels and input fields needed
103
104
105
106
107
    to implement a basic address book application. The figure below is a
    screenshot of our expected output.

    \image addressbook-tutorial-part1-screenshot.png

108
109
110
    Begin by launching Qt Creator and use it to generate a new project. To
    do this, select \gui{File} > \gui{New File or Project...} >
    \gui{Qt Application Project} > \gui{Qt Gui Application} and
111
112
113
    click \gui OK. Set your project name to \bold part1 with the QtCore and
    QtGui modules checked. Ensure that you select QWidget as your base class
    and name it \c AddressBook.
114

115
116
    When you click \gui Next, \e five files will be generated in this
    \gui{Project}:
117
118

    \list
119
120
        \o  \c{main.cpp} - the file containing a \c main() function, with an
            instance of \c AddressBook,
121
122
        \o  \c{addressbook.cpp} - the implementation file for the
            \c AddressBook class,
123
124
125
126
127
        \o  \c{addressbook.h} - the definition file for the \c AddressBook
            class,
        \o  \c{addressbook.ui} - the user interface file created with \QD,
            and
        \o  \c{part1.pro} - the project file.
128
129
    \endlist

130
131
    Now that you have all the files you need, click \gui Finish so you can
    start designing the user interface.
132

133
134
    \note For more details on how to create a \gui Project with Qt Creator,
    refer to \l{Creating a Project}.
135

136
    \section1 Placing Widgets on The Form
137

138
139
140
    \image addressbook-tutorial-part1-creator-screenshot.png

    In the \gui{Projects} sidebar, double-click on the \c{addressbook.ui} file.
141
142
143
    The \QD plugin will be launched, allowing you to design your program's user
    interface.

144
145
    \image addressbook-tutorial-part1-designer-screenshot.png

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    You require two \l{QLabel}s to label the input fields as well as a
    QLineEdit and a QTextEdit for the input fields. To create this follow the
    steps mentioned below:
    \list
       \o  Drag those widgets from the \gui{Widget Box} to your form.
       \o  In the \gui{Property Editor}, set their \gui{objectName} property to
           \c nameLabel and \c addressLabel for the \l{QLabel}s, \c nameLine
           for the QLineEdit and finally, \c addressText for the QTextEdit.
       \o  Position the widgets properly, according to the screenshot above.
       \o  Use a QGridLayout to position our labels and input fields in a
           structured manner. QGridLayout divides the available space into
           a grid and places widgets in the cells you specify with row and
           column numbers.
       \o  Place the caption of the \c addressLabel on the top, change the
           vertical alignment property to \c AlignTop.
    \endlist

    The figure below shows the layout cells and the position of our widgets.
    Place your widgets accordingly and save the form by choosing
    \gui{File} > \gui{Save} or use the shortcut key \key{Ctrl+S}.
166
167
168

    \image addressbook-tutorial-part1-labeled-screenshot.png

169
170
171
172
173
    A common mistake when designing user interfaces with \QD is overlooking the
    top level widget's layout. Unlike sub-layouts, which \QD displays with a
    red border, top level layouts have no graphical representation. Layouts are
    necessary for top level widgets, in this case QWidget, to ensure that when
    the window is resized, the widgets on the form will resize accordingly. You
174
    can try this out by pressing \key{Alt+Shift+R} now. To correct it, click
175
176
177
    anywhere on the form and select \gui{Lay out Horizontally} or
    \gui{Lay out Vertically}. The output will be the same. Now your widgets
    will resize correctly.
178

179
180
181
182
    \note Refer to the \l{Layout Classes} document for more
    details on Qt's layout management classes. In addition, the
    \l{Getting to Know Qt Designer} document explains how to use
    layouts with \QD.
183

184
    \section1 The AddressBook Class
185
186
187
188

    The \l{examples/addressbook-sdk/part1/addressbook.h}{\c addressbook.h} file
    is used to define the \c AddressBook class.

189
    Let's take a look at what is already provided for us by Qt Creator. The
190
    \c AddressBook class has been defined as a QWidget subclass with a
191
    constructor and destructor.The Q_OBJECT macro is used to indicate that this
192
193
194
    class uses internationalization as well as Qt's signals and slots features.
    Although the macro implements some of Qt's more advanced features, for now,
    it is useful to think of it as a shortcut that allows us to use the
195
    \l{QObject::}{tr()} and \l{QObject::}{connect()} functions.
196
197
198

    \snippet examples/addressbook-sdk/part1/addressbook.h class definition

199
    Qt Creator's \gui{Project Wizard} provides you with the \c Ui object as a
200
    way to access the widgets on our form.
201

202
203
204
    The \l{examples/addressbook-sdk/part1/addressbook.cpp}{\c addressbook.cpp}
    file is used to implement the \c AddressBook class. The constructor sets up
    the \c ui file; the destructor deletes it.
205

206
    \snippet examples/addressbook-sdk/part1/addressbook.cpp class implementation
207

208

209
    \section1 The \c{main()} Function
210

211
212
213
214
215
    The \l{examples/addressbook-sdk/part1/main.cpp}{\c main.cpp} file contains
    the \c{main()} function  It is generated by the \gui{Project Wizard}.
    Within this function, a QApplication object, \c a, is instantiated.
    QApplication is responsible for various application-wide resources, such as
    the default font and cursor, and for running an event loop. Hence, there is
216
    always one QApplication object in every GUI application using Qt.
217

218
    \snippet examples/addressbook-sdk/part1/main.cpp main function
219

220
221
    The code constructs a new \c AddressBook widget on the stack and
    invokes its \l{QWidget::}{show()} function to display it.
222
    However, the widget will not be shown until the application's event
223
224
225
226
227
228
229
230
    loop is started. This is done by calling the application's
    \l{QApplication::}{exec()} function. Finally, the result returned by
    \l{QApplication::}{exec()} is used as the \c main() function's return
    value.


    \section1 Running the Application

231
232
233
234
    To run your application with Qt Creator, simply click,
    \inlineimage qtcreator-run.png.
    A bare bones Address Book will be displayed.

235

236
237
238

    \section1 Qt Programming - Subclassing

239
    When writing Qt programs, you usually subclass Qt objects to add
240
241
242
243
244
    functionality. This is one of the essential concepts behind creating custom
    widgets or collections of standard widgets. Subclassing to extend or change
    the behavior of a widget has the following advantages:

    \list
245
246
        \o  You can write implementations of virtual or pure virtual functions
            to obtain exactly what you need, falling back on the base class's
247
            implementation when necessary.
248
        \o  It allows you to encapsulate parts of the user interface within a
249
250
251
252
253
254
255
            class, so that the other parts of the application do not need to
            know about the individual widgets in the user interface.
        \o  The subclass can be used to create multiple custom widgets in the
            same application or library, and the code for the subclass can be
            reused in other projects.
    \endlist

256
    Since Qt does not provided a specific address book widget, you subclass a
257
    standard Qt widget class and add features to it. The \c AddressBook class
258
    you create in this tutorial can be reused in situations where a basic
259
    address book is needed.
260
261


262
*/
263

264

265
266
267
268
/*!
    \page tutorials-addressbook-sdk-part2.html
    \previouspage Address Book 1 - Designing the User Interface
    \contentspage {Address Book Tutorial}{Contents}
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
269
    \nextpage {examples/addressbook-sdk/part3}{Chapter 3}
270
271
272
273
274
275
    \example examples/addressbook-sdk/part2
    \title Address Book 2 - Adding Addresses

    The next step to creating our basic address book application is to allow a
    little bit of user interaction.

Kavindra Palaraja's avatar
Kavindra Palaraja committed
276
    \image addressbook-tutorial-part2-add-contact.png
277

278
279
280
    You will provide a push button that the user can click to add a new
    contact. Also, some form of data structure is needed to store these
    contacts in an organized way.
281
282


283
    \section1 Placing Widgets on The Form
284

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
    You can continue with the form from the last chapter; you have the
    labels and input fields set up, but you need to add push buttons to
    complete the process of adding a contact. Break the existing layouts by
    following the steps below:
    \list
        \o Select, \gui{Break Layout} from the context menu. You might have to
           do a \gui{Select All} with \key{Ctrl+A} first..
        \o Add three push buttons and double-click on each of them to set
           their text to "Add", "Submit", and "Cancel".
        \o Set the \c objectName of the buttons to \c addButton,
           \c submitButton and \c cancelButton respectively.
        \o A \gui{Vertical Spacer} is required to ensure that the push buttons
           will be laid out neatly; drag one from the \gui{Widget Box}.
        \o Lay out these three push buttons and the spacer vertically, by
           selecting all three of them using \key{Ctrl + click} and selecting
           \gui{Lay out Vertically} from the context menu. Alternatively you
           can  use the \key{Ctrl+L} shortcut key.

           \note Use the spacer as you do not want the buttons to be evenly
           spaced, but arranged closer to the top of the widget.
        \o The figure below shows the difference between using the spacer and
           not using it.
           \image addressbook-tutorial-part2-stretch-effects.png
        \o Select all the objects on the form using, \key{Ctrl+A} and lay them
           out in a grid.
        \o Lastly, set the top level widget's layout by right-clicking anywhere
           on the widget and selecting \gui{Lay out Horizontally} or
           \gui{Lay out Vertically}.
    \endlist
314

315
316
    The final design of the form is shown in the screenshot below:

317
    \image addressbook-tutorial-part2-form-design.png
318
319
320
321


    \section1 The AddressBook Class

322
323
324
325
    To ensure that the Address Book reacts to user interaction, you need to
    write slots for each push button that you added earlier. A slot is a
    function that responds to a particular signal. This concept will be
    discussed further in detail below. However, for an overview of Qt's signals
326
327
328
    and slots concept, you can refer to the \l{Signals and Slots} document.

    In the \l{examples/addressbook-sdk/part2/addressbook.h}{\c addressbook.h}
329
    file, add the following code:
330
331
332

    \snippet examples/addressbook-sdk/part2/addressbook.h slot definition

333
    Since the \c AddressBook class is a subclass of QWidget, Qt Creator
334
335
    includes QWidget in the header file.

336
337
    \snippet examples/addressbook-sdk/part2/addressbook.h include

338
    You need a container to store our address book contacts, so that you can
339
340
341
    traverse and display them. A QMap object, \c contacts, is used for this
    purpose as it holds a key-value pair: the contact's name as the \e key, and
    the contact's address as the \e value.
342

343
    \snippet examples/addressbook-sdk/part2/addressbook.h members
344

345
    You also declare two private QString objects, \c oldName and \c oldAddress.
346
    These objects are needed to hold the name and address of the contact that
347
348
    was last displayed, before you click \gui Add. So, when you
    click \gui Cancel, you can revert to displaying the details of the last
349
350
    contact.

351

352
353
354
355
356
357
358
359

    Let's move on to implementing the slots defined earlier. Within the
    constructor of \c AddressBook, you set up our fields by ensuring that
    \c nameLine and \c addressText are read-only, so that you can only display
    but not edit existing contact details.

    \note In order to prevent crashes, you need make sure that the
    autogenerated \c setupUi() call is always first in the constructor.
360

361
    \snippet examples/addressbook-sdk/part2/addressbook.cpp setup fields
362

363
364
    You also hide both \c submitButton and \c cancelButton as they will only be
    displayed when you click \gui Add, and this is handled by the
365
    \c addContact() function discussed below.
366
367
368

    \snippet examples/addressbook-sdk/part2/addressbook.cpp signal slot

369
    You connect the push buttons' \l{QAbstractButton::}{clicked()} signal to
370
    their respective slots. The figure below illustrates this.
371

Kavindra Palaraja's avatar
Kavindra Palaraja committed
372
    \image addressbook-tutorial-part2-signals-and-slots.png
373

374
    Finally, set the window title to "Simple Address Book" using the
375
    \l{QWidget::}{setWindowTitle()} function. The tr() method allows us
376
    to translate user interface strings.
377
378
379

    \snippet examples/addressbook-sdk/part2/addressbook.cpp window title

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
380
    \section2 The \c addContact() Function
381

382
383
384
385
    In this function, begin by storing the last displayed contact details
    in \c oldName and \c oldAddress. Then clear these input fields and turn
    off the read-only mode. The focus is set on \c nameLine and display
    \c submitButton and \c cancelButton; but disable \c addButton.
386

387
    \snippet examples/addressbook-sdk/part2/addressbook.cpp addContact
388

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
389
    \section2 The \c submitContact() Function
390
391
392
393

    This function can be divided into three parts:

    \list 1
394
395
396
397
        \o  Extract the contact's detail from \c nameLine and \c addressText
            and store them in QString objects. Also validate to ensure that
            you did not click \gui Submit with empty input fields;
            otherwise, a QMessageBox is displayed to remind you for a name
398
399
400
401
            and address.

            \snippet examples/addressbook-sdk/part2/addressbook.cpp submitContact part1

402
403
404
        \o  Then proceed to check if the contact already exists. If it does
            not exist, add the contact to \c contacts and display a
            QMessageBox to inform you about this, preventing you from
405
            adding duplicate contacts. Our \c contacts object is based on
406
            key-value pairs or name and address, hence, you want to ensure that
407
408
409
410
            \e key is unique.

            \snippet examples/addressbook-sdk/part2/addressbook.cpp submitContact part2

411
        \o  Once you have handled both cases mentioned above, restore the
412
413
414
415
416
            push buttons to their normal state with the following code:

            \snippet examples/addressbook-sdk/part2/addressbook.cpp submitContact part3
    \endlist

417
    The screenshot below shows the QMessageBox object used to display
418
419
    information messages to the user.

Kavindra Palaraja's avatar
Kavindra Palaraja committed
420
    \image addressbook-tutorial-part2-add-successful.png
421

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
422
    \section2 The \c cancel() Function
423
424
425
426
427
428

    This function restores the last displayed contact details and enables
    \c addButton, as well as hides \c submitButton and \c cancelButton.

    \snippet examples/addressbook-sdk/part2/addressbook.cpp cancel

429
    The general idea behind adding a contact is to give you the
430
431
432
433
434
435
436
437
438
439
440
    flexibility to click \gui Submit or \gui Cancel at any time. The flowchart
    below further explains this concept:

    \image addressbook-tutorial-part2-add-flowchart.png


    \section1 Running the Application

    Run your application now. You will be able to add as many unique contacts
    as you like.

441
*/
442
443
444
445
446
447


/*!
    \page tutorials-addressbook-sdk-part3.html
    \previouspage Address Book 2 - Adding Addresses
    \contentspage {Address Book Tutorial}{Contents}
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
448
    \nextpage {examples/addressbook-sdk/part4}{Chapter 4}
449
    \example examples/addressbook-sdk/part3
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
450
    \title Address Book 3 - Navigating between Entries
451

452
453
454
    The address book application is now half complete. You need to add some
    functions to navigate between contacts. But first, you have to decide what
    sort of a data structure you would like to use to hold these contacts.
455

456
    In Chapter 2, you used a QMap of key-value pairs with the contact's name as
457
    the \e key, and the contact's address as the \e value. This works well for
458
    your case. However, in order to navigate and display each entry, a little
459
460
    bit of enhancement is needed.

461
    Enhance the QMap by making it replicate a data structure similar to a
462
463
    circularly-linked list, where all elements are connected, including the
    first element and the last element. The figure below illustrates this data
464
    structure.
465
466
467
468

    \image addressbook-tutorial-part3-linkedlist.png


469
    \section1 Placing Widgets on The Form
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
    So far, your application allows us to add new contacts. However, you also
    need to traverse the existing contacts. To do so follow the steps
    mentioned below:
    \list
        \o Add two push buttons at the bottom of your application and name
           them: \gui Next and \gui Previous.
        \o The buttons' \c objectName should be \c nextButton and
           \c previousButton, respectively.
        \o Break your top level layout by right-clicking on \c AddressBook in
           the \gui{Object Inspector} and then select \gui{Lay out|Break Layout}.
        \o Place the \gui Next and \gui Previous buttons in a horizontal
           layout.
        \o Drag and drop the buttons together with their layout into the
           existing grid layout.
        \o Set a top level layout for the widget again.
    \endlist
487

488
489
    The screenshot below illustrates what you will see as the button layout
    approaches the grid layout; drop it then.
490

491
    \image addressbook-tutorial-part3-drop-in-gridlayout.png
492

493
    \note Follow basic conventions for \c next() and \c previous() functions
494
495
496
    by placing the \c nextButton on the right and the \c previousButton on the
    left.

497

498
499
    \section1 The AddressBook Class

500
501
502
    In order to add navigation functions to the address book application,
    you need to add two more slots to our \c AddressBook class: \c next() and
    \c previous().
503
504
505

    \snippet examples/addressbook-sdk/part3/addressbook.h slot definition

506
507
508
    In the \c AddressBook constructor, you setup your fields and disable them
    by default. This is because navigation is only enabled when there is more
    than one contact in the address book.
509

510
511
    \snippet examples/addressbook-sdk/part3/addressbook.cpp setup fields

512
    Next, connect the buttons to their respective slots:
513
514
515

    \snippet examples/addressbook-sdk/part3/addressbook.cpp signal slot

516
517
    The screenshot below is your expected graphical user interface. Notice that
    it is getting closer to your final application.
518

Kavindra Palaraja's avatar
Kavindra Palaraja committed
519
520
    \image addressbook-tutorial-part3-screenshot.png

521
522
    Within your \c addContact() function, you have to disable the \gui Next and
    \gui Previous buttons so that you do not attempt to navigate while
523
524
525
526
    adding a contact.

    \snippet examples/addressbook-sdk/part3/addressbook.cpp disable navigation

527
528
    Also, in your \c submitContact() function, enable the navigation buttons,
    depending on the size of \c contacts. As mentioned earlier, navigation is
529
530
531
532
533
    only enabled when there is more than one contact in the address book. The
    following lines of code demonstrates how to do this:

    \snippet examples/addressbook-sdk/part3/addressbook.cpp enable navigation

534
    Also include these lines of code in the \c cancel() function.
535

536
537
    Recall that you intend to emulate a circularly-linked list with your QMap
    object, \c contacts. So in the \c next() function, obtain an iterator
538
539
540
    for \c contacts and then:

    \list
541
        \o If the iterator is not at the end of \c contacts, increment it by
542
           one.
543
544
        \o If the iterator is at the end of \c contacts, move it to the
           beginning of \c contacts. This gives an illusion that our QMap
545
546
547
548
549
           is working like a circularly-linked list.
    \endlist

    \snippet examples/addressbook-sdk/part3/addressbook.cpp next

550
    Once you have iterated to the current object in \c contacts, display its
551
552
    contents on \c nameLine and \c addressText.

553
    Similarly, for the \c previous() function, obtain an iterator for
554
555
556
    \c contacts and then:

    \list
557
        \o  If the iterator is at the end of \c contacts, clear the display
558
            and return.
559
        \o  If the iterator is at the beginning of \c contacts, move it to
560
            the end.
561
        \o  Then decrement the iterator by one.
562
    \endlist
563

564
    \snippet examples/addressbook-sdk/part3/addressbook.cpp previous
565

566
    Again, display the contents of the current object in \c contacts.
567

568
*/
569

570

571
572
573
574
/*!
    \page tutorials-addressbook-sdk-part4.html
    \previouspage Address Book 3 - Navigating between Entries
    \contentspage {Address Book Tutorial}{Contents}
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
575
    \nextpage {examples/addressbook-sdk/part5}{Chapter 5}
576
    \example examples/addressbook-sdk/part4
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
577
    \title Address Book 4 - Editing and Removing Addresses
578

579
    This chapter looks at ways to modify the contents of contacts stored
580
581
    in the address book application.

582
    \image addressbook-tutorial-part4-screenshot.png
583

584
    You now have an address book that not only holds contacts in an organized
585
586
587
588
    manner, but also allows navigation. It would be convenient to include edit
    and remove functions so that a contact's details can be changed when
    needed. However, this requires a little improvement, in the form of enums.

589
590
591
592
    In our previous chapters, you had two modes: \c AddingMode and
    \c NavigationMode - but they were not defined as enums. Instead, you
    enabled and disabled the corresponding buttons manually, resulting in
    multiple lines of repeated code.
593

594
    In this chapter, define the \c Mode enum with three different values:
595
    \list
596
597
598
        \o \c{NavigationMode}
        \o \c{AddingMode}
        \o \c{EditingMode}
599
600
    \endlist

601
    \section1 Placing Widgets on The Form
602

603
    To edit and remove contacts, you need two push buttons. Drag them and name
604
605
606
607
608
609
610
611
    them accordingly. Their \c objectName properties should be \c editButton
    and \c removeButton, respectively. The quickest way to place these two
    buttons into our existing layout, is to simply drag and drop them. Use the
    screenshot below as a guide:

    \image addressbook-tutorial-part4-drop-in-gridlayout.png


612
613
    \section1 The AddressBook Class

614
    Update the header file to contain the \c Mode enum:
615
616
617

    \snippet examples/addressbook-sdk/part4/addressbook.h enum

618
    Also add two new slots, \c editContact() and \c removeContact(), to your
619
620
621
622
    current list of public slots.

    \snippet examples/addressbook-sdk/part4/addressbook.h slot definition

623
    In order to switch between modes, introduce the \c updateInterface()
624
    function to control the enabling and disabling of all push buttons.
625

626
    \snippet examples/addressbook-sdk/part4/addressbook.h updateInterface
627

628
    Lastly, declare \c currentMode to keep track of the enum's current mode.
629
630
631
632

    \snippet examples/addressbook-sdk/part4/addressbook.h current mode

    Let's begin by implementing the mode-changing features of the address book
633
634
    application. The \c editButton and \c removeButton are disabled by default,
    as the address book starts up with zero contacts in memory.
635

636
    \snippet examples/addressbook-sdk/part4/addressbook.cpp extract objects
637

638
639
640
641
642
    These buttons are then connected to their respective slots,
    \c editContact() and \c removeContact.

    \snippet examples/addressbook-sdk/part4/addressbook.cpp signal slot

643
    Now look at the \c editContact() and \c removeContact() functions in
644
645
    detail.

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
646
    \section2 The \c editContact() Function
647
648
649
650
651
652
653
654

    This function stores the contact's old details in \c oldName and
    \c oldAddress, before switching the mode to \c EditingMode. In this mode,
    the \c submitButton and \c cancelButton are both enabled. Hence, the user
    can change the contact's details and click either button.

    \snippet examples/addressbook-sdk/part4/addressbook.cpp editContact

655
656
657
    Since you will reuse the \c submitButton for both: adding a new contact and
    editing an existing contact, you need to modify our existing
    \c submitContact() function. So, divide it in two with an \c{if-else}
658
659
    statement.

660
661
    First, check \c currentMode to see if it is in \c AddingMode. If it is,
    proceed with your adding process.
662
663
664
665
666

    \snippet examples/addressbook-sdk/part4/addressbook.cpp submitContact part1
    \dots
    \snippet examples/addressbook-sdk/part4/addressbook.cpp submitContact part2

667
668
    Otherwise, check to see if \c currentMode is in \c EditingMode. If it
    is, compare \c oldName with \c name. If the name has changed, remove
669
670
671
672
    the old contact from \c contacts and insert the newly updated contact.

    \snippet examples/addressbook-sdk/part4/addressbook.cpp submitContact part3

673
674
    If only the contact's address has changed, that is the \c oldAddress is
    not the  same as \c address, update the contact's address. Lastly, set
675
676
677
    \c currentMode to \c NavigationMode. This is an important step as it
    re-enables all the disabled push buttons.

678
    To remove a contact from the address book, implement the
679
680
681
682
683
    \c removeContact() function.

    \snippet examples/addressbook-sdk/part4/addressbook.cpp removeContact

    This function first checks to see if the contact exists in \c contacts. If
684
685
686
687
    it does, display a QMessageBox, to confirm the removal with the user.
    Once the user has confirmed, call \c previous() to ensure that the
    user interface shows another contact, and remove the contact using
    \l{QMap}'s \l{QMap::}{remove()} function. As a courtesy, display a
688
689
690
    QMessageBox to inform the user. Both the message boxes used in this
    function are shown below:

691
692
    \image addressbook-tutorial-part4-confirm.png
    \image addressbook-tutorial-part4-remove.png
693

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
694
    \section2 The \c updateInterface() Function
695

696
    This function is mentioned earlier as a means to enable and disable the
697
698
    push buttons, depending on the current mode. The function updates the
    current mode according to the \c mode argument passed to it, assigning it
699
    to \c currentMode, before checking its value.
700
701
702
703
704
705

    Each of the push buttons is then enabled or disabled, depending on the
    current mode. The code for \c AddingMode and \c EditingMode is shown below:

    \snippet examples/addressbook-sdk/part4/addressbook.cpp updateInterface part1

706
    For \c NavigationMode, however, include conditions within the parameters
707
708
709
710
711
712
713
714
    of the QPushButton::setEnabled() function. This is to ensure that
    \c editButton and \c removeButton are enabled when there is at least one
    contact in the address book; \c nextButton and \c previousButton are only
    enabled when there is more than one contact in the address book.

    \snippet examples/addressbook-sdk/part4/addressbook.cpp updateInterface part2

    By performing the task of setting the mode and updating the user interface
715
    in the same function, you avoid the possibility of the user interface
716
    getting "out of sync" with the internal state of the application.
717

718
    To maintain consistency, you need to modify our \c addContact() and
719
720
721
722
723
    \c cancel() functions respectively. Below is the code:

    \snippet examples/addressbook-sdk/part4/addressbook.cpp addContact
    \dots
    \snippet examples/addressbook-sdk/part4/addressbook.cpp cancel
724

725
726
727
728
*/


/*!
729
730
731
    \page tutorials-addressbook-sdk-part5.html
    \previouspage Address Book 4 - Editing and Removing Addresses
    \contentspage {Address Book Tutorial}{Contents}
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
732
    \nextpage {examples/addressbook-sdk/part6}{Chapter 6}
733
    \example examples/addressbook-sdk/part5
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
734
    \title Address Book 5 - Adding a Find Function
735

736
    This chapter looks at ways to locate contacts and addresses in the
737
738
    address book application.

739
    \image addressbook-tutorial-part5-screenshot.png
740

741
    As you keep adding contacts to your address book, it becomes tedious to
742
743
744
745
746
    navigate them with the \gui Next and \gui Previous buttons. In this case,
    a \gui Find function would be more efficient in looking up contacts. The
    screenshot above shows the \gui Find button and its position on the panel
    of buttons.

747
    When you click on the \gui Find button, it is useful to display a
748
    dialog prompting the user for a contact's name. Qt provides QDialog, which
749
    you subclass in this chapter, to implement a FindDialog class.
750

751

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
752
    \section1 Designing The FindDialog
753

754
    \image addressbook-tutorial-part5-finddialog-in-designer.png
755

756
757
758
759
760
761
762
763
    Begin by adding a new \c{.ui} file and a corresponding class to our
    project. Right click on your project and select
    \gui{Add New...} > \gui{Qt} > \gui{Qt Designer Form Class}.
    In the \gui{Qt Designer Form Class} dialog, select
    \e{Dialog without buttons}. Name the class \c{FindDialog} and add the files
    it to your project. Open your new form in the \QD form editor within
    Qt Creator by double-clicking on the \c{finddialog.ui} file in
    the \gui{Project Sidebar}.
764

765
    To replicate the screenshot above, you need a label, a line edit, and a push
766
767
768
769
770
    button. Drag these onto your form. Set their text accordingly and name them
    \c label, \c lineEdit, and \c findButton, respectively. Place these widgets
    in a horizontal layout. Then set a top level layout - either horizontal or
    vertical.

771

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
772
    \section1 Implementing The FindDialog Class
773

774
    Let's look at \c{FindDialog}'s header file. Define a public function,
775
    \c findText(), to be used by classes that instantiate \c FindDialog. This
776
777
778
    function allows the classes to obtain the search string entered by
    you. A public slot, \c findClicked(), is also defined to handle the
    search string when you click the \gui Find button.
779

780
    \snippet examples/addressbook-sdk/part5/finddialog.h findText
781
782
783
    \dots
    \snippet examples/addressbook-sdk/part5/finddialog.h findClicked

784
    Now, lets look at our constructor in the \c{finddialog.cpp} file.
785
786
787

    \snippet examples/addressbook-sdk/part5/finddialog.cpp constructor

788
789
    In \c findClicked(), validate to ensure that you did not click the
    \gui Find button without entering a contact's name. Then, set
790
    \c findText to the search string, extracted from \c lineEdit. After that,
791
    clear the contents of \c lineEdit and hide the dialog.
792

793
    \snippet examples/addressbook-sdk/part5/finddialog.cpp findClicked
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
794

795
    \c findText() is public, which makes it easy for classes instantiating
796
    and using \c FindDialog to access the search string that you have entered
797
    and accepted.
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
798

799
    \snippet examples/addressbook-sdk/part5/finddialog.cpp findText
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
800

801
    Finally, connect your signals to their respective slots. Notice that
802
    \c{findButton}'s \l{QPushButton::}{clicked()} signal is connected to
803
804
805
806
807
808
809
810
    \c findClicked(), which calls \l{QDialog::}{accept()} or
    \l{QDialog::}{reject()}. The \l{QDialog::}{accept()} slot provided by
    QDialog hides the dialog and sets the result code to
    \l{QDialog::}{Accepted}, while \l{QDialog::}{reject()}
    sets it to \l{QDialog::}{Rejected} accordingly. Use this function to help
    \c{AddressBook}'s \c findContact() function know when the \c FindDialog
    object has been closed. This logic will be explained in further detail
    when discussing the \c findContact() function.
811
812
813

    \image addressbook-tutorial-part5-signals-and-slots.png

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
814
815

    \section1 The AddressBook Class
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
816

817
818
    To ensure that you can use \c FindDialog from within your \c AddressBook
    class, include \c finddialog.h in the \c addressbook.h file.
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
819

820
    \snippet examples/addressbook-sdk/part5/addressbook.h include
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
821

822
823
    So far, all your address book features have a QPushButton and a
    corresponding slot. Similarly, the \gui Find feature, has
824
    \c{ui->findButton} and \c findContact().
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
825

826
    \snippet examples/addressbook-sdk/part5/addressbook.h slot definition
827

828
829
830
    Once you have instantiated a dialog, you might want to use it more than
    once; using a private variable allows you to refer to it from more than one
    place in the class.
831

832
    Within the \c AddressBook class's constructor, connect the
833
    \c{findButton}'s \l{QPushButton::}{clicked()} signal to \c findContact().
834
835
836
837
838
839
840

    \snippet examples/addressbook-sdk/part5/addressbook.cpp signal slot

    Now, all that is left is the code for our \c findContact() function:

    \snippet examples/addressbook-sdk/part5/addressbook.cpp findContact

841
842
    Start out by displaying the \c FindDialog instance, \c dialog. This is
    when you enter a contact name to look up. Once you click the
843
    dialog's \c findButton, the dialog is hidden and the result code is set to
844
    either QDialog::Accepted or QDialog::Rejected by the FindDialog's
845
846
    \c findClicked() method. This ensures that you only search for a contact
    if you have typed something in the FindDialog's line edit.
847

848
    Then proceed to extract the search string, which in this case is
849
    \c contactName, using \c{FindDialog}'s \c findText() function. If the
850
851
    contact exists in our address book, display it immediately. Otherwise,
    display the QMessageBox shown below to indicate that their search
852
853
    failed.

854
    \image addressbook-tutorial-part5-dialogbox.png
855

856
857
858
    The concept behind finding a contact only applies for cases where you have
    more than two contacts in our address book. Hence, implement this
    behavior by modifying our \c{Navigation Mode} within your
859
    \c updateInterface() function, by only enabling the \gui Find button when
860
    you have more than two contacts.
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
861

862
    \snippet examples/addressbook-sdk/part5/addressbook.cpp enable
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
863

864
865
*/

866

867
/*!
868
869
870
    \page tutorials-addressbook-sdk-part6.html
    \previouspage Address Book 5 - Adding a Find Function
    \contentspage {Address Book Tutorial}{Contents}
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
871
    \nextpage {examples/addressbook-sdk/part7}{Chapter 7}
872
    \example examples/addressbook-sdk/part6
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
873
    \title Address Book 6 - Loading and Saving
874

875
    This chapter covers the file handling features of Qt that is used to write
876
877
    loading and saving routines for the address book application.

878
    \image addressbook-tutorial-part6-screenshot.png
879

880
881
    Although browsing and searching for contacts are useful features, your
    address book is not really ready for use until you can save existing
882
    contacts and load them again at a later time. Qt provides a number of
883
    classes for \l{Input/Output and Networking}{input and output}, but you have
884
885
886
887
    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
888
    to. QFile is a subclass of the more general QIODevice class which represents
889
890
891
892
893
894
895
    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.

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
896

897
898
    \section1 Placing Widgets on The Form

899
    To load and save files containing contact details, you need two push
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
900
901
    buttons. Drag them and name them accordingly. Their \c objectName
    properties should be \c loadButton and \c saveButton, respectively. Then,
902
    similar to \l{Address Book 5 - Adding a Find Function}{Chapter 5}, place
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
903
904
905
906
907
908
    these buttons in our layout simply by dragging and dropping them.

    The \c text property of our push buttons are \gui{Load...} and
    \gui{Save...} respectively. Ideally, it would be more user-friendly to set
    the push buttons' labels to \gui{Load contacts from file} and
    \gui{Save contacts to file}. However, due to the size of our push buttons,
909
    set the labels to \gui{Load...} and \gui{Save...} instead.
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
910
911

    Fortunately, Qt Creator's \QD plugin provides a simple way to set tooltips
912
    with the \c toolTip property. So, set your buttons' tooltips to
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
913
    \gui{Load contacts from file} and \gui{Save contacts to file} respectively.
914
    To test your tooltip, use \key{Alt+Shift+R} and hover your mouse cursor on
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
915
    the push buttons.
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
916

917

918
    \image addressbook-tutorial-part6-propertyeditor.png
919
920
921
922


    \section1 The AddressBook Class

923
    Declare two public slots, \c saveToFile() and \c loadFromFile().
924

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
925
    \snippet examples/addressbook-sdk/part6/addressbook.h slot definition
926

Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
927
928
929
930
931
932
    Now lets look at the \c saveToFile() and \c loadFromFile() functions in
    detail.


    \section2 The \c saveToFile() Function

933
    To save a contact, first obtain \c fileName using
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
934
    QFileDialog::getSaveFileName(). This is a convenience function provided by
935
    QFileDialog, which pops up a modal file dialog and allows you to enter
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
936
    a file name or select any existing \c{.abk} file. The \c{.abk} file is our
937
    Address Book extension that you create when you save contacts.
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
938
939
940

    \snippet examples/addressbook-sdk/part6/addressbook.cpp saveToFile part1

941
    The file dialog that pops up is displayed in the screenshot below:
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
942

943
    \image addressbook-tutorial-part6-savedialog.png
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
944

945
    If \c fileName is not empty, create a QFile object, \c file, with
Kavindra Devi Palaraja's avatar
Kavindra Devi Palaraja committed
946
947
948
    \c fileName. The QFile object works with QDataStream as QFile is a
    QIODevice.