Krita/QActions
QActions are an abstraction to associate some data like name, icon, and tooltip with a callback method, in order to provide an interface for widgets and keyboard shortcuts. Here I use the term "action" to refer to objects that inherit from QAction. This does not include the classes PrimaryAction/SecondaryAction, which could perhaps get a renaming when they are refactored in the future.
There has never been guidelines of how to use these until now, and because they can be easily tacked on and forgotten about, the system is prone to rotting. To counteract this, a coherent manager for actions in Krita has been designed. Because the system will remain complex even after existing code is cleaned up, this page also documents the way things are currently done.
New System
All action metadata should be contained in one of the .action XML files. Each action should be identified by a unique name. Otherwise these are in a somewhat flexible "long" format. Much of the rationale of the format is the extractrc program used to extract translation strings. In particular, only text contained in fields <text></text>, <tooltip></tooltip> and some others will be translated.
The global static class KisActionRegistry reads these data files. The class can serve as a factory of actions.
To create a QAction, most of the time, we want to use the method
QAction *action = KisActionRegistry::instance()->makeQAction("name");
Calls like action->setTooltip(i18n("tooltip")); should be completely obviated. The latter is an example of static data which should be removed from the code out to the .action description files. KisActionRegistry will also have a template method for creating derived classes of actions, such as QWidgetActions.
Right now, KisActionRegistry exposes the DOM data, though that might perhaps better be encapsulated another way. The system should be robust against requests for a property that is not in the data, e.g. requesting the shortcut for an action that has no <shortcut> tag.
Current Issues
There are general ideas of how the actions system works, but no hard and fast rules.
There are many distinct groups of actions inside Krita.
Collections of actions are stored in a Widgetutils/XMLGUIClient class called KActionCollection. This class has an enormous amount of structure and functionality, to the point which it can be annoying. This is ripe for refactoring, if you ever feel like doing so.
The main KActionCollection is owned by the KisMainWindow, since that class inherits from XMLGUIClient. This main collection gets passed around and referenced from tons and tons of different clients. This is the one we share with KisActionManager, KisViewManager, all the KisXxxManagers inject actions into this collection. (KisViewManager->actionCollection() is referenced 48 times in the code base.) The behavior of this when multiple main windows are open will be discussed later.
There are a number of QActions that are associated with tools. These show up in the Flake library. Tools have their own action collections.