Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions |

# Walkthrough: A Tiny Editor Illustrating QActionGroup

In the following we will step through a very rudimental editor program that shows one of the most common uses of the QActionGroup class: how to combine several toggle actions in a way that allows one-of-many choices.

If you're not yet familiar with the concept of actions, please refer to the Simple Application Walkthrough featuring QAction.

## A tiny main program

        #include <qapplication.h>
        #include "editor.h"

        int main( int argc, char ** argv)
        {
            QApplication app( argc, argv );
            Editor editor;
            editor.setCaption( "Qt Example - Actiongroup" );
            app.setMainWidget( &editor );
            editor.show();
            return app.exec();
        }

This tiny editor is a very small program. It might be unusual for an editor but it does not even provide the possibility to open a file given as a commandline argument. The reason for this is simple: It has nothing to to with QActionGroups.

The crucial point in the above main() is that we make editor, an object constructed from a self-written class Editor, the main widget in our application. This class is defined in editor.h.

When you read through the code and happen to be unsure about something: The Simple Application Walkthrough explains the elements of a typical Qt main program in detail.

## The interface of the Editor class

Before implementing the Editor class we should think about what it is supposed to do. Fortunately Qt provides a full-featured rich text editor class, QTextEdit. The only thing left for us is to give it a user interface.

        #include <qmainwindow.h>
        class QTextEdit;
        class QAction;

        class Editor : public QMainWindow
        {
            Q_OBJECT

        public:
            Editor();

        private slots:
            void setFontColor( QAction * );

        private:
            QTextEdit * editor;
            QAction * setRedFont;
        };

As we look for a means to implement one-of-many choices, a nice example would involve two buttons that make the user change the font color: If he or she invokes the setRedFont action the font color changes from default black to red.

To do this color change we need a slot, setFontColor() that takes care about the signal the action emits.

The Editor class itself is derived from QMainWindow. Only the constructor might be called from outside the class.

## Action!

        #include "editor.h"

        #include <qtextedit.h>
        #include <qmenubar.h>
        #include <qpopupmenu.h>
        #include <qtoolbar.h>
        #include <qaction.h>

It's not that much that we need for our tiny editor: QTextEdit, QMenuBar, QToolBar, QPopupMenu and last but not least QAction and QActionGroup from qaction.h.

        Editor::Editor()
            : QMainWindow( 0, "main window")
        {
            QActionGroup * colors = new QActionGroup( this, "colors", TRUE );

If one of the buttons is on, the other one must be off. The easiest way to to this is to create an action group, colors, that controls this exclusive behaviour. This is done by setting the third argument of the QActionGroup constructor to TRUE (we could omit it because it's the default). As simple as this we get an exclusive action group that will look after its member actions and switch off all other toggle actions except the one that is on.

            QAction * setBlackFont = new QAction( "black", QPixmap( (const char**)black_xpm ),
                                                  "Font color: black", CTRL+Key_B,
                                                  colors, "blackfontcolor", TRUE );

Then we create our first action, the one that sets the font color back to default black. It is called setBlackFont and is equipped with a descriptive QAction::text() reading black, a QAction::menuText() reading Font color: black, a QAction::iconSet() derived from the pixmap black_xpm and ALT+B as keyboard accelerator.

The last argument of the action constructor, TRUE, is responsible for making setBlackFont a toggle action that can be switched on or off. Most importantly setBlackFont becomes a member of the colors action group at creation time: colors is defined to be its parent.

            setRedFont = new QAction( "red", QPixmap( (const char**)red_xpm ), "Font color: red",
                                      CTRL+Key_R, colors, "redfontcolor", TRUE );

The same way we create the other toggle action, setRedFont, as a child of colors.

Whenever one of the two members of the colors group emits the QAction::toggled() signal the QActionGroup is notified internally and emits the QActionGroup::selected() signal in turn. QActionGroup::selected() carries the action that caused the signal as its argument.

All we have to do now is to connect this signal to a slot that changes the font color to red or black depending on the toggled action:

            QObject::connect( colors, SIGNAL( selected( QAction * ) ),
                              this, SLOT( setFontColor( QAction * ) ) );

This is the entire trick. Thus let's recall what we have done so far: We created two toggle actions, setRedFont and setBlackFont. Because they are children of an exclusive QActionGroup named colors it is impossible for the user to type red and black at the same time: Whenever he or she invokes one of the actions the other one changes state to off, colors emits a QActionGroup::selected() signal and the setFontColor() slot takes care of it.

All we have to do now is to add our two actions to the Editor window.

            QToolBar * toolbar = new QToolBar( this, "toolbar" );

First we create a tool bar.

            colors->addTo( toolbar );

But instead of adding each action manually we simply add their parent action group to toolbar and are done. colors makes sure that setBlackFont and setRedFont find themselves presented in the tool bar: setBlackFont as a tool button decorated with the black_xpm pixmap on the left, setRedFont (because it was added to colors later) to its right.

            QPopupMenu * font = new QPopupMenu( this );
            menuBar()->insertItem( "&Font", font );

Next we create a popup menu and insert it into the menu bar under the Font entry.

In a menu with this name a user would certainly expect to find more than just two entries to change the font color. You might want to add other font related actions in the future, and therefore it would be nice to group setBlackFont and setRedFont in a submenu entirely dedicated to the purpose of changing font colors.

With an action group this is easy. We simply tell colors to group together all of its members in a single submenu:

            colors->setUsesDropDown( TRUE );

This however causes a problem: a submenu entry must have a menu text, and up to now we don't have any.

When we recall that action groups intrinsically are QActions themselves the solution becomes obvious:

            colors->setMenuText( "Font Color" );

We simply assign the menu text Font Color to colors.

The rest is business as usual:

            colors->addTo( font );

We add the new and improved QActionGroup as a submenu to the font popup menu.

            editor = new QTextEdit( this, "editor" );

Last but not least we create the heart of Editor, the rich text editor ...

            setCentralWidget( editor );

... and make it the central widget in our window.

        }

The only thing left to implement is the setFontColor slot that is responsible for changing the font color to red or black depending on which action was toggled on.

        void Editor::setFontColor( QAction * coloraction )
        {

As the QActionGroup::selected() signal carries the relevant action as its argument, the first thing we have to do is to preserve it in the coloraction variable for later use.

            if ( coloraction == setRedFont )
                editor->setColor( red );

If coloraction is the same as setRedFont we change the editor's font color to red.

            else
                editor->setColor( black );

Otherwise it is set to black.

        }

See also Step-by-step Examples.