|  | Home · Examples

# Address Book 5 - Adding a Find Function

[Previous: Address Book 4 - Editing and Removing Addresses][Address Book Tutorial][Next: Address Book 6 - Loading and Saving]

In this chapter, we look at ways to locate contacts and addresses in the address book application.

As we keep adding contacts to our address book application, it becomes tedious to navigate them with the Next and Previous buttons. In this case, a Find function would be more efficient in looking up contacts. The screenshot above shows the Find button and its position on the panel of buttons.

When the user clicks on the 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.

## Defining the FindDialog Class

In order to subclass QDialog, we first include the header for QDialog in the `finddialog.h` file. Also, we use forward declaration to declare QLineEdit and QPushButton since we will be using those widgets in our dialog class.

As in our `AddressBook` class, the `FindDialog` class includes the Q_OBJECT macro and its constructor is defined to accept a parent QWidget, even though the dialog will be opened as a separate window.

    #include <QDialog>

    QT_BEGIN_NAMESPACE
    class QLineEdit;
    class QPushButton;
    QT_END_NAMESPACE

    class FindDialog : public QDialog
    {
        Q_OBJECT

    public:
        FindDialog(QWidget *parent = 0);
        QString getFindText();

    public slots:
        void findClicked();

    private:
        QPushButton *findButton;
        QLineEdit *lineEdit;
        QString findText;
    };

We define a public function, `getFindText()` for use by classes that instantiate `FindDialog`, which allows them to obtain the text entered by the user. A public slot, `findClicked()`, is defined to handle the search string when the user clicks the Find button.

Lastly, we define the private variables, `findButton`, `lineEdit` and `findText`, corresponding to the Find button, the line edit into which the user types the search string, and an internal string used to store the search string for later use.

## Implementing the FindDialog Class

Within the constructor of `FindDialog`, we set up the private variables, `lineEdit`, `findButton` and `findText`. We use a QHBoxLayout to position the widgets.
The following code example is written in c++.

    FindDialog::FindDialog(QWidget *parent)
        : QDialog(parent)
    {
        QLabel *findLabel = new QLabel(tr("Enter the name of a contact:"));
        lineEdit = new QLineEdit;

        findButton = new QPushButton(tr("&Find"));
        findText = "";

        QHBoxLayout *layout = new QHBoxLayout;
        layout->addWidget(findLabel);
        layout->addWidget(lineEdit);
        layout->addWidget(findButton);

        setLayout(layout);
        setWindowTitle(tr("Find a Contact"));
        connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));
        connect(findButton, SIGNAL(clicked()), this, SLOT(accept()));
    }

We set the layout and window title, as well as connect the signals to their respective slots. Notice that `findButton`'s clicked() signal is connected to to `findClicked()` and accept(). The accept() slot provided by QDialog hides the dialog and sets the result code to Accepted. We use this function to help `AddressBook`'s `findContact()` function know when the `FindDialog` object has been closed. This will be further explained when discussing the `findContact()` function.
In `findClicked()`, we validate to ensure that the user did not click the Find button without entering a contact's name. Then, we set `findText` to the search string, extracted from `lineEdit`. After that, we clear the contents of `lineEdit` and hide the dialog.Error parsing snippet. The `findText` variable has a public getter function, `getFindText()`, associated with it. Since we only ever set `findText` directly in both the constructor and in the `findClicked()` function, we do not create a setter function to accompany `getFindText()`. Because `getFindText()` is public, classes instantiating and using `FindDialog` can always access the search string that the user has entered and accepted.Error parsing snippet.

## Defining the AddressBook Class

In ensure we can use `FindDialog` from within our `AddressBook` class, we include `finddialog.h` in the `addressbook.h` file.

    #include "finddialog.h"

So far, all our address book features have a QPushButton and a corresponding slot. Similarly, for the Find feature we have `findButton` and `findContact()`.

The `findButton` is declared as a private variable and the `findContact()` function is declared as a public slot.Error parsing snippet.... QPushButton *findButton; Lastly, we declare the private variable, `dialog`, which we will use to refer to an instance of `FindDialog`.

        FindDialog *dialog;

Once we have instantiated a dialog, we will 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.

## Implementing the AddressBook Class

Within the `AddressBook` class's constructor, we instantiate our private objects, `findButton` and `findDialog`:
The following code example is written in c++.

        findButton = new QPushButton(tr("&Find"));
        findButton->setEnabled(false);
    ...
        dialog = new FindDialog;

Next, we connect the `findButton`'s clicked() signal to `findContact()`.
The following code example is written in c++.

        connect(findButton, SIGNAL(clicked()), this, SLOT(findContact()));

Now all that is left is the code for our `findContact()` function:Error parsing snippet. We start out by displaying the `FindDialog` instance, `dialog`. This is when the user enters a contact name to look up. Once the user clicks the dialog's `findButton`, the dialog is hidden and the result code is set to QDialog::Accepted. This ensures that our `if` statement is always true.

We then proceed to extract the search string, which in this case is `contactName`, using `FindDialog`'s `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.