In this chapter we investigate adding the
command structure to the application framework we developed in
Chapter 12.
This consists of QAction objects that are
added to toolbars and menu bars, and that can provide keyboard
accelerators.
Actions
We first encountered the
QAction class in Chapter 10. To
recap briefly, QAction is a model of a
well-defined action that a user can perpetrate against your
application, or the data of your application models. This a very
powerful concept. Previously, you would have to create menu
items and connect them to slots, create toolbar items and
connect them to slots, and create keyboard shortcuts and connect
them to slots, too.
Keeping everything synchronized is
difficult, and the whole process often leads to a horrible mess.
Combine this with the possibility that you might want to disable
some action—such as redo, when there's nothing to
redo—and you're suddenly writing lots of duplicated code.
And then, of course, you get to the point where your users want
to modify the contents of the toolbar...
By bringing all the user-interface
characteristics of actions together in the
QAction class, most of the mess can be
avoided. The QAction class tracks the
following interface elements:
Pull-down menus text
Tooltip text
What's This text
Statusbar tips
Keyboard accelerators
Associated icons
Enabled/disabled
Toggled on or off
For each of these properties, there is a set function;
although you can also set some properties in the constructor
of QAction. Here is an annotated example
of a complete QAction
definition:
Example 13-1. Defining a complex toggle action
planAction=QAction(self)
planAction.setIconSet(QIconSet(QPixmap(plan)))
planAction.setText("Plan")
planAction.setMenuText("&Plan ...")
planAction.setOn(0)
planAction.setStatusTip("Enable the cunning plan")
planAction.setToolTip("Enables the cunning plan")
planAction.setWhatsThis(
"""Plan
Selecting plan enables the cunning plan
for this window.""")
planAction.setAccel(QAccel.stringToKey("CTRL+C"),)
planAction.setToggleAction(1)

- There are three constructors that
create a QAction with some of the
properties already set. However, I find it nicer to
create an empty QAction and set
everything by hand. Besides, the next thing we would
like to do is to read in the definition of a
QAction from an XML file or a
Python dictionary, and automatically generate the
actions. If you want to do this, it is just as easy to
set every property separately.
One important parameter is the
parent to the
QAction. You can create groups of
QActions —
QActionGroups. A
QActionGroup is a type of
QAction that functions like a type
of QGroupBox: it can group
actions into mutually exclusive choices. The whole group
of actions can be added to a menu.

- The set of icons you associate
with an action is used to paint the toolbar buttons.
They are also used to decorate the pull-down menus.
QIconSet can generate icons in
different sizes and with an active, normal or disabled
look all by itself, based on one icon—or you can
explicitly set icons of different sizes. You can provide
a user option to toggle
QMainWindow.setUsesBigPixmaps
on or off. This decides whether the toolbars will be
drawn with big icons, or small ones.

- This is a generic text that can be
used where a more specific text hasn't been set. For
instance, if you enable captions in toolbars with
QMainWindow.setUsesTextLabel(),
then this text will be used. It will also be used for
pulldown menu texts, unless you set those explicitly
with setMenuText().

- By setting the menutext
explicitly, you can add keyboard shortcuts (like alt-p
in this case), or the three dots that indicate that a
dialog window will open. You wouldn't want the shortcut
to show up on toolbar captions—they don't work
there, so you can set them in the menu text, by
prefixing an ampersand (&) to the shortcut
letter.

- Sometimes, a certain action
toggles an application state on or off. Examples include
setting toolbar captions of toolbar icon sizes, or bold
or normal fonts. By grouping actions in action groups,
you can create mutually exclusive groups (such as
centered, justified or ragged text in a text
editor).

- This text appears in the statusbar
of the mainwindow when the user presses but doesn't
release the menu option or toolbar button associated
with the action.

- This is a longer text that appears
in the form of a yellow note when the user presses the
optional ‘what's this' button, which appears on the
toolbar.

- The keyboard accelerator that
activates this action—for instance, pressing the control
and the s key together—will trigger the
activated() signal, which might be
connected to the save() slot function.
It is easiest to construct this using
QAccel's
stringToKey() function. Not only is
this very convenient, it can also be translated to
languages where a different shortcut key is preferred, by
using either pygettext or PyQt's
tr(). See Chapter 25 for
more information on internationalizing an
application.

- Of course, if you create a toggle
action, it is nice to be able to set the initial
state—which is what this does.
The QAction class can emit two
signals:
activated()
toggled(boolean)
By connecting these signals to the correct slots (either
directly in the document, or proxy slots defined in the
application interface), you have encapsulated the entire
behavior of your interface.
self.connect(planaction,
SIGNAL("activated()"),
self.slotExecuteCunningPlan)
or, for a toggle action:
self.connect(planaction,
SIGNAL("toggled(bool)"),
self.slotActivateCunningPlan)
All that remains, is to add the actions to pulldown menus
or toolbars:
self.planaction.addTo(self.planMenu)
self.planaction.addTo(self.toolBar)