File indexing completed on 2024-05-12 15:58:43

0001 /*
0002  *  SPDX-FileCopyrightText: 2011 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_STROKE_STRATEGY_UNDO_COMMAND_BASED_H
0008 #define __KIS_STROKE_STRATEGY_UNDO_COMMAND_BASED_H
0009 
0010 #include <kundo2command.h>
0011 #include <QVector>
0012 #include <QMutex>
0013 
0014 #include "kis_types.h"
0015 #include "kis_simple_stroke_strategy.h"
0016 #include "KisRunnableBasedStrokeStrategy.h"
0017 
0018 
0019 class KisStrokeJob;
0020 class KisSavedMacroCommand;
0021 class KisStrokeUndoFacade;
0022 class KisStrokesQueueMutatedJobInterface;
0023 
0024 
0025 class KRITAIMAGE_EXPORT KisStrokeStrategyUndoCommandBased : public KisRunnableBasedStrokeStrategy
0026 {
0027 public:
0028     struct MutatedCommandInterface
0029     {
0030         virtual ~MutatedCommandInterface() {}
0031 
0032         void setRunnableJobsInterface(KisRunnableStrokeJobsInterface *interface) {
0033             m_mutatedJobsInterface = interface;
0034         }
0035 
0036         KisRunnableStrokeJobsInterface* runnableJobsInterface() const {
0037             return m_mutatedJobsInterface;
0038         }
0039 
0040     private:
0041         KisRunnableStrokeJobsInterface *m_mutatedJobsInterface;
0042     };
0043 
0044 
0045     class KRITAIMAGE_EXPORT Data : public KisStrokeJobData {
0046     public:
0047         Data(KUndo2CommandSP _command,
0048              bool _undo = false,
0049              Sequentiality _sequentiality = SEQUENTIAL,
0050              Exclusivity _exclusivity = NORMAL,
0051              bool _shouldGoToHistory = true)
0052             : KisStrokeJobData(_sequentiality, _exclusivity),
0053               command(_command),
0054               undo(_undo),
0055               shouldGoToHistory(_shouldGoToHistory)
0056         {
0057         }
0058 
0059         Data(KUndo2Command *_command,
0060              bool _undo = false,
0061              Sequentiality _sequentiality = SEQUENTIAL,
0062              Exclusivity _exclusivity = NORMAL,
0063              bool _shouldGoToHistory = true)
0064             : KisStrokeJobData(_sequentiality, _exclusivity),
0065               command(_command),
0066               undo(_undo),
0067               shouldGoToHistory(_shouldGoToHistory)
0068         {
0069         }
0070 
0071         ~Data() override;
0072 
0073         KUndo2CommandSP command;
0074         bool undo;
0075         bool shouldGoToHistory = true;
0076     };
0077 
0078 public:
0079     KisStrokeStrategyUndoCommandBased(const KUndo2MagicString &name,
0080                                       bool undo,
0081                                       KisStrokeUndoFacade *undoFacade,
0082                                       KUndo2CommandSP initCommand = KUndo2CommandSP(0),
0083                                       KUndo2CommandSP finishCommand = KUndo2CommandSP(0));
0084 
0085     using KisSimpleStrokeStrategy::setExclusive;
0086 
0087     void initStrokeCallback() override;
0088     void finishStrokeCallback() override;
0089     void cancelStrokeCallback() override;
0090     void doStrokeCallback(KisStrokeJobData *data) override;
0091 
0092     /**
0093      * Set extra data that will be assigned to the command
0094      * representing this action. Using extra data has the following
0095      * restrictions:
0096      *
0097      * 1) The \p data must be set *before* the stroke has been started.
0098      *    Setting the \p data after the stroke has been started with
0099      *    image->startStroke(strokeId) leads to an undefined behaviour.
0100      *
0101      * 2) \p data becomes owned by the strategy/command right after
0102      *    setting it. Don't try to change it afterwards.
0103      */
0104     void setCommandExtraData(KUndo2CommandExtraData *data);
0105 
0106     /**
0107      * Sets the id of this action. Will be used for merging the undo commands
0108      *
0109      * The \p value must be set *before* the stroke has been started.
0110      * Setting the \p value after the stroke has been started with
0111      * image->startStroke(strokeId) leads to an undefined behaviour.
0112      */
0113     void setMacroId(int value);
0114 
0115     /**
0116      * The undo-command-based is a low-level strategy, so it allows
0117      * changing its wraparound mode status.
0118      *
0119      * WARNING: the switch must be called *before* the stroke has been
0120      * started! Otherwise the mode will not be activated.
0121      */
0122     using KisStrokeStrategy::setSupportsWrapAroundMode;
0123 
0124     void setUsedWhileUndoRedo(bool value);
0125 
0126 protected:
0127     void runAndSaveCommand(KUndo2CommandSP command,
0128                            KisStrokeJobData::Sequentiality sequentiality,
0129                            KisStrokeJobData::Exclusivity exclusivity);
0130     void notifyCommandDone(KUndo2CommandSP command,
0131                            KisStrokeJobData::Sequentiality sequentiality,
0132                            KisStrokeJobData::Exclusivity exclusivity);
0133 
0134     KisStrokeStrategyUndoCommandBased(const KisStrokeStrategyUndoCommandBased &rhs);
0135 
0136     /**
0137      * @brief Applies some modifications (e.g. assigning extra data) to the toplevel command
0138      */
0139     virtual void postProcessToplevelCommand(KUndo2Command *command);
0140 
0141     KisStrokeUndoFacade* undoFacade() const;
0142 
0143 protected:
0144     void executeCommand(KUndo2CommandSP command, bool undo);
0145     void cancelStrokeCallbackImpl(QVector<KisStrokeJobData*> &mutatedJobs);
0146 private:
0147     bool m_undo;
0148     KUndo2CommandSP m_initCommand;
0149     KUndo2CommandSP m_finishCommand;
0150     KisStrokeUndoFacade *m_undoFacade {nullptr};
0151 
0152     QScopedPointer<KUndo2CommandExtraData> m_commandExtraData;
0153     int m_macroId;
0154 
0155     // protects done commands only
0156     QMutex m_mutex;
0157     KisSavedMacroCommand *m_macroCommand {nullptr};
0158 };
0159 
0160 #endif /* __KIS_STROKE_STRATEGY_UNDO_COMMAND_BASED_H */