Remove references to "How to Learn Qt", since that is in qtdoc repo.
[profile/ivi/qtbase.git] / src / widgets / doc / src / addressbook.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** GNU Free Documentation License
10 ** Alternatively, this file may be used under the terms of the GNU Free
11 ** Documentation License version 1.3 as published by the Free Software
12 ** Foundation and appearing in the file included in the packaging of
13 ** this file.
14 **
15 ** Other Usage
16 ** Alternatively, this file may be used in accordance with the terms
17 ** and conditions contained in a signed written agreement between you
18 ** and Nokia.
19 **
20 **
21 **
22 **
23 **
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \page tutorials-addressbook.html
30
31     \title Address Book Tutorial
32     \brief An introduction to GUI programming, showing how to put together a
33     simple yet fully-functioning application.
34
35     This tutorial is an introduction to GUI programming with the Qt
36     cross-platform framework.
37
38     \image addressbook-tutorial-screenshot.png
39
40     \omit
41     It doesn't cover everything; the emphasis is on teaching the programming
42     philosophy of GUI programming, and Qt's features are introduced as needed.
43     Some commonly used features are never used in this tutorial.
44     \endomit
45
46     In this tutorial, you will learn about some of the basic
47     components of Qt, including:
48
49     \list
50     \li Widgets and layout managers
51     \li Container classes
52     \li Signals and slots
53     \li Input and output devices
54     \endlist
55
56     Tutorial contents:
57
58     \list 1
59     \li \l{tutorials/addressbook/part1}{Designing the User Interface}
60     \li \l{tutorials/addressbook/part2}{Adding Addresses}
61     \li \l{tutorials/addressbook/part3}{Navigating between Entries}
62     \li \l{tutorials/addressbook/part4}{Editing and Removing Addresses}
63     \li \l{tutorials/addressbook/part5}{Adding a Find Function}
64     \li \l{tutorials/addressbook/part6}{Loading and Saving}
65     \li \l{tutorials/addressbook/part7}{Additional Features}
66     \endlist
67
68     The tutorial source code is located in \c{examples/tutorials/addressbook}.
69
70     Although this little application does not look much like a
71     fully-fledged modern GUI application, it uses many of the basic
72     elements that are used in more complex applications. After you
73     have worked through this tutorial, we recommend reading the
74     \l{mainwindows/application}{Application} example, which presents a
75     small GUI application, with menus, toolbars, a status bar, and so
76     on.  
77 */
78
79 /*!
80     \page tutorials-addressbook-part1.html
81
82     \example tutorials/addressbook/part1
83     \title Part 1 - Designing the User Interface
84
85     This first part covers the design of the basic graphical user
86     interface (GUI) for our address book application.
87
88     The first step in creating a GUI program is to design the user
89     interface.  Here the our goal is to set up the labels and input
90     fields to implement a basic address book. The figure below is a
91     screenshot of the expected output.
92
93     \image addressbook-tutorial-part1-screenshot.png
94
95     We require two QLabel objects, \c nameLabel and \c addressLabel, as well
96     as two input fields, a QLineEdit object, \c nameLine, and a QTextEdit
97     object, \c addressText, to enable the user to enter a contact's name and
98     address. The widgets used and their positions are shown in the figure
99     below.
100
101     \image addressbook-tutorial-part1-labeled-screenshot.png
102
103     There are three files used to implement this address book:
104
105     \list
106         \li \c{addressbook.h} - the definition file for the \c AddressBook
107             class,
108         \li \c{addressbook.cpp} - the implementation file for the
109             \c AddressBook class, and
110         \li \c{main.cpp} - the file containing a \c main() function, with
111             an instance of \c AddressBook.
112     \endlist
113
114     \section1 Qt Programming - Subclassing
115
116     When writing Qt programs, we usually subclass Qt objects to add
117     functionality. This is one of the essential concepts behind creating
118     custom widgets or collections of standard widgets. Subclassing to
119     extend or change the behavior of a widget has the following advantages:
120
121     \list
122     \li We can write implementations of virtual or pure virtual functions to
123     obtain exactly what we need, falling back on the base class's implementation
124     when necessary.
125     \li It allows us to encapsulate parts of the user interface within a class,
126     so that the other parts of the application don't need to know about the
127     individual widgets in the user interface.
128     \li The subclass can be used to create multiple custom widgets in the same
129     application or library, and the code for the subclass can be reused in other
130     projects.
131     \endlist
132
133     Since Qt does not provide a specific address book widget, we subclass a
134     standard Qt widget class and add features to it. The \c AddressBook class
135     we create in this tutorial can be reused in situations where a basic address
136     book widget is needed.
137
138     \section1 Defining the AddressBook Class
139
140     The \l{tutorials/addressbook/part1/addressbook.h}{\c addressbook.h} file is
141     used to define the \c AddressBook class.
142
143     We start by defining \c AddressBook as a QWidget subclass and declaring
144     a constructor. We also use the Q_OBJECT macro to indicate that the class
145     uses internationalization and Qt's signals and slots features, even
146     if we do not use all of these features at this stage.
147
148     \snippet tutorials/addressbook/part1/addressbook.h class definition
149
150     The class holds declarations of \c nameLine and \c addressText,
151     the private instances of QLineEdit and QTextEdit mentioned
152     earlier.  The data stored in \c nameLine and \c addressText will
153     be needed for many of the address book functions.
154
155     We don't include declarations of the QLabel objects we will use
156     because we will not need to reference them once they have been
157     created.  The way Qt tracks the ownership of objects is explained
158     in the next section.
159
160     The Q_OBJECT macro itself implements some of the more advanced features of Qt.
161     For now, it is useful to think of the Q_OBJECT macro as a shortcut which allows
162     us to use the \l{QObject::}{tr()} and \l{QObject::}{connect()} functions.
163
164     We have now completed the \c addressbook.h file and we move on to
165     implement the corresponding \c addressbook.cpp file.
166
167     \section1 Implementing the AddressBook Class
168
169     The constructor of \c AddressBook accepts a QWidget parameter, \a parent.
170     By convention, we pass this parameter to the base class's constructor.
171     This concept of ownership, where a parent can have one or more children,
172     is useful for grouping widgets in Qt. For example, if you delete a parent,
173     all of its children will be deleted as well.
174
175     \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
176
177     In this constructor, the QLabel objects \c nameLabel and \c
178     addressLabel are instantiated, as well as \c nameLine and \c
179     addressText. The \l{QObject::tr()}{tr()} function returns a
180     translated version of the string, if there is one
181     available. Otherwise it returns the string itself. This function
182     marks its QString parameter as one that should be translated into
183     other languages. It should be used wherever a translatable string
184     appears.
185
186     When programming with Qt, it is useful to know how layouts work.
187     Qt provides three main layout classes: QHBoxLayout, QVBoxLayout
188     and QGridLayout to handle the positioning of widgets.
189
190     \image addressbook-tutorial-part1-labeled-layout.png
191
192     We use a QGridLayout to position our labels and input fields in a
193     structured manner. QGridLayout divides the available space into a grid and
194     places widgets in the cells we specify with row and column numbers. The
195     diagram above shows the layout cells and the position of our widgets, and
196     we specify this arrangement using the following code:
197
198     \snippet tutorials/addressbook/part1/addressbook.cpp layout
199
200     Notice that \c addressLabel is positioned using Qt::AlignTop as an
201     additional argument. This is to make sure it is not vertically centered in
202     cell (1,0). For a basic overview on Qt Layouts, refer to the 
203     \l{Layout Management} documentation.
204
205     In order to install the layout object onto the widget, we have to invoke
206     the widget's \l{QWidget::setLayout()}{setLayout()} function:
207
208     \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
209
210     Lastly, we set the widget's title to "Simple Address Book".
211
212     \section1 Running the Application
213
214     A separate file, \c main.cpp, is used for the \c main() function. Within
215     this function, we instantiate a QApplication object, \c app. QApplication
216     is responsible for various application-wide resources, such as the default
217     font and cursor, and for running an event loop. Hence, there is always one
218     QApplication object in every GUI application using Qt.
219
220     \snippet tutorials/addressbook/part1/main.cpp main function
221
222     We construct a new \c AddressBook widget on the stack and invoke
223     its \l{QWidget::show()}{show()} function to display it.
224     However, the widget will not be shown until the application's event loop
225     is started. We start the event loop by calling the application's
226     \l{QApplication::}{exec()} function; the result returned by this function
227     is used as the return value from the \c main() function. At this point,
228     it becomes apparent why we instanciated \c AddressBook on the stack: It
229     will now go out of scope. Therefore, \c AddressBook and all its child widgets
230     will be deleted, thus preventing memory leaks.
231 */
232
233 /*!
234     \page tutorials-addressbook-part2.html
235
236     \example tutorials/addressbook/part2
237     \title Part 2 - Adding Addresses
238
239     The next step in creating the address book is to implement some
240     user interactions.
241
242     \image addressbook-tutorial-part2-add-contact.png
243
244     We will provide a push button that the user can click to add a new contact.
245     Also, some form of data structure is needed to store these contacts in an
246     organized way.
247
248     \section1 Defining the AddressBook Class
249
250     Now that we have the labels and input fields set up, we add push buttons to
251     complete the process of adding a contact. This means that our
252     \c addressbook.h file now has three QPushButton objects declared and three
253     corresponding public slots.
254
255     \snippet tutorials/addressbook/part2/addressbook.h slots
256
257     A slot is a function that responds to a particular signal. We will discuss
258     this concept in further detail when implementing the \c AddressBook class.
259     However, for an overview of Qt's signals and slots concept, you can refer
260     to the \l{Signals and Slots} document.
261
262     Three QPushButton objects (\c addButton, \c submitButton, and
263     \c cancelButton) are now included in our private variable declarations,
264     along with \c nameLine and \c addressText.
265
266     \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
267
268     We need a container to store our address book contacts, so that we can
269     traverse and display them. A QMap object, \c contacts, is used for this
270     purpose as it holds a key-value pair: the contact's name as the \e key,
271     and the contact's address as the \e{value}.
272
273     \snippet tutorials/addressbook/part2/addressbook.h remaining private variables
274
275     We also declare two private QString objects, \c oldName and \c oldAddress.
276     These objects are needed to hold the name and address of the contact that
277     was last displayed, before the user clicked \uicontrol Add. So, when the user clicks
278     \uicontrol Cancel, we can revert to displaying the details of the last contact.
279
280     \section1 Implementing the AddressBook Class
281
282     Within the constructor of \c AddressBook, we set the \c nameLine and
283     \c addressText to read-only, so that we can only display but not edit
284     existing contact details.
285
286     \dots
287     \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
288     \dots
289     \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
290
291     Then, we instantiate our push buttons: \c addButton, \c submitButton, and
292     \c cancelButton.
293
294     \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
295
296     The \c addButton is displayed by invoking the \l{QPushButton::show()}
297     {show()} function, while the \c submitButton and \c cancelButton are
298     hidden by invoking \l{QPushButton::hide()}{hide()}. These two push
299     buttons will only be displayed when the user clicks \uicontrol Add and this is
300     handled by the \c addContact() function discussed below.
301
302     \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
303
304     We connect the push buttons' \l{QPushButton::clicked()}{clicked()} signal
305     to their respective slots. The figure below illustrates this.
306
307     \image addressbook-tutorial-part2-signals-and-slots.png
308
309     Next, we arrange our push buttons neatly to the right of our address book
310     widget, using a QVBoxLayout to line them up vertically.
311
312     \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
313
314     The \l{QBoxLayout::addStretch()}{addStretch()} function is used to ensure
315     the push buttons are not evenly spaced, but arranged closer to the top of
316     the widget. The figure below shows the difference between using
317     \l{QBoxLayout::addStretch()}{addStretch()} and not using it.
318
319     \image addressbook-tutorial-part2-stretch-effects.png
320
321     We then add \c buttonLayout1 to \c mainLayout, using
322     \l{QGridLayout::addLayout()}{addLayout()}. This gives us nested layouts
323     as \c buttonLayout1 is now a child of \c mainLayout.
324
325     \snippet tutorials/addressbook/part2/addressbook.cpp grid layout
326
327     Our layout coordinates now look like this:
328
329     \image addressbook-tutorial-part2-labeled-layout.png
330
331     In the \c addContact() function, we store the last displayed contact
332     details in \c oldName and \c oldAddress. Then we clear these input
333     fields and turn off the read-only mode. The focus is set on \c nameLine
334     and we display \c submitButton and \c cancelButton.
335
336     \snippet tutorials/addressbook/part2/addressbook.cpp addContact
337
338     The \c submitContact() function can be divided into three parts:
339
340     \list 1
341     \li We extract the contact's details from \c nameLine and \c addressText
342     and store them in QString objects. We also validate to make sure that the
343     user did not click \uicontrol Submit with empty input fields; otherwise, a
344     QMessageBox is displayed to remind the user for a name and address.
345
346     \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
347
348     \li We then proceed to check if the contact already exists. If it does not
349     exist, we add the contact to \c contacts and we display a QMessageBox to
350     inform the user that the contact has been added.
351
352     \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
353
354     If the contact already exists, again, we display a QMessageBox to inform
355     the user about this, preventing the user from adding duplicate contacts.
356     Our \c contacts object is based on key-value pairs of name and address,
357     hence, we want to ensure that \e key is unique.
358
359     \li Once we have handled both cases mentioned above, we restore the push
360     buttons to their normal state with the following code:
361
362     \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
363
364     \endlist
365
366     The screenshot below shows the QMessageBox object we use to display
367     information messages to the user.
368
369     \image addressbook-tutorial-part2-add-successful.png
370
371     The \c cancel() function restores the last displayed contact details and
372     enables \c addButton, as well as hides \c submitButton and
373     \c cancelButton.
374
375     \snippet tutorials/addressbook/part2/addressbook.cpp cancel
376
377     The general idea behind adding a contact is to give the user the
378     flexibility to click \uicontrol Submit or \uicontrol Cancel at any time. The flowchart below
379     further explains this concept:
380
381     \image addressbook-tutorial-part2-add-flowchart.png
382 */
383
384 /*!
385     \page tutorials-addressbook-part3.html
386
387     \example tutorials/addressbook/part3
388     \title Part 3 - Navigating between Entries
389
390     The address book is now about half complete. We should add the
391     capability to navigate among the contacts, but first we must
392     decide what sort of a data structure we need for containing these
393     contacts.
394
395     In the previous section, we used a QMap of key-value pairs with
396     the contact's name as the \e key, and the contact's address as the
397     \e value. This works well for our case. However, in order to
398     navigate and display each entry, a little bit of enhancement is
399     needed.
400
401     We enhance the QMap by making it replicate a data structure similar to a
402     circularly-linked list, where all elements are connected, including the
403     first element and the last element. The figure below illustrates this data
404     structure.
405
406     \image addressbook-tutorial-part3-linkedlist.png
407
408     \section1 Defining the AddressBook Class
409
410     To add navigation functions to the address book, we must add two
411     more slots to the \c AddressBook class: \c next() and \c
412     previous() to the \c addressbook.h file:
413
414     \snippet tutorials/addressbook/part3/addressbook.h navigation functions
415
416     We also require another two QPushButton objects, so we declare \c nextButton
417     and \c previousButton as private variables:
418
419     \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
420
421     \section1 Implementing the AddressBook Class
422
423     In the \c AddressBook constructor in \c addressbook.cpp, we instantiate
424     \c nextButton and \c previousButton and disable them by default. This is
425     because navigation is only enabled when there is more than one contact
426     in the address book.
427
428     \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
429
430     We then connect these push buttons to their respective slots:
431
432     \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
433
434     The image below is the expected graphical user interface. 
435
436     \image addressbook-tutorial-part3-screenshot.png
437
438     We follow basic conventions for \c next() and \c previous() functions by
439     placing the \c nextButton on the right and the \c previousButton on the
440     left. In order to achieve this intuitive layout, we use QHBoxLayout to
441     place the widgets side-by-side:
442
443     \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
444
445     The QHBoxLayout object, \c buttonLayout2, is then added to \c mainLayout.
446
447     \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
448
449     The figure below shows the coordinates of the widgets in \c mainLayout.
450     \image addressbook-tutorial-part3-labeled-layout.png
451
452     Within our \c addContact() function, we have to disable these buttons so
453     that the user does not attempt to navigate while adding a contact.
454
455     \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
456
457     Also, in our \c submitContact() function, we enable the navigation
458     buttons, \c nextButton and \c previousButton, depending on the size
459     of \c contacts. As mentioned earlier, navigation is only enabled when
460     there is more than one contact in the address book. The following lines
461     of code demonstrates how to do this:
462
463     \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
464
465     We also include these lines of code in the \c cancel() function.
466
467     Recall that we intend to emulate a circularly-linked list with our QMap
468     object, \c contacts. So, in the \c next() function, we obtain an iterator
469     for \c contacts and then:
470
471     \list
472         \li If the iterator is not at the end of \c contacts, we increment it
473         by one.
474         \li If the iterator is at the end of \c contacts, we move it to the
475         beginning of \c contacts. This gives us the illusion that our QMap is
476         working like a circularly-linked list.
477     \endlist
478
479     \snippet tutorials/addressbook/part3/addressbook.cpp next() function
480
481     Once we have iterated to the correct object in \c contacts, we display
482     its contents on \c nameLine and \c addressText.
483
484     Similarly, for the \c previous() function, we obtain an iterator for
485     \c contacts and then:
486
487     \list
488         \li If the iterator is at the end of \c contacts, we clear the
489         display and return.
490         \li If the iterator is at the beginning of \c contacts, we move it to
491         the end.
492         \li We then decrement the iterator by one.
493     \endlist
494
495     \snippet tutorials/addressbook/part3/addressbook.cpp previous() function
496
497     Again, we display the contents of the current object in \c contacts.
498
499 */
500
501 /*!
502     \page tutorials-addressbook-part4.html
503
504     \example tutorials/addressbook/part4
505     \title Part 4 - Editing and Removing Addresses
506
507     Now we look at ways to modify the contents of contacts stored in
508     the address book.
509
510     \image addressbook-tutorial-screenshot.png
511
512     We now have an address book that not only holds contacts in an
513     organized manner, but also allows navigation. It would be
514     convenient to include edit and remove functions so that a
515     contact's details can be changed when needed. However, this
516     requires a little improvement, in the form of enums. We defined
517     two modes: \c{AddingMode} and \c{NavigationMode}, but they were
518     not defined as enum values. Instead, we enabled and disabled the
519     corresponding buttons manually, resulting in multiple lines of
520     repeated code.
521
522     Here we define the \c Mode enum with three different values:
523
524     \list
525         \li \c{NavigationMode},
526         \li \c{AddingMode}, and
527         \li \c{EditingMode}.
528     \endlist
529
530     \section1 Defining the AddressBook Class
531
532     The \c addressbook.h file is updated to contain the \c Mode enum:
533
534     \snippet tutorials/addressbook/part4/addressbook.h Mode enum
535
536     We also add two new slots, \c editContact() and \c removeContact(), to
537     our current list of public slots.
538
539     \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
540
541     In order to switch between modes, we introduce the \c updateInterface() function
542     to control the enabling and disabling of all QPushButton objects. We also
543     add two new push buttons, \c editButton and \c removeButton, for the edit
544     and remove functions mentioned earlier.
545
546     \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
547     \dots
548     \snippet tutorials/addressbook/part4/addressbook.h buttons declaration
549     \dots
550     \snippet tutorials/addressbook/part4/addressbook.h mode declaration
551
552     Lastly, we declare \c currentMode to keep track of the enum's current mode.
553
554     \section1 Implementing the AddressBook Class
555
556     We now implement the mode-changing features of the address
557     book. The \c editButton and \c removeButton are instantiated and
558     disabled by default. The address book starts with zero contacts
559     in memory.
560
561     \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
562
563     These buttons are then connected to their respective slots, \c editContact()
564     and \c removeContact(), and we add them to \c buttonLayout1.
565
566     \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
567     \dots
568     \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
569
570     The \c editContact() function stores the contact's old details in
571     \c oldName and \c oldAddress, before switching the mode to \c EditingMode.
572     In this mode, the \c submitButton and \c cancelButton are both enabled,
573     hence, the user can change the contact's details and click either button.
574
575     \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
576
577     The \c submitContact() function has been divided in two with an \c{if-else}
578     statement. We check \c currentMode to see if it's in \c AddingMode. If it is,
579     we proceed with our adding process.
580
581     \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
582     \dots
583     \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
584
585     Otherwise, we check to see if \c currentMode is in \c EditingMode. If it
586     is, we compare \c oldName with \c name. If the name has changed, we remove
587     the old contact from \c contacts and insert the newly updated contact.
588
589     \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
590
591     If only the address has changed (i.e., \c oldAddress is not the same as \c address),
592     we update the contact's address. Lastly, we set \c currentMode to
593     \c NavigationMode. This is an important step as it re-enables all the
594     disabled push buttons.
595
596     To remove a contact from the address book, we implement the
597     \c removeContact() function. This function checks to see if the contact
598     exists in \c contacts.
599
600     \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
601
602     If it does, we display a QMessageBox, to confirm the removal with the
603     user. Once the user has confirmed, we call \c previous() to ensure that the
604     user interface shows another contact, and we remove the contact using \l{QMap}'s
605     \l{QMap::remove()}{remove()} function. As a courtesy, we display a QMessageBox
606     to inform the user. Both the message boxes used in this function are shown below:
607
608     \image addressbook-tutorial-part4-remove.png
609
610     \section2 Updating the User Interface
611
612     We mentioned the \c updateInterface() function earlier as a means to
613     enable and disable the push buttons depending on the current mode.
614     The function updates the current mode according to the \c mode argument
615     passed to it, assigning it to \c currentMode before checking its value.
616
617     Each of the push buttons is then enabled or disabled, depending on the
618     current mode. The code for \c AddingMode and \c EditingMode is shown below:
619
620     \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
621
622     For \c NavigationMode, however, we include conditions within the parameters
623     of the QPushButton::setEnabled() function. This is to ensure that
624     \c editButton and \c removeButton are enabled when there is at least one
625     contact in the address book; \c nextButton and \c previousButton are only
626     enabled when there is more than one contact in the address book.
627
628     \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
629
630     By setting the mode and updating the user interface in the same
631     function, we avoid the possibility of the user interface getting
632     out of sync with the internal state of the application.
633   */
634
635 /*!
636     \page tutorials-addressbook-part5.html
637
638     \example tutorials/addressbook/part5
639     \title Part 5 - Adding a Find Function
640
641     Here we look at ways to locate contacts and addresses in the
642     address book.
643
644     \image addressbook-tutorial-part5-screenshot.png
645
646     As we add contacts to our address book, it becomes tedious to
647     navigate the list with the \e Next and \e Previous buttons. A \e
648     Find function would be more efficient.  The screenshot above shows
649     the \e Find button and its position on the panel of buttons.
650
651     When the user clicks on the \e Find button, it is useful to
652     display a dialog that prompts for a contact's name. Qt provides
653     QDialog, which we subclass here to implement a \c FindDialog
654     class.
655
656     \section1 Defining the FindDialog Class
657
658     \image addressbook-tutorial-part5-finddialog.png
659
660     In order to subclass QDialog, we first include the header for QDialog in
661     the \c finddialog.h file. Also, we use forward declaration to declare
662     QLineEdit and QPushButton since we will be using those widgets in our
663     dialog class.
664
665     As in our \c AddressBook class, the \c FindDialog class includes
666     the Q_OBJECT macro and its constructor is defined to accept a parent
667     QWidget, even though the dialog will be opened as a separate window.
668
669     \snippet tutorials/addressbook/part5/finddialog.h FindDialog header
670
671     We define a public function, \c getFindText(), to be used by classes that
672     instantiate \c FindDialog. This function allows these classes to obtain the
673     search string entered by the user. A public slot, \c findClicked(), is also
674     defined to handle the search string when the user clicks the \uicontrol Find
675     button.
676
677     Lastly, we define the private variables, \c findButton, \c lineEdit
678     and \c findText, corresponding to the \uicontrol Find button, the line edit
679     into which the user types the search string, and an internal string
680     used to store the search string for later use.
681
682     \section1 Implementing the FindDialog Class
683
684     Within the constructor of \c FindDialog, we set up the private variables,
685     \c lineEdit, \c findButton and \c findText. We use a QHBoxLayout to
686     position the widgets.
687
688     \snippet tutorials/addressbook/part5/finddialog.cpp constructor
689
690     We set the layout and window title, as well as connect the signals to their
691     respective slots. Notice that \c{findButton}'s \l{QPushButton::clicked()}
692     {clicked()} signal is connected to to \c findClicked() and
693     \l{QDialog::accept()}{accept()}. The \l{QDialog::accept()}{accept()} slot
694     provided by QDialog hides the dialog and sets the result code to
695     \l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s
696     \c findContact() function know when the \c FindDialog object has been
697     closed. We will explain this logic in further detail when discussing the
698     \c findContact() function.
699
700     \image addressbook-tutorial-part5-signals-and-slots.png
701
702     In \c findClicked(), we validate \c lineEdit to ensure that the user
703     did not click the \uicontrol Find button without entering a contact's name. Then, we set
704     \c findText to the search string, extracted from \c lineEdit. After that,
705     we clear the contents of \c lineEdit and hide the dialog.
706
707     \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
708
709     The \c findText variable has a public getter function, \c getFindText(),
710     associated with it. Since we only ever set \c findText directly in both the
711     constructor and in the \c findClicked() function, we do not create a
712     setter function to accompany \c getFindText().
713     Because \c getFindText() is public, classes instantiating and using
714     \c FindDialog can always access the search string that the user has
715     entered and accepted.
716
717     \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
718
719     \section1 Defining the AddressBook Class
720
721     To ensure we can use \c FindDialog from within our \c AddressBook class, we
722     include \c finddialog.h in the \c addressbook.h file.
723
724     \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
725
726     So far, all our address book features have a QPushButton and a
727     corresponding slot. Similarly, for the \uicontrol Find feature we have
728     \c findButton and \c findContact().
729
730     The \c findButton is declared as a private variable and the
731     \c findContact() function is declared as a public slot.
732
733     \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
734     \dots
735     \snippet tutorials/addressbook/part5/addressbook.h findButton declaration
736
737     Lastly, we declare the private variable, \c dialog, which we will use to
738     refer to an instance of \c FindDialog.
739
740     \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
741
742     Once we have instantiated a dialog, we will want to use it more than once;
743     using a private variable allows us to refer to it from more than one place
744     in the class.
745
746     \section1 Implementing the AddressBook Class
747
748     Within the \c AddressBook class's constructor, we instantiate our private
749     objects, \c findButton and \c findDialog:
750
751     \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
752     \dots
753     \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
754
755     Next, we connect the \c{findButton}'s
756     \l{QPushButton::clicked()}{clicked()} signal to \c findContact().
757
758     \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
759
760     Now all that is left is the code for our \c findContact() function:
761
762     \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
763
764     We start out by displaying the \c FindDialog instance, \c dialog. This is
765     when the user enters a contact name to look up. Once the user clicks
766     the dialog's \c findButton, the dialog is hidden and the result code is
767     set to QDialog::Accepted. This ensures that
768     our \c if statement is always true.
769
770     We then proceed to extract the search string, which in this case is
771     \c contactName, using \c{FindDialog}'s \c getFindText() function. If the
772     contact exists in our address book, we display it immediately. Otherwise,
773     we display the QMessageBox shown below to indicate that their search
774     failed.
775
776     \image addressbook-tutorial-part5-notfound.png
777 */
778
779 /*!
780     \page tutorials-addressbook-part6.html
781
782     \example tutorials/addressbook/part6
783     \title Part 6 - Loading and Saving
784
785     This part covers the Qt file handling features we use to write
786     loading and saving routines for the address book.
787
788     \image addressbook-tutorial-part6-screenshot.png
789
790     Although browsing and searching the contact list are useful
791     features, our address book is not complete until we can save
792     existing contacts and load them again at a later time.
793
794     Qt provides a number of classes for \l{Input/Output and Networking}
795     {input and output}, but we have chosen to use two which are simple to use
796     in combination: QFile and QDataStream.
797
798     A QFile object represents a file on disk that can be read from and written
799     to. QFile is a subclass of the more general QIODevice class which
800     represents many different kinds of devices.
801
802     A QDataStream object is used to serialize binary data so that it can be
803     stored in a QIODevice and retrieved again later. Reading from a QIODevice
804     and writing to it is as simple as opening the stream - with the respective
805     device as a parameter - and reading from or writing to it.
806
807
808     \section1 Defining the AddressBook Class
809
810     We declare two public slots, \c saveToFile() and \c loadFromFile(), as well
811     as two QPushButton objects, \c loadButton and \c saveButton.
812
813     \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
814     \dots
815     \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
816
817     \section1 Implementing the AddressBook Class
818
819     In our constructor, we instantiate \c loadButton and \c saveButton.
820     Ideally, it would be more user-friendly to set the push buttons' labels
821     to "Load contacts from a file" and "Save contacts to a file". However, due
822     to the size of our other push buttons, we set the labels to \uicontrol{Load...}
823     and \uicontrol{Save...}. Fortunately, Qt provides a simple way to set tooltips with
824     \l{QWidget::setToolTip()}{setToolTip()} and we use it in the following way
825     for our push buttons:
826
827     \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
828     \dots
829     \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
830
831     Although it is not shown here, just like the other features we implemented,
832     we add the push buttons to the layout panel on the right, \c buttonLayout1,
833     and we connect the push buttons' \l{QPushButton::clicked()}{clicked()}
834     signals to their respective slots.
835
836     For the saving feature, we first obtain \c fileName using
837     QFileDialog::getSaveFileName(). This is a convenience function provided
838     by QFileDialog, which pops up a modal file dialog and allows the user to
839     enter a file name or select any existing \c{.abk} file. The \c{.abk} file
840     is our Address Book extension that we create when we save contacts.
841
842     \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
843
844     The file dialog that pops up is displayed in the screenshot below:
845
846     \image addressbook-tutorial-part6-save.png
847
848     If \c fileName is not empty, we create a QFile object, \c file, with
849     \c fileName. QFile works with QDataStream as QFile is a QIODevice.
850
851     Next, we attempt to open the file in \l{QIODevice::}{WriteOnly} mode.
852     If this is unsuccessful, we display a QMessageBox to inform the user.
853
854     \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
855
856     Otherwise, we instantiate a QDataStream object, \c out, to write the open
857     file. QDataStream requires that the same version of the stream is used
858     for reading and writing. We ensure that this is the case by setting the
859     version used to the \l{QDataStream::Qt_4_5}{version introduced with Qt 4.5}
860     before serializing the data to \c file.
861
862     \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
863
864     For the loading feature, we also obtain \c fileName using
865     QFileDialog::getOpenFileName(). This function, the counterpart to
866     QFileDialog::getSaveFileName(), also pops up the modal file dialog and
867     allows the user to enter a file name or select any existing \c{.abk} file
868     to load it into the address book.
869
870     \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
871
872     On Windows, for example, this function pops up a native file dialog, as
873     shown in the following screenshot.
874
875     \image addressbook-tutorial-part6-load.png
876
877     If \c fileName is not empty, again, we use a QFile object, \c file, and
878     attempt to open it in \l{QIODevice::}{ReadOnly} mode. Similar to our
879     implementation of \c saveToFile(), if this attempt is unsuccessful, we
880     display a QMessageBox to inform the user.
881
882     \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
883
884     Otherwise, we instantiate a QDataStream object, \c in, set its version as
885     above and read the serialized data into the \c contacts data structure.
886     The \c contacts object is emptied before data is read into it to simplify
887     the file reading process. A more advanced method would be to read the
888     contacts into a temporary QMap object, and copy over non-duplicate contacts
889     into \c contacts.
890
891     \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
892
893     To display the contacts that have been read from the file, we must first
894     validate the data obtained to ensure that the file we read from actually
895     contains address book contacts. If it does, we display the first contact;
896     otherwise, we display a QMessageBox to inform the user about the problem.
897     Lastly, we update the interface to enable and disable the push buttons
898     accordingly.
899 */
900
901 /*!
902     \page tutorials-addressbook-part7.html
903
904     \example tutorials/addressbook/part7
905     \title Part 7 - Additional Features
906
907     This part covers some additional features that make the address
908     book more convenient for the frequent user.
909
910     \image addressbook-tutorial-part7-screenshot.png
911
912     Although our address book is useful in isolation, it would be
913     better if we could exchange contact data with other applications.
914     The vCard format is a popular file format that can be used for
915     this purpose.  Here we extend our address book client to allow
916     contacts to be exported to vCard \c{.vcf} files.
917
918     \section1 Defining the AddressBook Class
919
920     We add a QPushButton object, \c exportButton, and a corresponding public
921     slot, \c exportAsVCard() to our \c AddressBook class in the
922     \c addressbook.h file.
923
924     \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
925     \dots
926     \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
927
928     \section1 Implementing the AddressBook Class
929
930     Within the \c AddressBook constructor, we connect \c{exportButton}'s
931     \l{QPushButton::clicked()}{clicked()} signal to \c exportAsVCard().
932     We also add this button to our \c buttonLayout1, the layout responsible
933     for our panel of buttons on the right.
934
935     In our \c exportAsVCard() function, we start by extracting the contact's
936     name into \c name. We declare \c firstName, \c lastName and \c nameList.
937     Next, we look for the index of the first white space in \c name. If there
938     is a white space, we split the contact's name into \c firstName and
939     \c lastName. Then, we replace the space with an underscore ("_").
940     Alternately, if there is no white space, we assume that the contact only
941     has a first name.
942
943     \snippet tutorials/addressbook/part7/addressbook.cpp export function part1
944
945     As with the \c saveToFile() function, we open a file dialog to let the user
946     choose a location for the file. Using the file name chosen, we create an
947     instance of QFile to write to.
948
949     We attempt to open the file in \l{QIODevice::}{WriteOnly} mode. If this
950     process fails, we display a QMessageBox to inform the user about the
951     problem and return. Otherwise, we pass the file as a parameter to a
952     QTextStream object, \c out. Like QDataStream, the QTextStream class
953     provides functionality to read and write plain text to files. As a result,
954     the \c{.vcf} file generated can be opened for editing in a text editor.
955
956     \snippet tutorials/addressbook/part7/addressbook.cpp export function part2
957
958     We then write out a vCard file with the \c{BEGIN:VCARD} tag, followed by
959     the \c{VERSION:2.1} tag. The contact's name is written with the \c{N:}
960     tag. For the \c{FN:} tag, which fills in the "File as" property of a vCard,
961     we have to check whether the contact has a last name or not. If the contact
962     does, we use the details in \c nameList to fill it. Otherwise, we write
963     \c firstName only.
964
965     \snippet tutorials/addressbook/part7/addressbook.cpp export function part3
966
967     We proceed to write the contact's address. The semicolons in the address
968     are escaped with "\\", the newlines are replaced with semicolons, and the
969     commas are replaced with spaces. Lastly, we write the \c{ADR;HOME:;}
970     tag, followed by \c address and then the \c{END:VCARD} tag.
971
972     \snippet tutorials/addressbook/part7/addressbook.cpp export function part4
973
974     In the end, a QMessageBox is displayed to inform the user that the vCard
975     has been successfully exported.
976
977     \e{vCard is a trademark of the \l{http://www.imc.org}
978     {Internet Mail Consortium}}.
979 */