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_H
0008 #define __KIS_STROKE_STRATEGY_H
0009 
0010 #include <QString>
0011 #include "kis_types.h"
0012 #include "kundo2magicstring.h"
0013 #include "kritaimage_export.h"
0014 #include "KisLodPreferences.h"
0015 
0016 class KisStrokeJobStrategy;
0017 class KisStrokeJobData;
0018 class KisStrokesQueueMutatedJobInterface;
0019 
0020 class KRITAIMAGE_EXPORT KisStrokeStrategy
0021 {
0022 public:
0023     KisStrokeStrategy(const QLatin1String &id, const KUndo2MagicString &name = KUndo2MagicString());
0024     virtual ~KisStrokeStrategy();
0025 
0026     /**
0027      * notifyUserStartedStroke() is a callback used by the strokes system to notify
0028      * when the user adds the stroke to the strokes queue. That moment corresponds
0029      * to the user calling strokesFacade->startStroke(strategy) and might happen much
0030      * earlier than the first job being executed.
0031      *
0032      * NOTE: this method will be executed in the context of the GUI thread!
0033      */
0034     virtual void notifyUserStartedStroke();
0035 
0036     /**
0037      * notifyUserEndedStroke() is a callback used by the strokes system to notify
0038      * when the user ends the stroke. That moment corresponds to the user calling
0039      * strokesFacade->endStroke(id) and might happen much earlier when the stroke
0040      * even started its execution.
0041      *
0042      * NOTE: this method will be executed in the context of the GUI thread!
0043      */
0044     virtual void notifyUserEndedStroke();
0045 
0046     virtual KisStrokeJobStrategy* createInitStrategy();
0047     virtual KisStrokeJobStrategy* createFinishStrategy();
0048     virtual KisStrokeJobStrategy* createCancelStrategy();
0049     virtual KisStrokeJobStrategy* createDabStrategy();
0050     virtual KisStrokeJobStrategy* createSuspendStrategy();
0051     virtual KisStrokeJobStrategy* createResumeStrategy();
0052 
0053     virtual KisStrokeJobData* createInitData();
0054     virtual KisStrokeJobData* createFinishData();
0055     virtual KisStrokeJobData* createCancelData();
0056     virtual KisStrokeJobData* createSuspendData();
0057     virtual KisStrokeJobData* createResumeData();
0058 
0059     virtual KisStrokeStrategy* createLodClone(int levelOfDetail);
0060 
0061     bool isExclusive() const;
0062     bool supportsWrapAroundMode() const;
0063 
0064 
0065     /**
0066      * Returns true if mere start of the stroke should cancel all the
0067      * pending redo tasks.
0068      *
0069      * This method should return true in almost all circumstances
0070      * except if we are running an undo or redo stroke.
0071      */
0072     bool clearsRedoOnStart() const;
0073 
0074     /**
0075      * Returns true if the other currently running strokes should be
0076      * politely asked to exit. The default value is 'true'.
0077      *
0078      * The only known exception right now is
0079      * KisRegenerateFrameStrokeStrategy which does not requests ending
0080      * of any actions, since it performs purely background action.
0081      */
0082     bool requestsOtherStrokesToEnd() const;
0083 
0084     /**
0085      * Returns true if the update scheduler can cancel this stroke
0086      * when some other stroke is going to be started. This makes the
0087      * "forgettable" stroke very low priority.
0088      *
0089      * Default is 'false'.
0090      */
0091     bool canForgetAboutMe() const;
0092 
0093     /**
0094      * Returns true if the stroke can be cancelled by the
0095      * engine, e.g. when the user presses Esc key or
0096      * Ctrl+Z shortcut. Default value is true. The only
0097      * exception right now are the strokes that perform
0098      * undo/redo operations.
0099      *
0100      * The owner of the stroke can still cancel the stroke
0101      * via the strokeId handle (though it is not used for
0102      * undo/redo strokes).
0103      */
0104     bool isAsynchronouslyCancellable() const;
0105 
0106     bool needsExplicitCancel() const;
0107 
0108 
0109     /**
0110      * \see setBalancingRatioOverride() for details
0111      */
0112     qreal balancingRatioOverride() const;
0113 
0114     QString id() const;
0115     KUndo2MagicString name() const;
0116 
0117     /**
0118      * Returns current lod preferences of the strokes queue
0119      */
0120     KisLodPreferences currentLodPreferences() const;
0121 
0122     void setMutatedJobsInterface(KisStrokesQueueMutatedJobInterface *mutatedJobsInterface, KisStrokeId strokeId);
0123 
0124     bool forceLodModeIfPossible() const;
0125     void setForceLodModeIfPossible(bool forceLodModeIfPossible);
0126 
0127 protected:
0128     // testing surrogate class
0129     friend class KisMutatableDabStrategy;
0130 
0131     /**
0132      * This function is supposed to be called by internal asynchronous
0133      * jobs. It allows adding subtasks that may be executed concurrently.
0134      *
0135      * Requirements:
0136      *   * must be called *only* from within the context of the strokes
0137      *     worker thread during execution of one of its jobs
0138      *
0139      * Guarantees:
0140      *   * the added job is guaranteed to be executed in some time after
0141      *     the currently executed job, *before* the next SEQUENTIAL or
0142      *     BARRIER job
0143      *   * if the currently executed job is CUNCURRENTthe mutated job *may*
0144      *     start execution right after adding to the queue without waiting for
0145      *     its parent to complete. Though this behavior is *not* guaranteed,
0146      *     because addMutatedJob does not initiate processQueues(), because
0147      *     it may lead to a deadlock.
0148      */
0149     void addMutatedJobs(const QVector<KisStrokeJobData*> list);
0150 
0151     /**
0152      * Convenience override for addMutatedJobs()
0153      */
0154     void addMutatedJob(KisStrokeJobData *data);
0155 
0156 
0157     // you are not supposed to change these parameters
0158     // after the KisStroke object has been created
0159 
0160     void setExclusive(bool value);
0161     void setSupportsWrapAroundMode(bool value);
0162     void setClearsRedoOnStart(bool value);
0163     void setRequestsOtherStrokesToEnd(bool value);
0164     void setCanForgetAboutMe(bool value);
0165     void setAsynchronouslyCancellable(bool value);
0166     void setNeedsExplicitCancel(bool value);
0167 
0168     /**
0169      * Set override for the desired scheduler balancing ratio:
0170      *
0171      * ratio = stroke jobs / update jobs
0172      *
0173      * If \p value < 1.0, then the priority is given to updates, if
0174      * the value is higher than 1.0, then the priority is given
0175      * to stroke jobs.
0176      *
0177      * Special value -1.0, suggests the scheduler to use the default value
0178      * set by the user's config file (which is 100.0 by default).
0179      */
0180     void setBalancingRatioOverride(qreal value);
0181 
0182 protected:
0183     /**
0184      * Protected c-tor, used for cloning of hi-level strategies
0185      */
0186     KisStrokeStrategy(const KisStrokeStrategy &rhs);
0187 
0188 private:
0189     bool m_exclusive;
0190     bool m_supportsWrapAroundMode;
0191 
0192     bool m_clearsRedoOnStart;
0193     bool m_requestsOtherStrokesToEnd;
0194     bool m_canForgetAboutMe;
0195     bool m_asynchronouslyCancellable;
0196     bool m_needsExplicitCancel;
0197     bool m_forceLodModeIfPossible;
0198     qreal m_balancingRatioOverride;
0199 
0200     QLatin1String m_id;
0201     KUndo2MagicString m_name;
0202 
0203     KisStrokeId m_strokeId;
0204     KisStrokesQueueMutatedJobInterface *m_mutatedJobsInterface;
0205 };
0206 
0207 #endif /* __KIS_STROKE_STRATEGY_H */