Trolltech | Documentation | Qt Quarterly | « ActiveX under Control | Forgot a tr()? »

Extension Dialogs
by Reginald Stadlbauer
An extension dialog is a dialog with two different appearances: a 'simple' appearance and a larger 'extended' appearance. Extension dialogs provide a means of hiding advanced options from casual and inexperienced users without restricting power users. Creating these dialogs using Qt and Qt Designer is straightforward.

An extension dialog is initially presented in its 'simple' form with a Details >>> button. When this button is clicked, the dialog expands to reveal more advanced options, and the button changes to Details <<<. When the button is clicked again, the dialog returns to its original form.

Handling the layout of an extension dialog by hand is not trivial. Fortunately, QDialog automatically takes care of the layout issues and provides QDialog::setExtension(), QDialog::showExtension() and QDialog::setOrientation() to support extension dialogs.

Creating the Dialog

To create an extension dialog in Qt Designer, first create the 'simple' dialog. Then create a separate form (using the QWidget template) that will be used as the extension part of the dialog. In our example code we will call the extension widget Extension and save it in extension.ui. The Details >>> button should be added to the 'simple' dialog. In our example code we will call this button detailsPushButton and connect its clicked() signal to a custom slot that we'll call toggleExtension().

We next use Object Explorer's Source tab to add both a variable, bool extensionShown, and an include (in implementation), extension.h, to the form.

If you use the subclassing approach to implement your dialog's functionality, add the following code to the constructor of the subclass. If you write your code using Qt Designer's code editor, add an init() slot to the form and put the code in there.

    extensionShown = FALSE;
    setExtension( new Extension( this ) );
    setOrientation( Vertical );

This initializes the state of the extension and sets the dialog's extension widget. The extension appears at the right of the simple dialog (making the dialog wider) if the orientation is horizontal, or it appears below (making the dialog taller) if the orientation is vertical.

We'll now implement the toggleExtension() slot (which is connected to the detailsPushButton):

    extensionShown = !extensionShown;
    showExtension( extensionShown );
    QString text = tr( "&Details " );
    text += extensionShown ? "<<<" : ">>>";
    detailsPushButton->setText( text );

This code inverts (toggles) the state of the extension. It then shows or hides the extension as appropriate, and updates the details button's text.

Using the Dialog

The difference between extension dialogs and conventional dialogs is that some the widgets (checkboxes, radio buttons, etc.) are in the extension. The screenshots used the following code:

    void MainForm::init()
    {
        sessions = FALSE;
        logging = FALSE;
        log_filename = QString::null;
        log_acts = TRUE;
        log_errs = TRUE;
    }

In the constructor (or init()) function we initialize the variables that the user can set through the extension dialog.

    void MainForm::optionsDlg()
    {
        MyDialog *dlg = new MyDialog( this, "dialog", TRUE );
        Extension *ext = (Extension*)dlg->extension(); 
        dlg->sessionsCheckBox->setChecked( sessions );
        dlg->loggingCheckBox->setChecked( logging );
        ext->logfileLineEdit->setText( log_filename );
        ext->logActionsCheckBox->setChecked( log_acts );
        ext->logErrorsCheckBox->setChecked( log_errs );
        if ( dlg->exec() ) {
            sessions = dlg->sessionsCheckBox->isChecked();
            logging = dlg->loggingCheckBox->isChecked();
            log_filename = ext->logfileLineEdit->text();
            log_acts = ext->logActionsCheckBox->isChecked();
            log_errs = ext->logErrorsCheckBox->isChecked();
        }
        delete dlg;
    }

When the the dialog is invoked we set the widgets in the dialog and the extension to reflect current values. If the user clicks "OK", we update our variables from the widgets. Easy!

Qt Casting

In the code shown earlier, we used an unchecked cast for the sake of clarity. The standard C++ cast looks like this:

    Extension *ext = dynamic_cast<Extension*>(dlg->extension());
    if ( !ext ) 
        return;

Some compilers don't support dynamic_cast, so we provide a portable equivalent for QObjects:

    Extension *ext = (Extension*)dlg->extension()->qt_cast("Extension");
    if ( !ext ) 
        return;

This document is licensed under the Creative Commons Attribution-Share Alike 2.5 license.

Copyright © 2002 Trolltech. Trademarks Forgot a tr()? »