Home · All Namespaces · All Classes · Grouped Classes · Modules · Functions codeless banner

Image Viewer Tutorial: Part 4

Welcome back to the image viewer tutorial. In this part, the list screen will be enhanced with some actions and an input dialog will be created.

Enhancing the list screen

The rename action

The rename action will provide a way to rename a selected image. For that purpose, a new rename action has to be created in the list screen.

    void ListScreen::createActions()
    {
        ...
        _renameAction = new QAction("Rename", this);
        connect(_renameAction, SIGNAL(triggered()), this, SLOT(onRenameImage()));
        ...
    }

The rename action will trigger the onRenameImage() slot. The rename action should also be added to the options menu

    void ListScreen::createMenu()
    {
        ...
        menu->addAction(_renameAction);
        ...
    }

The onRenameImage slot needs to launch an input dialog. When the dialog is accepted, the image will be renamed. Qt Extended does not support the QInputDialog, so a custom input dialog should be created. This is fairly easy. Our input dialog derives from a QDialog.

    #ifndef INPUTDIALOG_H
    #define INPUTDIALOG_H

    #include <QDialog>
    #include <QLineEdit>

    class QkeyEvent;

    class InputDialog : public QDialog
    {
        Q_OBJECT
    public:
        InputDialog(QWidget *parent);
        void setText(const QString &text);
        QString text();
    private:
        QLineEdit* _edit;
    };

    #endif

The setText() method puts the name of the image into the dialog. The text() method will retrieve the new name for the image.

The dialog consists of only one widget: a QLineEdit, which is arranged in a QVBoxLayout. Using the setText() method, the text will be set on the QLineEdit. The text() method retrieves the text from the QLineEdit. There is currently no verification of the input. This feature could be added later.

    #include "inputdialog.h"

    #include <QVBoxLayout>
    #include <QKeyEvent>

    InputDialog::InputDialog(QWidget *parent)
    : QDialog(parent)
    {
        QVBoxLayout* layout = new QVBoxLayout(this);
        _edit = new QLineEdit(this);
        layout->addWidget(_edit);
        setLayout(layout);
    }

    void InputDialog::setText(const QString &text)
    {
        _edit->setText(text);
    }

    QString InputDialog::text()
    {
        return _edit->text();
    }

In the onRenameImage() method, the content object is first retrieved according to the selected row and the InputDialog() is created. Then the image name is set as the dialog text. The dialog is launched with the QtopiaApplication::execDialog() method. If the dialog is accepted, the execDialog() method returns a QDialog::Accepted and the new name can be retrieved from the dialog. The new name is set on the content and the changes are commited. The commit function must be called to commit the changes. At the end, the dialog is deleted. Storing the dialog for later usage could be another option. QtopiaApplication::execDialog(dlg) call is used to place the dialog on the bottom of the screen, just above the soft menubar, so it looks much more like a phone interface. (the Dialog.exec() method could have been used but it would have placed the dialog according to Qt dialog behaviour, i.e. on the center of the screen with a minimal size.

    void ListScreen::onRenameImage()
    {
        QContent c   = _cs->content(currentIndex().row());
        QString name = c.name();
        InputDialog *dlg = new InputDialog(this);
        dlg->setText(name);
        dlg->setWindowTitle("Rename Image:");
        int ans = QtopiaApplication::execDialog(dlg);
        if (ans == QDialog::Accepted) {
            QString newName = dlg->text();
            if (newName.isEmpty())
                return;
            c.setName(newName);
            c.commit();
        }
        delete dlg;
    }

To edit the content, the select key has to be pressed. As the dialog is in key navigation mode, "select" has to be pressed to select the QLineEdit and then "edit" to go into the edit mode. After finishing editing, "ok" must be pressed to go back to the navigation mode. Then, pressing back accepts the dialog. Pressing Cancel in the options menu will cancel the dialog.

Here the sequence:

This is quite complicated and can be made easier!

Enhancing the Rename Dialog

The Ok and Cancel behaviour of the dialog can not be achieved currently. This is due to the fact that the delete and cut/copy/paste functions must be supported with the softkeys. But a more user-friendly interface can be found...

The input dialog must be changed: the edit widget will be introducted as the focus proxy of the dialog. This means that when the dialog receives focus, it forwards the focus to the edit widget. By doing that, the edit widget does not have to be selected any more in order to go to the edit state.

In addition, the key events will be intercepted and if a Qt::Key_Select arrives (which is used to go out of the edit mode normally), the button will be accepted:

For the input dialog constructor:

    InputDialog::InputDialog(QWidget *parent)
    : QDialog(parent)
    {
        ...
        setFocusProxy(_edit);
        ...
    }

And to intercept the key events:

    void InputDialog::keyPressEvent(QKeyEvent *event)
    {
        if (event->key() == Qt::Key_Select) {
            accept();
        } else {
            QDialog::keyPressEvent(event);
        }
    }

Now, the list has to be refreshed in order to display the new name. In that purpose,a slot that populates the list must be created:

File: listscreen.h

    class ListScreen : public QListWidget
    {
        ...
    private slots:
        void updateList(QContentIdList a,QContent::ChangeType b);
        ...
    };

File: listscreen.cpp

    void ListScreen::updateList(QContentIdList a, QContent::ChangeType b)
    {
        populate();
    }

This slot has to be connected to the QContentSet::changed(...) method in the ListScreen constructor. By doing that, the list will be repopulated each time a change occurs in the QContentSet (item added, item renamed/updtated/, item deleted)

File: listscreen.cpp

    ListScreen::ListScreen(IViewer *viewer)
    : QListWidget(viewer), _viewer(viewer)
    {
        ...
        connect(_cs,SIGNAL(changed(QContentIdList,QContent::ChangeType)),
                this,SLOT(updateList(QContentIdList,QContent::ChangeType)));
        ...
    }

Now, every item in the list can be renamed. The next step is to provide a way to delete those items.

The delete action

A delete action needs to be added to the menu. This is the same procedure as seen before. The delete action should call a onDeleteImage() slot.

In the delete image slot, the content is retrieved by row. This time, a message box displays a question. If the yes option is selected, the content is removed via the Content::removeFiles() method. Again, calling commit() is mandatory to commit the changes.

    void ListScreen::onDeleteImage()
    {
        QContent c = _cs->content(currentIndex().row());
        QString file = c.file();
        int ans = QMessageBox::question(this, "Delete Image", file, QMessageBox::Yes, QMessageBox::No);
        if (ans == QMessageBox::No)
            return;
        c.removeFiles();
        c.commit();
    }

Time to compile and restart the application. Now there are two new options (rename and delete) that can be tried out.

Summary

This part talked about ways to implement a custom dialog and to change the default implementation in order to have a dialog behaving nicely. The use of the QMessageBox class and the use of the QContent class have been explained.

Prev|Top|Start Page|Next


Copyright © 2009 Trolltech Trademarks
Qt Extended 4.4.3