Krita/Recording System

From KDE Community Wiki

Action Recording System


  1. All the types of tool actions should fit into action recorder system.
  2. Ensure that KisMacroPlayer is thread-safe (d->pause)
  3. [future] Use KoProperties or other user-friendly backends for saving the strategies into XML. This will allow the user to modify a recorded action by changing its properties.


Current Framework

Current action recording framework is base onto KisRecordedAction class. This class represents a single user action that can be serialized into XML and be replayed later. It has id() and name() for identification and UI representation as well. Each KisRecordedAction-based class has a corresponding KisRecordedActionFactory-based class. This factory is stored in the registry and supposed to map XML-data into a real constructed object.

KisRecordedNodeAction is an action that has some helper functions to save/load the real pointer of the node into/from a path written as a string.

KisMacro represents a container for KisRecordedAction objects. It has convenience methods for managing the sequence of actions, one method for running all the actions and two methods for serialization of the whole macro into XML.

KisActionRecorder is a simple wrapper around KisMacro. It just emits a signal on the addition of every action.

Stroke-Based approach

Currently, every tool (and every stroke of the tool) should have their own type of KisRecordedAction. That is quite difficult to achieve so now all the tools those use the Strokes Framework will have a common code for recording the action.

Let's see how the system works on example. Imagine we decided to save a stroke. We call the constructor of KisRecordedStrokeBasedAction and pass the stroke to it. The action itself cannot store any pointers to the stroke internally, so, first, it asks the stroke to serialize itself into XML. The stroke gets the request, saves it's internal variables , saves all the data (DabProcessingData) for jobs in his queue and then asks its KisStrokeStrategy to save itself (needIndirectPainting, isSequential and etc.) and the data for all the KisDabProcessingStrategy'es it should create. At this point the XML document will contain all the information needed for the replaying the action.

Now let's replay an action. Imagine we have a piece of XML data only. The steps are the following:

  1. We ask KisRecordedStrokeBasedActionFactory to create an action for us. Action is created.
  2. We ask an action to replay the stroke
  3. Action calls static function KisStroke::fromXML
  4. The stroke reads an id of the saved stroke and uses KisStrokeStrategyFactoryRegistry to retrieve its factory
  5. It creates a KisStrokeStrategy using the factory. The stroke strategy creates a KisDabProcessingStrategy as well
  6. The stroke creates all the jobs for the queue using the factory

Important Notes

  • KisRecordedStrokeBasedAction does not store any pointers or references to the real stroke. The only thing it stores internally is XML data describing the stroke
  • You needn't write your own implementation of KisStrokeStrategyFactory for every tool you create. You just need to typedef a template KisStorkeStrategyFactoryTraits.
    typedef KisStrokeStrategyFactoryTraits<FooStroke, BarData> FooBarStrokeFactory;
    This typedef defines a factory for stroke with the strategy named FooStroke and a data type named BarData. This factory should be added to the registry as well.