Files
qt-creator/doc/addressbook-sdk.qdoc

933 lines
39 KiB
Plaintext
Raw Normal View History

/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
2009-06-16 17:26:44 +02:00
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** 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 either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** 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.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
2009-06-16 17:26:44 +02:00
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page tutorials-addressbook-sdk.html
\startpage {index.html}{Qt Reference Documentation}
\nextpage {examples/addressbook-sdk/part1}{Chapter 1}
\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.
\image addressbook-tutorial-screenshot.png
In the process, we will learn about some basic technologies provided by
Qt, such as:
\list
\o Widgets and layout managers
\o Container classes
\o Signals and slots
\o Input and output devices
\endlist
All these technologies will be introduced via the Qt Creator Integrated
Development Environment (IDE).
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
\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}
\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.
*/
/*!
\page tutorials-addressbook-sdk-part1.html
\contentspage {Address Book Tutorial}{Contents}
2009-06-10 11:25:51 +02:00
\nextpage {examples/addressbook-sdk/part2}{Chapter 2}
\example examples/addressbook-sdk/part1
\title Address Book 1 - Designing the User Interface
The first part of this tutorial covers the design of the basic graphical
user interface (GUI) we use for the Address Book application.
The first step to creating a GUI program is to design the user interface.
In this chapter, our goal is to set up the labels and input fields needed
to implement a basic address book application. The figure below is a
screenshot of our expected output.
\image addressbook-tutorial-part1-screenshot.png
We begin by launching Qt Creator and use it to generate a new project. To
do this, select \gui New from the \gui File menu. In the
\gui{New...} dialog, select \gui{Projects|Qt4 Gui Application}. For a step
by step guide on how to create a \gui Project with Qt Creator, refer to the
\l{Creating a Project in Qt Creator}. Ensure that you select QWidget as
your subclass and name it \c AddressBook.
Five files will be generated in this \gui{Project}:
\list
\o \c{addressbook.pro} - the project file,
\o \c{addressbook.h} - the definition file for the \c AddressBook
class,
\o \c{addressbook.cpp} - the implementation file for the
\c AddressBook class,
\o \c{main.cpp} - the file containing a \c main() function, with an
instance of \c AddressBook, and
\o \c{addressbook.ui} - the user interface file created with \QD.
\endlist
Now that we have all the files we need, let's move on to designing the user
interface.
\section1 Placing Widgets on The Form
In the \gui{Project Sidebar}, double-click on the \c{addressbook.ui} file.
The \QD plugin will be launched, allowing you to design your program's user
interface.
We require two \l{QLabel}s to label the input fields as well as a QLineEdit
and a QTextEdit for the input fields. So, drag those widgets from the
\gui{Widget Box} to your form. 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.
Next, we have to position the widgets properly, according to the screenshot
earlier. We 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 we specify with row and column numbers. The
diagram below shows the layout cells and the position of our widgets. Place
your widgets accordingly and save the form by choosing
\gui{File | Save} or using the \key{Ctrl+S} shortcut.
\image addressbook-tutorial-part1-labeled-screenshot.png
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
can try this out by pressing \key{Ctrl+Alt+R} now. To correct it, simply click
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.
2009-05-29 18:32:36 +02:00
2009-04-20 14:17:24 +02:00
\section1 The AddressBook Class
The \l{examples/addressbook-sdk/part1/addressbook.h}{\c addressbook.h} file
is used to define the \c AddressBook class.
2009-04-20 14:17:24 +02:00
Let's take a look at what is already provided for us by Qt Creator. The
\c AddressBook class has been defined as a QWidget subclass with a
constructor and destructor.The Q_OBJECT macro is used to indicate that this
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
\l{QObject::}{tr()} and \l{QObject::}{connect()} functions.
\snippet examples/addressbook-sdk/part1/addressbook.h class definition
2009-04-20 14:17:24 +02:00
Qt Creator's \gui{Project Wizard} provides us with the \c Ui object as a
way to access the widgets on our form.
2009-04-20 14:17:24 +02:00
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.
2009-04-20 14:17:24 +02:00
\snippet examples/addressbook-sdk/part1/addressbook.cpp class implementation
2009-04-20 14:17:24 +02:00
\section1 The \c{main()} Function
2009-04-20 14:17:24 +02:00
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
2009-04-20 15:35:28 +02:00
always one QApplication object in every GUI application using Qt.
2009-04-20 14:17:24 +02:00
\snippet examples/addressbook-sdk/part1/main.cpp main function
2009-06-17 19:01:36 +02:00
The code constructs a new \c AddressBook widget on the stack and
invokes its \l{QWidget::}{show()} function to display it.
However, the widget will not be shown until the application's event
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
To run your application with Qt Creator, simply click on the Play button
(image). A bare bones Address Book will be displayed. Click on the X button
to close it.
2009-04-20 16:42:58 +02:00
2009-04-20 15:35:28 +02:00
\section1 Qt Programming - Subclassing
When writing Qt programs, we usually subclass Qt objects to add
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
\o We can write implementations of virtual or pure virtual functions
to obtain exactly what we need, falling back on the base class's
implementation when necessary.
\o It allows us to encapsulate parts of the user interface within a
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
Since Qt does not provided a specific address book widget, we subclass a
standard Qt widget class and add features to it. The \c AddressBook class
we create in this tutorial can be reused in situations where a basic
address book is needed.
*/
2009-04-20 16:42:58 +02:00
2009-04-20 16:42:58 +02:00
/*!
\page tutorials-addressbook-sdk-part2.html
\previouspage Address Book 1 - Designing the User Interface
\contentspage {Address Book Tutorial}{Contents}
2009-06-10 11:25:51 +02:00
\nextpage {examples/addressbook-sdk/part3}{Chapter 3}
2009-04-20 16:42:58 +02:00
\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.
2009-06-11 17:26:15 +02:00
\image addressbook-tutorial-part2-add-contact.png
2009-04-20 16:42:58 +02:00
We 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.
\section1 Placing Widgets on The Form
2009-04-20 16:42:58 +02:00
We shall continue with the form we had from the last chapter; we have the
labels and input fields set up, but we need to add push buttons to complete
the process of adding a contact. So, we begin by breaking the existing
layouts: select \gui{Break Layout} from the context menu. You might have to
do a \gui{Select All} with \key{Ctrl+A} first.. Then, we add three push
buttons. Double-click on each of them to set their text to "Add", "Submit",
and "Cancel". We now require a vertical spacer to ensure that the push
buttons will be laid out neatly; drag one from the \gui{Widget Box}.
2009-05-29 18:32:36 +02:00
Next, lay out these three push buttons and the spacer vertically, by
selecting all three of them (using the \key{Ctrl + click}) and choosing
\gui{Lay out Vertically} from the context menu. Alternatively you can click
on the ... button or use the \key{Ctrl+L} shortcut. We use the spacer as we
do not want the buttons to be evenly spaced, but arranged closer to the top
of the widget. The figure below shows the difference between using the
spacer and not using it.
2009-06-11 17:26:15 +02:00
\image addressbook-tutorial-part2-stretch-effects.png
2009-05-29 18:32:36 +02:00
Select all the objects on the form (use \key{Ctrl+A}) and lay them out in a
grid. 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}.
2009-05-29 18:32:36 +02:00
The final design of the form is shown in the screenshot below:
## image
\section1 The AddressBook Class
To ensure that the Address Book reacts to user interaction, we need to
write slots for each push button that we added earlier. A slot is a
function that responds to a particular signal. We will discuss this
concept in further detail below. However, for an overview of Qt's signals
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}
file, we add the following code:
\snippet examples/addressbook-sdk/part2/addressbook.h slot definition
Next, we have to provide private members for the \c AddressBook class so
that we can access these widgets freely throughout the class.
\snippet examples/addressbook-sdk/part2/addressbook.h members1
The Qt types used for our private members, e.g., QPushButton, QLineEdit,
QTextEdit, etc., need to be included with the \c include directive, as
shown below:
\snippet examples/addressbook-sdk/part2/addressbook.h include
\note The names, e.g., \c addButton etc., correspond to the name of the
actual object. You can modify them by double-clicking on their names within
\QD's \gui{Object Inspector}.
2009-05-29 18:32:36 +02:00
We need a container to store our address book contacts, so that we can
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.
2009-04-20 16:42:58 +02:00
\snippet examples/addressbook-sdk/part2/addressbook.h members2
We also declare two private QString objects, \c oldName and \c oldAddress.
These objects are needed to hold the name and address of hte contact that
was last displayed, before the user clicked \gui Add. So, when the user
clicks \gui Cancel, we can revert to displaying the details of the last
contact.
Let's move on to implementing the slots we defined earlier. Within the
constructor of \c AddressBook, we extract the widgets from the form using
the \c ui object by pointing our private members to them.
\snippet examples/addressbook-sdk/part2/addressbook.cpp extract objects
Then we set \c nameLine and \c addressText to read-only, so that we can
only display but not edit existing contact details. We also hide
\c submitButton and \c cancelButton as they will only be be displayed
when the user clicks \gui Add, and this is handled by the \c addContact()
function discussed below.
\snippet examples/addressbook-sdk/part2/addressbook.cpp signal slot
We connect the push buttons' \l{QAbstractButton::}{clicked()} signal to
their respective slots. The figure below illustrates this.
2009-06-11 17:26:15 +02:00
\image addressbook-tutorial-part2-signals-and-slots.png
Finally, we set the window title to "Simple Address Book" using the
\l{QWidget::}{setWindowTitle()} function.
\snippet examples/addressbook-sdk/part2/addressbook.cpp window title
\section2 The \c{addContact()} Function
In this function, we begin by storing the last displayed contact details
in \c oldName and \c oldAddress. Then we clear these input fields and turn
off the read-only mode. The focus is set on \c nameLine and we display
\c submitButton and \c cancelButton; but we disable \c addButton.
\snippet examples/addressbook-sdk/part2/addressbook.cpp addContact
\section2 The \c{submitContact()} Function
This function can be divided into three parts:
\list 1
\o We extract the contact's detail from \c nameLine and \c addressText
and store them in QString objects. We also validate to ensure that
the user did not click \gui Submit with empty input fields;
otherwise, a QMessageBox is displayed to remind the user for a name
and address.
\snippet examples/addressbook-sdk/part2/addressbook.cpp submitContact part1
\o We then proceed to check if the contact already exists. If it does
not exist, we add the contact to \c contacts and we display a
QMessageBox to inform the user about this, preventing the user from
adding duplicate contacts. Our \c contacts object is based on
key-value pairs or name and address, hence, we want to ensure that
\e key is unique.
\snippet examples/addressbook-sdk/part2/addressbook.cpp submitContact part2
\o Once we have handled both cases mentioned above, we restore the
push buttons to their normal state with the following code:
\snippet examples/addressbook-sdk/part2/addressbook.cpp submitContact part3
\endlist
The screenshot below shows the QMessageBox object we use to display
information messages to the user.
2009-06-11 17:52:05 +02:00
\image addressbook-tutorial-part2-add-successful.png
\section2 The \c{cancel()} Function
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
The general idea behind adding a contact is to give the user the
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.
2009-04-20 16:42:58 +02:00
*/
/*!
\page tutorials-addressbook-sdk-part3.html
\previouspage Address Book 2 - Adding Addresses
\contentspage {Address Book Tutorial}{Contents}
2009-06-10 11:25:51 +02:00
\nextpage {examples/addressbook-sdk/part4}{Chapter 4}
\example examples/addressbook-sdk/part3
2009-06-10 16:24:35 +02:00
\title Address Book 3 - Navigating between Entries
The address book application is now half complete. We need to add some
functions to navigate between contacts. But first, we have to decide what
sort of a data structure we would like to use to hold these contacts.
In Chapter 2, we used a QMap of key-value pairs with the contact's name as
the \e key, and the contact's address as the \e value. This works well for
our case. However, in order to navigate and display each entry, a little
bit of enhancement is needed.
We enhance the QMap by making it replicate a data structure similar to a
circularly-linked list, where all elements are connected, including the
first element and the last element. The figure below illustrates this data
structure;
\image addressbook-tutorial-part3-linkedlist.png
\section1 Placing Widgets on The Form
So far, our application allows us to add new contacts. However, we also
need to traverse the existing contacts. To do so, we add two push buttons
at the bottom of our application and name them: \gui Next and
\gui Previous. The buttons' \c objectName should be \c nextButton and
\c previousButton, respectively. Then, we break our top level layout.
Simply right-click on \c AddressBook in the \gui{Object Inspector} and
then select \gui{Lay out|Break Layout}. Place the \gui Next and
\gui Previous buttons in a horizontal layout. Now drag and drop the buttons
together with their layout into the existing grid layout. The screenshot
below illustrates what you will see as the button layout approaches the
grid layout; drop it then.
\image addressbook-tutorial-part3-drop-in-gridlayout
Finally, set a top level layout for the widget again.
\note We follow basic conventions for \c next() and \c previous() functions
by placing the \c nextButton on the right and the \c previousButton on the
left.
\section1 The AddressBook Class
Let's move on to the code. In order to add navigation functions to the
address book application, we need to add two more slots to our
\c AddressBook class: \c next() and \c previous().
\snippet examples/addressbook-sdk/part3/addressbook.h slot definition
We also define two more QPushButton objects:
\snippet examples/addressbook-sdk/part3/addressbook.h members
In the \c AddressBook constructor, we extract the push buttons from the
\c ui object and disable them by default. This is because navigation is
only enabled when there is more than one contact in the address book.
\snippet examples/addressbook-sdk/part3/addressbook.cpp extract objects
Next, we connect the buttons to their respective slots:
\snippet examples/addressbook-sdk/part3/addressbook.cpp signal slot
The screenshot below is our expected graphical user interface. Notice that
it is getting closer to our final application.
2009-06-11 17:52:05 +02:00
\image addressbook-tutorial-part3-screenshot.png
Within our \c addContact() function, we have to disable the \gui Next and
\gui Previous buttons so that the user does not attempt to navigate while
adding a contact.
\snippet examples/addressbook-sdk/part3/addressbook.cpp disable navigation
Also, in our \c submitContact() function, we enable the navigation buttons,
depending on the size of \c contacts. Asmentioned earlier, navigation is
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
We also include these lins of code in the \c cancel() function.
Recall that we intend to emulate a circularly-linked list with our QMap
object, \c contacts. So in the \c next() function, we obtain an iterator
for \c contacts and then:
\list
\o If the iterator is not at the end of \c contacts, we increment it by
one.
\o If the iterator is at the end of \c contacts, we move it to the
beginning of \c contacts. This gives us the illusion that our QMap
is working like a circularly-linked list.
\endlist
\snippet examples/addressbook-sdk/part3/addressbook.cpp next
Once we have iterated to the current object in \c contacts, we display its
contents on \c nameLine and \c addressText.
Similarly, for the \c previous() function,we obtain an iterator for
\c contacts and then:
\list
2009-06-17 19:01:36 +02:00
\o If the iterator is at the end of \c contacts, we clear the display
and return.
\o If the iterator is at the beginning of \c contacts, we move it to
the end.
\o We then decrement the iterator by one.
\endlist
\snippet examples/addressbook-sdk/part3/addressbook.cpp previous
Again, we display the contents of the current object in \c contacts.
*/
/*!
\page tutorials-addressbook-sdk-part4.html
\previouspage Address Book 3 - Navigating between Entries
\contentspage {Address Book Tutorial}{Contents}
2009-06-10 11:25:51 +02:00
\nextpage {examples/addressbook-sdk/part5}{Chapter 5}
\example examples/addressbook-sdk/part4
2009-06-10 16:24:35 +02:00
\title Address Book 4 - Editing and Removing Addresses
In this chapter, we look at ways to modify the contents of contacts stored
in the address book application.
#screenshot
We now have an address book that not only holds contacts in an organized
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.
In our previous chapters, we had two modes: \c AddingMode and
\c NavigationMode - but they were not defined as enums. Instead, we enabled
and disabled the corresponding buttons manually, resulting in multiple
lines of repeated code.
In this chapter, we define the \c Mode enum with three different values:
\list
\o \c{NavigationMode},
\o \c{AddingMode}, and
\o \c{EditingMode}.
\endlist
\section1 Placing Widgets on The Form
To edit and remove contacts, we need two push buttons. Drag them and name
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
\section1 The AddressBook Class
We update the header file to contain the \c Mode enum:
\snippet examples/addressbook-sdk/part4/addressbook.h enum
We also add two new slots, \c editContact() and \c removeContact(), to our
current list of public slots.
\snippet examples/addressbook-sdk/part4/addressbook.h slot definition
In order to switch between modes, we introduce the \c updateInterface()
function to control the enabling and disabling of all push buttons. We also
add two new push buttons, \c editButton and \c removeButton, for the edit
and remove functions mentioned earlier.
\snippet examples/addressbook-sdk/part4/adressbook.h updateInterface
\dots
\snippet examples/addressbook-sdk/part4/addressbook.h members
Lastly, we declare \c currentMode to keep track of the enum's current mode.
\snippet examples/addressbook-sdk/part4/addressbook.h current mode
Let's begin by implementing the mode-changing features of the address book
application. The \c editButton and \c removeButton are extracted and
disabled by default, as the address book starts up with zero contacts in
memory.
\snippet examples/addressbook-sdk/part4/addressbook.cpp extract objects
These buttons are then connected to their respective slots,
\c editContact() and \c removeContact.
\snippet examples/addressbook-sdk/part4/addressbook.cpp signal slot
Now we look at the \c editContact() and \c removeContact() functions in
detail.
\section2 The \c{editContact()} Function
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
Since we will reuse the \c submitButton for both: adding a new contact and
editing an existing contact, we need to modify our existing
\c submitContact() function. So, we divide it in two with an \c{if-else}
statement.
First, we check \c currentMode to see if it is in \c AddingMode. If it is,
we proceed with our adding process.
\snippet examples/addressbook-sdk/part4/addressbook.cpp submitContact part1
\dots
\snippet examples/addressbook-sdk/part4/addressbook.cpp submitContact part2
Otherwise, we check to see if \c currentMode is in \c EditingMode. If it
is, we compare \c oldName with \c name. If the name has changed, we remove
the old contact from \c contacts and insert the newly updated contact.
\snippet examples/addressbook-sdk/part4/addressbook.cpp submitContact part3
If only the contact's address changed, i.e., \c oldAddress is not the same
as \c address, we update the contact's address. Lastly, we set
\c currentMode to \c NavigationMode. This is an important step as it
re-enables all the disabled push buttons.
To remove a contact from the address book, we implement the
\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
it does, we display a QMessageBox, to confirm the removal with the user.
Once the user has confirmed, we call \c previous() to ensure that the
user interface shows another contact, and we remove the contact using
\l{QMap}'s \l{QMap::}{remove()} function. As a courtesy, we display a
QMessageBox to inform the user. Both the message boxes used in this
function are shown below:
# image
\section2 The \c{updateInterface()} Function
We mentioned this function earlier as a means to enable and disable the
push buttons, depending on the current mode. The function updates the
current mode according to the \c mode argument passed to it, assigning it
to \c currentMode, before checking its value.\
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
For \c NavigationMode, however, we include conditions within the parameters
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
in the same function, we avoid the possibility of the user interface
getting "out of sync" with the internal state of the application.
To maintain consistency, we need to modify our \c addContact() and
\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
*/
/*!
\page tutorials-addressbook-sdk-part5.html
\previouspage Address Book 4 - Editing and Removing Addresses
\contentspage {Address Book Tutorial}{Contents}
2009-06-10 11:25:51 +02:00
\nextpage {examples/addressbook-sdk/part6}{Chapter 6}
\example examples/addressbook-sdk/part5
2009-06-10 16:24:35 +02:00
\title Address Book 5 - Adding a Find Function
In this chapter, we look at ways to locate contacts and addresses in the
address book application.
# image
As we keep adding contacts to our address book, it becomes tedious to
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.
When the user clicks on the \gui Find button, it is useful to display a
dialog that can prompt the user for a contact's name. Qt provides QDialog,
which we subclass in this chapter, to implement a FindDialog class.
\section1 Designing The FindDialog
#image
We begin by adding a new \c{.ui} file to our project. Right click on your
project and select \gui{Add New...}. In the \gui{New File} dialog, select
2009-06-10 11:25:51 +02:00
\gui{Qt Designer Form}. In the \gui{Qt Designer Form} dialog, select
\e{Dialog without buttons}. Name it \c{finddialog.ui} and add it to your
project. The \QD plugin within Qt Creator will now display your new form.
To replicate the screenshot above, we need a label, a line edit, and a push
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.
\section1 Implementing The FindDialog Class
Let's look at \c{FindDialog}'s header file. Here, we need to provide
private members for the class so that we can access the widgets freely
throughout the class.
\snippet examples/addressbook-sdk/part5/finddialog.h private members
We define a public function, \c getFindText(), to be used by classes that
instantiate \c FindDialog. This function allows the these classes to obtain
the search string entered by the user. A public slot, \c findClicked(), is
also defined to handle the search string when the user clicks the \gui Find
button.
\snippet examples/addressbook-sdk/part5/finddialog.h getFindText
\dots
\snippet examples/addressbook-sdk/part5/finddialog.h findClicked
Now, lets look at our constructor in the \c{finddialog.cpp} file. Here, we
set up the private variables, \c lineEdit, \c findButton, and \c findText.
\snippet examples/addressbook-sdk/part5/finddialog.cpp constructor
We connect our signals to their respective slots. Notice that
\c{findButton}'s \l{QPushButton:}{clicked()} signal is connected to
\c findClicked() and \l{QDialog::}{accept()}. The \l{QDialog::}{accept()}
slot provided by QDialog hides the dialog and sets the result code to
\l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s
\c findContact() function know when the \c FindDialog object has been
closed. We will explain this logic in further detail when discussing the
\c findContact() function.
\image addressbook-tutorial-part5-signals-and-slots.png
In \c findClicked(), we validate to ensure that the user did not click the
\gui Find button without entering a contact's name. Then, we set
\c findText to the search string, extracted from \c lineEdit. After that,
we clear the contents of \c lineEdit and hide the dialog.
\snippet examples/addressbook-sdk/part5/finddialog.cpp findClicked
The \c findText variable has a public getter function, \c getFindText(),
associated with it. Since we only ever set \c findText directly in both
the constructor and in hte \c findClicked() function, we do not create a
setter function to accompany \c getFindText(). Because \c getFindText() is
public, classes instantiating and using \c FindDialog can always access the
search string that the user has entered and accepted.
\snippet examples/addressbook-sdk/part5/finddialog.cpp getFindText
\section1 The AddressBook Class
To ensure that we can use \c FindDialog from within our \c AddressBook
class, we include \c finddialog.h in the \c addressbook.h file.
\snippet examples/addressbook-sdk/part5/addressbook.h include
So far, all our address book features have a QPushButton and a
corresponding slot. Similarly, for the \gui Find feature, we have
\c findButton and \c findContact().
\snippet examples/addressbook-sdk/part5/addressbook.h slot definition
\dots
\snippet examples/addressbook-sdk/part5/addressbook.h private members
Lastly, we declare the private variable, \c dialog, which we will use to
refer to an instance of \c FindDialog.
Once we have instantiated a dialog, we might want to use it more than once;
using a private variable allows us to refer to it from more than one place
in the class.
Within the \c AddressBook class's constructor, we insantiate our private
objects, \c findButton and \c dialog:
\snippet examples/addressbook-sdk/part5/addressbook.cpp private members
Next, we connect the \c{findButton}'s \l{QPushButton::}{clicked()} signal
to \c findContact().
\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
We start out by displaying the \c FindDialog instance, \c dialog. This is
when the user enters a contact name to look up. Once the user clicks the
dialog's \c findButton, the dialog is hidden and the result code is set to
QDialog::Accepted. THis ensures that our \c if statement is always true.
We then proceed to extract the search string, which in this case is
\c contactName, using \c{FindDialog}'s \c getFindText() function. If the
contact exists in our address book, we display it immediately. Otherwise,
we display the QMessageBox shown below to indicate that their search
failed.
# image
The concept behind finding a contact only applies for cases where we have
more than two contacts in our address book. Hence, we implement this
behavior by modifying our \c{Navigation Mode} within our
\c updateInterface() function, by only enabling the \gui Find button when
we have more than two contacts.
\snippet examples/addressbook-sdk/part5/addressbook.cpp enable
*/
/*!
\page tutorials-addressbook-sdk-part6.html
\previouspage Address Book 5 - Adding a Find Function
\contentspage {Address Book Tutorial}{Contents}
2009-06-10 11:25:51 +02:00
\nextpage {examples/addressbook-sdk/part7}{Chapter 7}
\example examples/addressbook-sdk/part6
2009-06-10 16:24:35 +02:00
\title Address Book 6 - Loading and Saving
This chapter covers the file handling features of Qt that we used to write
loading and saving routines for the address book application.
# screenshot
Although browsing and searching for contacts are useful features, our
address book is not really ready for use until we can save existing
contacts and load them again at a later time. Qt provides a number of
classes for \l{Input/Output and Networking}{input and output}, but we have
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
to. QFile isa subclass of the more general QIODevice class which represents
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.
\section1 Placing Widgets on The Form
\section1 The AddressBook Class
We declare two public slots, \c saveToFile() and \c loadFromFile(), as well
as two QPushButton objects, \c loadButton and \c saveButton.
# code
In our constructor, we instantiate \c loadButton and \c saveButton.
Ideally, it would be more user-friendly to set the push buttons' labels to
"Load contacts from a file" and "Save contacts to a file". However, due to
the size of our push buttons, we set the labels to \gui{Load...} and
\gui{Save...}. Fortunately, Qt provides a simple way to set tooltips with
\l{QWidget::}{setToolTip()} and we use it in the following way for our push
buttons:
# code
*/
/*!
\page tutorials-addressbook-sdk-part7.html
\previouspage Address Book 6 - Loading and Saving
\contentspage {Address Book Tutorial}{Contents}
\example examples/addressbook-sdk/part7
2009-06-10 16:24:35 +02:00
\title Address Book 7 - Additional Features
*/