Command Framework

Structure for registering commands to the FreeCAD system.

Structure for registering commands to the FreeCAD system.

Overview

In GUI applications many commands can be invoked via a menu item, a toolbar button or an accelerator key. The answer of Qt to master this challenge is the class QAction. A QAction object can be added to a popup menu or a toolbar and keep the state of the menu item and the toolbar button synchronized.

For example, if the user clicks the menu item of a toggle action then the toolbar button gets also pressed and vice versa. For more details refer to your Qt documentation.

Drawbacks

Since QAction inherits QObject and emits the triggered() signal or toggled() signal for toggle actions it is very convenient to connect these signals e.g. with slots of your MainWindow class. But this means that for every action an appropriate slot of MainWindow is necessary and leads to an inflated MainWindow class. Furthermore, it's simply impossible to provide plugins that may also need special slots – without changing the MainWindow class.

Way out

To solve these problems we have introduced the command framework to decouple QAction and MainWindow. The base classes of the framework are Gui::CommandBase and Gui::Action that represent the link between Qt's QAction world and the FreeCAD's command world.

The Action class holds a pointer to QAction and CommandBase and acts as a mediator and – to save memory – that gets created (Gui::CommandBase::createAction()) not before it is added (Gui::Command::addTo()) to a menu or toolbar.

Now, the implementation of the slots of MainWindow can be done in the method activated() of subclasses of Command instead.

For example, the implementation of the "Open file" command can be done as follows.

class OpenCommand : public Command
{
public:
OpenCommand() : Command("Std_Open")
{
// set up menu text, status tip, ...
sMenuText = "&Open";
sToolTipText = "Open a file";
sWhatsThis = "Open a file";
sStatusTip = "Open a file";
sPixmap = "Open"; // name of a registered pixmap
sAccel = "Shift+P"; // or "P" or "P, L" or "Ctrl+X, Ctrl+C" for a sequence
}
protected:
void activated(int)
{
QString filter ... // make a filter of all supported file formats
QStringList FileList = QFileDialog::getOpenFileNames( filter,QString(), getMainWindow() );
for ( QStringList::Iterator it = FileList.begin(); it != FileList.end(); ++it ) {
getGuiApplication()->open((*it).latin1());
}
}
};

An instance of OpenCommand must be created and added to the Gui::CommandManager to make the class known to FreeCAD. To see how menus and toolbars can be built go to the Workbench Framework.

See also
Gui::Command, Gui::CommandManager