Undo framework ============== .. _qt_undo: https://doc.qt.io/qt-5/qundo.html Met.3D uses Qt to implement undoable user actions. The details how that works is provided by `Qt `_. This page describes how user actions can be made undoable using the undo framework in Met.3D. Undo command ------------ Each action a user might do, should to be implemented in an *Undo command*. An *Undo command* encapsulates a single action from the user. When the user triggers an action from the UI, it should instantiate an *Undo command* for that action. The command has to be pushed on the :ref:`undo_stack` which executes it. It is NOT needed to manually execute the action, the *Undo command* does that already. When the command is dropped from the *Undo stack*, either because it is full, cleared, or the command is obsolete, it will be deleted. Each *Undo command* is implemented as a class inheriting from ``QUndoCommand``. It has to implement the ``redo()`` member function to execute the action the user triggered. It also has to implement the ``undo()`` member function to revert that action. Additionally, everytime these function are called, it should be checked if the command is still valid. It might be, that the program state changed in some way that makes undoing or redoing the command impossible. Currently, many undo commands are part of actions executed on some object, such as ``MActor``. To make it clear, that the command corresponds to the *Actor* class, we implement the undo commands as nested classes. For example, the undo command to add an actor is implemented as ``class MActor::CreateCommand``. An example undo command is the following, which creates an actor. .. code-block:: cpp :linenos: :caption: Undo command class (.h) class MActor : public QObject { // Actor class header ... // Undo commands public: /** * Undo command used for actor creation. */ class CreateCommand : public QUndoCommand { public: CreateCommand(QString actorType, QString actorName, const QVector& scenes = {}); CreateCommand(QString actorConfig, QVector scenes, Qt::KeyboardModifiers mods = {}); void undo() override; void redo() override; MActor *getCreatedActor() const { return createdActor; } private: /** * The type of actor to create. */ QString actorType; /** * The name of the actor to create. */ QString actorName; /** * The path to the actor config that is used to create the actor from. */ QString actorConfig; /** * The scenes to add the actor to. */ QVector scenes; /** * Keyboard modifiers used when creating the actor. */ Qt::KeyboardModifiers mods; /** * The created actor. */ MActor *createdActor; }; } .. _undo_stack: Undo stack ---------- Met.3D uses a global undo stack in form of the singleton ``MUndoStack``. All undo commands can be pushed and executed by calling ``MUndoStack::run()``. The undo stack will be cleared when switching sessions.