2009-04-02 10:41:35 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** 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)
|
2009-04-02 10:41:35 +02:00
|
|
|
**
|
|
|
|
|
** 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.
|
2009-04-02 10:41:35 +02:00
|
|
|
** $QT_END_LICENSE$
|
|
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\page tutorials-addressbook-sdk.html
|
|
|
|
|
|
|
|
|
|
\startpage {index.html}{Qt Reference Documentation}
|
2009-06-09 12:40:10 +02:00
|
|
|
\nextpage {examples/addressbook-sdk/part1}{Chapter 1}
|
2009-04-02 10:41:35 +02:00
|
|
|
|
|
|
|
|
\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.
|
|
|
|
|
|
2009-06-11 17:02:16 +02:00
|
|
|
\image addressbook-tutorial-screenshot.png
|
2009-04-02 10:41:35 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2009-05-25 15:43:40 +02:00
|
|
|
All these technologies will be introduced via the Qt Creator Integrated
|
|
|
|
|
Development Environment (IDE).
|
|
|
|
|
|
2009-04-02 10:41:35 +02:00
|
|
|
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
|
2009-04-15 17:28:04 +02:00
|
|
|
\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}
|
2009-04-02 10:41:35 +02:00
|
|
|
\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.
|
2009-06-18 12:55:18 +02:00
|
|
|
|
2009-04-02 10:41:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\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}
|
2009-04-15 17:28:04 +02:00
|
|
|
\example examples/addressbook-sdk/part1
|
2009-04-02 10:41:35 +02:00
|
|
|
\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
|
2009-05-25 15:43:40 +02:00
|
|
|
\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.
|
2009-04-02 10:41:35 +02:00
|
|
|
|
2009-05-25 15:43:40 +02:00
|
|
|
Five files will be generated in this \gui{Project}:
|
2009-04-02 10:41:35 +02:00
|
|
|
|
|
|
|
|
\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
|
|
|
|
|
|
2009-05-25 15:43:40 +02:00
|
|
|
Now that we have all the files we need, let's move on to designing the user
|
2009-04-02 10:41:35 +02:00
|
|
|
interface.
|
|
|
|
|
|
2009-06-02 15:21:20 +02:00
|
|
|
|
2009-07-01 16:47:37 +02:00
|
|
|
\section1 Placing Widgets on The Form
|
2009-04-02 10:41:35 +02:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2009-05-25 15:43:40 +02:00
|
|
|
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
|
2009-04-02 10:41:35 +02:00
|
|
|
\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
|
2009-06-02 15:19:21 +02:00
|
|
|
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.
|
2009-04-02 10:41:35 +02:00
|
|
|
|
|
|
|
|
\image addressbook-tutorial-part1-labeled-screenshot.png
|
|
|
|
|
|
2009-06-02 15:19:21 +02:00
|
|
|
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
|
2009-06-04 13:07:16 +02:00
|
|
|
can try this out by pressing \key{Ctrl+Alt+R} now. To correct it, simply click
|
2009-06-02 15:19:21 +02:00
|
|
|
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-15 17:28:04 +02:00
|
|
|
|
2009-04-20 14:17:24 +02:00
|
|
|
\section1 The AddressBook Class
|
2009-04-15 17:28:04 +02:00
|
|
|
|
|
|
|
|
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
|
2009-04-15 17:28:04 +02:00
|
|
|
\c AddressBook class has been defined as a QWidget subclass with a
|
2009-04-20 10:51:40 +02:00
|
|
|
constructor and destructor.The Q_OBJECT macro is used to indicate that this
|
2009-05-25 15:43:40 +02:00
|
|
|
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
|
2009-04-20 10:51:40 +02:00
|
|
|
\l{QObject::}{tr()} and \l{QObject::}{connect()} functions.
|
2009-04-15 17:28:04 +02:00
|
|
|
|
|
|
|
|
\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-15 17:28:04 +02:00
|
|
|
|
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-15 17:28:04 +02:00
|
|
|
|
2009-04-20 14:17:24 +02:00
|
|
|
\snippet examples/addressbook-sdk/part1/addressbook.cpp class implementation
|
2009-04-15 17:28:04 +02:00
|
|
|
|
2009-04-02 10:41:35 +02:00
|
|
|
|
2009-04-20 14:17:24 +02:00
|
|
|
\section1 The \c{main()} Function
|
2009-04-02 10:41:35 +02:00
|
|
|
|
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-02 10:41:35 +02:00
|
|
|
|
2009-04-20 14:17:24 +02:00
|
|
|
\snippet examples/addressbook-sdk/part1/main.cpp main function
|
2009-04-02 10:41:35 +02:00
|
|
|
|
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
|
2009-05-25 15:43:40 +02:00
|
|
|
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-02 10:41:35 +02:00
|
|
|
*/
|
2009-04-20 16:42:58 +02:00
|
|
|
|
2009-05-25 15:43:40 +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.
|
|
|
|
|
|
|
|
|
|
|
2009-07-01 16:47:37 +02:00
|
|
|
\section1 Placing Widgets on The Form
|
2009-04-20 16:42:58 +02:00
|
|
|
|
2009-06-03 10:50:04 +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
|
2009-06-04 14:25:12 +02:00
|
|
|
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
|
2009-06-02 15:19:21 +02:00
|
|
|
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
|
|
|
|
2009-06-02 17:42:27 +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
|
2009-06-04 13:07:16 +02:00
|
|
|
that we can access these widgets freely throughout the class.
|
2009-06-02 17:42:27 +02:00
|
|
|
|
2009-06-03 10:50:04 +02:00
|
|
|
\snippet examples/addressbook-sdk/part2/addressbook.h members1
|
|
|
|
|
|
2009-06-30 15:42:17 +02:00
|
|
|
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
|
|
|
|
|
|
2009-06-02 17:42:27 +02:00
|
|
|
\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
|
|
|
|
2009-06-02 17:42:27 +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
|
|
|
|
2009-06-03 10:50:04 +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
|
|
|
|
|
|
2009-06-03 11:11:43 +02:00
|
|
|
We connect the push buttons' \l{QAbstractButton::}{clicked()} signal to
|
|
|
|
|
their respective slots. The figure below illustrates this.
|
2009-06-03 10:50:04 +02:00
|
|
|
|
2009-06-11 17:26:15 +02:00
|
|
|
\image addressbook-tutorial-part2-signals-and-slots.png
|
2009-06-03 10:50:04 +02:00
|
|
|
|
2009-06-03 11:11:43 +02:00
|
|
|
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
|
|
|
|
|
|
2009-06-03 10:50:04 +02:00
|
|
|
\section2 The \c{addContact()} Function
|
|
|
|
|
|
2009-06-03 11:11:43 +02:00
|
|
|
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.
|
2009-06-03 10:50:04 +02:00
|
|
|
|
2009-06-03 11:11:43 +02:00
|
|
|
\snippet examples/addressbook-sdk/part2/addressbook.cpp addContact
|
2009-06-03 14:24:12 +02:00
|
|
|
|
|
|
|
|
\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
|
2009-06-03 14:24:12 +02:00
|
|
|
|
|
|
|
|
\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
|
|
|
*/
|
2009-06-03 17:00:30 +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}
|
2009-06-03 17:00:30 +02:00
|
|
|
\example examples/addressbook-sdk/part3
|
2009-06-10 16:24:35 +02:00
|
|
|
\title Address Book 3 - Navigating between Entries
|
2009-06-03 17:00:30 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
2009-07-01 16:47:37 +02:00
|
|
|
\section1 Placing Widgets on The Form
|
2009-06-03 17:00:30 +02:00
|
|
|
|
2009-06-04 14:25:12 +02:00
|
|
|
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
|
2009-06-05 12:07:34 +02:00
|
|
|
\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.
|
|
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
\image addressbook-tutorial-part3-drop-in-gridlayout
|
2009-06-05 12:07:34 +02:00
|
|
|
|
|
|
|
|
Finally, set a top level layout for the widget again.
|
2009-06-04 14:25:12 +02:00
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
\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.
|
|
|
|
|
|
2009-06-04 14:25:12 +02:00
|
|
|
|
2009-06-03 17:00:30 +02:00
|
|
|
\section1 The AddressBook Class
|
|
|
|
|
|
2009-06-05 12:07:34 +02:00
|
|
|
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
|
|
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
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.
|
2009-06-05 12:07:34 +02:00
|
|
|
|
|
|
|
|
\snippet examples/addressbook-sdk/part3/addressbook.cpp extract objects
|
|
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
Next, we connect the buttons to their respective slots:
|
2009-06-05 12:07:34 +02:00
|
|
|
|
|
|
|
|
\snippet examples/addressbook-sdk/part3/addressbook.cpp signal slot
|
|
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
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
|
|
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
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
|
2009-06-05 12:31:14 +02:00
|
|
|
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
|
2009-06-05 12:07:34 +02:00
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
\snippet examples/addressbook-sdk/part3/addressbook.cpp previous
|
2009-06-05 12:07:34 +02:00
|
|
|
|
2009-06-05 12:31:14 +02:00
|
|
|
Again, we display the contents of the current object in \c contacts.
|
2009-06-04 14:25:12 +02:00
|
|
|
|
2009-06-03 17:00:30 +02:00
|
|
|
*/
|
2009-06-05 16:25:31 +02:00
|
|
|
|
2009-06-24 16:36:58 +02:00
|
|
|
|
2009-06-05 16:25:31 +02:00
|
|
|
/*!
|
|
|
|
|
\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}
|
2009-06-05 16:25:31 +02:00
|
|
|
\example examples/addressbook-sdk/part4
|
2009-06-10 16:24:35 +02:00
|
|
|
\title Address Book 4 - Editing and Removing Addresses
|
2009-06-05 16:25:31 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2009-07-01 16:47:37 +02:00
|
|
|
\section1 Placing Widgets on The Form
|
2009-06-05 16:25:31 +02:00
|
|
|
|
2009-06-05 17:57:47 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
2009-06-05 16:25:31 +02:00
|
|
|
\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
|
|
|
|
|
|
2009-06-05 17:57:47 +02:00
|
|
|
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.
|
|
|
|
|
|
2009-06-08 16:02:34 +02:00
|
|
|
\snippet examples/addressbook-sdk/part4/addressbook.cpp extract objects
|
2009-06-05 17:57:47 +02:00
|
|
|
|
2009-06-08 16:02:34 +02:00
|
|
|
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.
|
2009-06-05 17:57:47 +02:00
|
|
|
|
2009-06-08 17:17:20 +02:00
|
|
|
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
|
2009-06-05 16:25:31 +02:00
|
|
|
|
2009-07-01 16:47:37 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
2009-06-05 16:25:31 +02:00
|
|
|
\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}
|
2009-06-05 16:25:31 +02:00
|
|
|
\example examples/addressbook-sdk/part5
|
2009-06-10 16:24:35 +02:00
|
|
|
\title Address Book 5 - Adding a Find Function
|
2009-06-05 16:25:31 +02:00
|
|
|
|
2009-06-08 17:35:08 +02:00
|
|
|
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.
|
|
|
|
|
|
2009-06-30 15:42:17 +02:00
|
|
|
|
2009-06-30 15:57:45 +02:00
|
|
|
\section1 Designing The FindDialog
|
2009-06-08 17:35:08 +02:00
|
|
|
|
|
|
|
|
#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
|
2009-06-08 17:35:08 +02:00
|
|
|
\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.
|
|
|
|
|
|
2009-06-30 15:42:17 +02:00
|
|
|
|
2009-06-30 15:57:45 +02:00
|
|
|
\section1 Implementing The FindDialog Class
|
2009-06-24 17:32:47 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2009-06-30 15:42:17 +02:00
|
|
|
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
|
2009-06-24 17:32:47 +02:00
|
|
|
|
2009-06-30 15:42:17 +02:00
|
|
|
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.
|
2009-06-24 17:32:47 +02:00
|
|
|
|
2009-06-30 15:42:17 +02:00
|
|
|
\snippet examples/addressbook-sdk/part5/finddialog.cpp findClicked
|
2009-06-30 15:57:45 +02:00
|
|
|
|
|
|
|
|
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
|
2009-06-30 16:57:56 +02:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2009-07-01 14:04:05 +02:00
|
|
|
\snippet examples/addressbook-sdk/part5/addressbook.h include
|
2009-06-30 16:57:56 +02:00
|
|
|
|
|
|
|
|
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().
|
|
|
|
|
|
2009-07-02 11:25:33 +02:00
|
|
|
\snippet examples/addressbook-sdk/part5/addressbook.h slot definition
|
2009-07-01 14:04:05 +02:00
|
|
|
\dots
|
2009-07-02 11:25:33 +02:00
|
|
|
\snippet examples/addressbook-sdk/part5/addressbook.h private members
|
2009-07-01 14:04:05 +02:00
|
|
|
|
|
|
|
|
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.
|
2009-06-30 16:57:56 +02:00
|
|
|
|
2009-07-01 14:04:05 +02:00
|
|
|
\snippet examples/addressbook-sdk/part5/addressbook.cpp enable
|
2009-06-30 16:57:56 +02:00
|
|
|
|
2009-06-24 16:36:58 +02:00
|
|
|
*/
|
|
|
|
|
|
2009-06-08 16:02:34 +02:00
|
|
|
|
2009-06-24 16:36:58 +02:00
|
|
|
/*!
|
2009-06-08 16:02:34 +02:00
|
|
|
\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}
|
2009-06-08 16:02:34 +02:00
|
|
|
\example examples/addressbook-sdk/part6
|
2009-06-10 16:24:35 +02:00
|
|
|
\title Address Book 6 - Loading and Saving
|
2009-06-08 16:02:34 +02:00
|
|
|
|
2009-07-01 16:47:37 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-06-24 16:36:58 +02:00
|
|
|
*/
|
|
|
|
|
|
2009-06-08 16:02:34 +02:00
|
|
|
|
2009-06-24 16:36:58 +02:00
|
|
|
/*!
|
2009-06-08 16:02:34 +02:00
|
|
|
\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
|
2009-06-08 16:02:34 +02:00
|
|
|
|
|
|
|
|
*/
|