10.1.1.  QActions, QToolbars, and QActionGroups

[ fromfile: menus.xml id: actions ]

Example 10.3. src/widgets/menus/study.h

[ . . . . ]
class Study : public QMainWindow {
    Q_OBJECT
 public:
    explicit Study(QWidget* parent=0);
 public slots:
    void actionEvent(QAction* act);
 private:
    QActionGroup* actionGroup;  1
    QToolBar* toolbar;          2

    QAction* useTheForce;
    QAction* useTheDarkSide;
    QAction* studyWithObiWan;
    QAction* studyWithYoda;
    QAction* studyWithEmperor;
    QAction* fightYoda;
    QAction* fightDarthVader;
    QAction* fightObiWan;
    QAction* fightEmperor;
protected:
    QAction* addChoice(QString name, QString text);

};
[ . . . . ]

1

For catching the signals

2

For displaying the actions as buttons


Example 10.4. src/widgets/menus/study.cpp

[ . . . . ]

Study::Study(QWidget* parent) : QMainWindow(parent) {
    actionGroup = new QActionGroup(this);
    actionGroup->setExclusive(false);
    statusBar();

    QWidget::setWindowTitle( "to become a jedi, you wish?"); 1

    QMenu* useMenu = new QMenu("&Use", this);
    QMenu* studyMenu = new QMenu("&Study", this);
    QMenu* fightMenu = new QMenu("&Fight", this);

    useTheForce = addChoice("useTheForce", "Use The &Force");
    useTheForce->setStatusTip("This is the start of a journey...");
    useTheForce->setEnabled(true);
    useMenu->addAction(useTheForce);                         2
[ . . . . ]

    studyWithObiWan = addChoice("studyWithObiWan", "&Study With Obi Wan");
    studyMenu->addAction(studyWithObiWan);
    studyWithObiWan->setStatusTip("He will certainly open doors "
                                   "for you...");

    fightObiWan = addChoice("fightObiWan", "Fight &Obi Wan");
    fightMenu->addAction(fightObiWan);
    fightObiWan->setStatusTip("You'll learn some tricks from him "
                               "that way, for sure!");
[ . . . . ]

    QMainWindow::menuBar()->addMenu(useMenu);
    QMainWindow::menuBar()->addMenu(studyMenu);
    QMainWindow::menuBar()->addMenu(fightMenu);

    toolbar = new QToolBar("Choice ToolBar", this);          3
    toolbar->addActions(actionGroup->actions());

    QMainWindow::addToolBar(Qt::LeftToolBarArea, toolbar);


    QObject::connect(actionGroup, SIGNAL(triggered(QAction*)),
            this, SLOT(actionEvent(QAction*)));              4

    QWidget::move(300, 300);
    QWidget::resize(300, 300);
}

1

Some of the ClassName:: prefixes used here are not necessary, because the functions can be called on "this". The class names can be used to explicitly call a baser- version, or show the reader which version is called.

2

It's already in a QActionGroup, but we also add it to a QMenu.

3

This gives us visible buttons in a dockable widget for each of the QActions.

4

Instead of connecting each individual action's signal, perform one connect to an actionGroup that contains them all.


Example 10.5. src/widgets/menus/study.cpp

[ . . . . ]


// Factory function for creating QActions initialized in a uniform way
QAction* Study::addChoice(QString name, QString text) {
    QAction* retval = new QAction(text, this);
    retval->setObjectName(name);
    retval->setEnabled(false);
    retval->setCheckable(true);
    actionGroup->addAction(retval); 1
    return retval;
}

1

Add every action to a QActionGroup so we need only one signal connected to one slot.


Example 10.6. src/widgets/menus/study.cpp

[ . . . . ]

void Study::actionEvent(QAction* act) {
   QString name = act->objectName();
   QString msg = QString();

   if (act == useTheForce ) {
       studyWithObiWan->setEnabled(true);
       fightObiWan->setEnabled(true);
       useTheDarkSide->setEnabled(true);
   }
   if (act == useTheDarkSide) {
       studyWithYoda->setEnabled(false);
       fightYoda->setEnabled(true);
       studyWithEmperor->setEnabled(true);
       fightEmperor->setEnabled(true);
       fightDarthVader->setEnabled(true);
   }
   if (act == studyWithObiWan) {
       fightObiWan->setEnabled(true);
       fightDarthVader->setEnabled(true);
       studyWithYoda->setEnabled(true);
   }
[ . . . . ]

   if (act == fightObiWan ) {
       if (studyWithEmperor->isChecked()) {
            msg = "You are victorious!";
       }
       else {
           msg = "You lose.";
           act->setChecked(false);
           studyWithYoda->setEnabled(false);
       }
   }
[ . . . . ]

   if (msg != QString()) {
      QMessageBox::information(this, "Result", msg, "ok");
   }
}

Figure 10.2.  Checkable Actions in Menus and Toolbars

Checkable Actions in Menus and Toolbars