Krita Source Code Documentation
Loading...
Searching...
No Matches
KisSuspendProjectionUpdatesStrokeStrategy Class Reference

#include <kis_suspend_projection_updates_stroke_strategy.h>

+ Inheritance diagram for KisSuspendProjectionUpdatesStrokeStrategy:

Classes

struct  Private
 
struct  SharedData
 
struct  SuspendUpdatesFilterInterface
 

Public Types

using SharedDataSP = QSharedPointer<SharedData>
 
- Public Types inherited from KisSimpleStrokeStrategy
enum  JobType {
  JOB_INIT = 0 , JOB_CANCEL , JOB_FINISH , JOB_DOSTROKE ,
  JOB_SUSPEND , JOB_RESUME , NJOBS
}
 

Public Member Functions

 KisSuspendProjectionUpdatesStrokeStrategy (KisImageWSP image, bool suspend, SharedDataSP sharedData)
 
 ~KisSuspendProjectionUpdatesStrokeStrategy () override
 
- Public Member Functions inherited from KisRunnableBasedStrokeStrategy
 KisRunnableBasedStrokeStrategy (const KisRunnableBasedStrokeStrategy &rhs)
 
 KisRunnableBasedStrokeStrategy (const QLatin1String &id, const KUndo2MagicString &name=KUndo2MagicString())
 
KisRunnableStrokeJobsInterfacerunnableJobsInterface () const
 
 ~KisRunnableBasedStrokeStrategy ()
 
- Public Member Functions inherited from KisSimpleStrokeStrategy
KisStrokeJobDatacreateCancelData () override
 
KisStrokeJobStrategycreateCancelStrategy () override
 
KisStrokeJobStrategycreateDabStrategy () override
 
KisStrokeJobDatacreateFinishData () override
 
KisStrokeJobStrategycreateFinishStrategy () override
 
KisStrokeJobDatacreateInitData () override
 
KisStrokeJobStrategycreateInitStrategy () override
 
KisStrokeJobDatacreateResumeData () override
 
KisStrokeJobStrategycreateResumeStrategy () override
 
KisStrokeJobDatacreateSuspendData () override
 
KisStrokeJobStrategycreateSuspendStrategy () override
 
virtual void finishStrokeCallback ()
 
 KisSimpleStrokeStrategy (const QLatin1String &id, const KUndo2MagicString &name=KUndo2MagicString())
 
- Public Member Functions inherited from KisStrokeStrategy
qreal balancingRatioOverride () const
 
bool canForgetAboutMe () const
 
bool clearsRedoOnStart () const
 
virtual KisStrokeStrategycreateLodClone (int levelOfDetail)
 
KisLodPreferences currentLodPreferences () const
 
bool forceLodModeIfPossible () const
 
QString id () const
 
bool isAsynchronouslyCancellable () const
 
bool isExclusive () const
 
 KisStrokeStrategy (const QLatin1String &id, const KUndo2MagicString &name=KUndo2MagicString())
 
KUndo2MagicString name () const
 
bool needsExplicitCancel () const
 
virtual void notifyUserEndedStroke ()
 
virtual void notifyUserStartedStroke ()
 
bool requestsOtherStrokesToEnd () const
 
void setForceLodModeIfPossible (bool forceLodModeIfPossible)
 
void setMutatedJobsInterface (KisStrokesQueueMutatedJobInterface *mutatedJobsInterface, KisStrokeId strokeId)
 
bool supportsWrapAroundMode () const
 
virtual void tryCancelCurrentStrokeJobAsync ()
 tryCancelCurrentStrokeJobAsync is called by the strokes queue when the stroke is being cancelled. The stroke strategy may or may not handle this request and cancel the currently running long action.
 
virtual ~KisStrokeStrategy ()
 

Static Public Member Functions

static QList< KisStrokeJobData * > createResumeJobsData (KisImageWSP image)
 
static SharedDataSP createSharedData ()
 
static QList< KisStrokeJobData * > createSuspendJobsData (KisImageWSP image)
 
- Static Public Member Functions inherited from KisSimpleStrokeStrategy
static QLatin1String jobTypeToString (JobType type)
 

Private Member Functions

void cancelStrokeCallback () override
 
void doStrokeCallback (KisStrokeJobData *data) override
 
void initStrokeCallback () override
 
void resumeStrokeCallback () override
 
void suspendStrokeCallback () override
 

Private Attributes

const QScopedPointer< Privatem_d
 

Additional Inherited Members

- Protected Member Functions inherited from KisSimpleStrokeStrategy
void enableJob (JobType type, bool enable=true, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
 
 KisSimpleStrokeStrategy (const KisSimpleStrokeStrategy &rhs)
 
- Protected Member Functions inherited from KisStrokeStrategy
void addMutatedJob (KisStrokeJobData *data)
 
void addMutatedJobs (const QVector< KisStrokeJobData * > list)
 
 KisStrokeStrategy (const KisStrokeStrategy &rhs)
 
void setAsynchronouslyCancellable (bool value)
 
void setBalancingRatioOverride (qreal value)
 
void setCanForgetAboutMe (bool value)
 
void setClearsRedoOnStart (bool value)
 
void setExclusive (bool value)
 
void setNeedsExplicitCancel (bool value)
 
void setRequestsOtherStrokesToEnd (bool value)
 
void setSupportsWrapAroundMode (bool value)
 

Detailed Description

Member Typedef Documentation

◆ SharedDataSP

Constructor & Destructor Documentation

◆ KisSuspendProjectionUpdatesStrokeStrategy()

KisSuspendProjectionUpdatesStrokeStrategy::KisSuspendProjectionUpdatesStrokeStrategy ( KisImageWSP image,
bool suspend,
SharedDataSP sharedData )

Here we add a dumb INIT job so that KisStrokesQueue would know that the stroke has already started or not. When the queue reaches the resume stroke and starts its execution, no Lod0 can execute anymore. So all the new Lod0 strokes should go to the end of the queue and wrapped into their own Suspend/Resume pair.

Definition at line 424 of file kis_suspend_projection_updates_stroke_strategy.cpp.

426 QLatin1String("suspend_stroke_strategy") :
427 QLatin1String("resume_stroke_strategy")),
428 m_d(new Private)
429{
430 m_d->image = image;
431 m_d->suspend = suspend;
432 m_d->sharedData = sharedData;
433
441 enableJob(JOB_INIT, true);
442
443 enableJob(JOB_DOSTROKE, true);
444 enableJob(JOB_CANCEL, true);
445
448
451}
KisRunnableBasedStrokeStrategy(const QLatin1String &id, const KUndo2MagicString &name=KUndo2MagicString())
void enableJob(JobType type, bool enable=true, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
void setClearsRedoOnStart(bool value)
void setNeedsExplicitCancel(bool value)

References KisStrokeJobData::BARRIER, KisSimpleStrokeStrategy::enableJob(), KisSimpleStrokeStrategy::JOB_CANCEL, KisSimpleStrokeStrategy::JOB_DOSTROKE, KisSimpleStrokeStrategy::JOB_INIT, KisSimpleStrokeStrategy::JOB_RESUME, KisSimpleStrokeStrategy::JOB_SUSPEND, m_d, KisStrokeStrategy::setClearsRedoOnStart(), and KisStrokeStrategy::setNeedsExplicitCancel().

◆ ~KisSuspendProjectionUpdatesStrokeStrategy()

KisSuspendProjectionUpdatesStrokeStrategy::~KisSuspendProjectionUpdatesStrokeStrategy ( )
override

Definition at line 453 of file kis_suspend_projection_updates_stroke_strategy.cpp.

454{
455 qDeleteAll(m_d->executedCommands);
456}

References m_d.

Member Function Documentation

◆ cancelStrokeCallback()

void KisSuspendProjectionUpdatesStrokeStrategy::cancelStrokeCallback ( )
overrideprivatevirtual

We shouldn't Q_EMIT any ad-hoc updates when cancelling the stroke. It generates weird temporary holes on the canvas, making the user feel awful, thinking his image got corrupted. We will just Q_EMIT a common refreshGraphAsync() that will do all the work in a beautiful way

Reimplemented from KisSimpleStrokeStrategy.

Definition at line 569 of file kis_suspend_projection_updates_stroke_strategy.cpp.

570{
571 KisImageSP image = m_d->image.toStrongRef();
572 if (!image) {
573 return;
574 }
575
576 for (auto it = m_d->executedCommands.rbegin(); it != m_d->executedCommands.rend(); ++it) {
577 (*it)->undo();
578 }
579
580 m_d->tryFetchUsedUpdatesFilter(image);
581
582 if (m_d->haveDisabledGUILodSync) {
584 }
585
593 if (!m_d->suspend) {
594 // FIXME: optimize
595 image->refreshGraphAsync();
596 }
597}
void emitRequestLodPlanesSyncBlocked(bool value)
void refreshGraphAsync(KisNodeSP root, const QVector< QRect > &rects, const QRect &cropRect, KisProjectionUpdateFlags flags=KisProjectionUpdateFlag::None) override
KisImageSignalRouter * signalRouter()

References KisImageSignalRouter::emitRequestLodPlanesSyncBlocked(), m_d, KisImage::refreshGraphAsync(), and KisImage::signalRouter().

◆ createResumeJobsData()

QList< KisStrokeJobData * > KisSuspendProjectionUpdatesStrokeStrategy::createResumeJobsData ( KisImageWSP image)
static

◆ createSharedData()

KisSuspendProjectionUpdatesStrokeStrategy::SharedDataSP KisSuspendProjectionUpdatesStrokeStrategy::createSharedData ( )
static

Definition at line 535 of file kis_suspend_projection_updates_stroke_strategy.cpp.

536{
537 return toQShared(new SharedData());
538}
QSharedPointer< T > toQShared(T *ptr)

References toQShared().

◆ createSuspendJobsData()

QList< KisStrokeJobData * > KisSuspendProjectionUpdatesStrokeStrategy::createSuspendJobsData ( KisImageWSP image)
static

Definition at line 525 of file kis_suspend_projection_updates_stroke_strategy.cpp.

526{
528}

◆ doStrokeCallback()

void KisSuspendProjectionUpdatesStrokeStrategy::doStrokeCallback ( KisStrokeJobData * data)
overrideprivatevirtual

When the Lod0 stroke is being recalculated in the background we should block all the updates it issues to avoid user distraction. The result of the final stroke should be shown to the user in the very end when everything is fully ready. Ideally the use should not notice that the image has changed :)

(Don't mix this process with suspend/resume capabilities of a single stroke. That is a different system!)

The process of the Lod0 regeneration consists of the following:

1) Suspend stroke executes. It sets a special updates filter on the image. The filter blocks all the updates and saves them in an internal structure to be emitted in the future.

2) Lod0 strokes are being recalculated. All their updates are blocked and saved in the filter.

3) Resume stroke starts:

3.1) First it disables emitting of sigImageUpdated() so the gui
     will not get any update notifications.

3.2) Then it enables updates themselves.

3.3) Initiates all the updates that were requested by the Lod0
     stroke. The node graph is regenerated, but the GUI does
     not get this change.

3.4) Special barrier job waits for all the updates to finish
     and, when they are done, enables GUI notifications again.

3.5) In a multithreaded way emits the GUI notifications for the
     entire image. Multithreaded way is used to conform the
     double-stage update principle of KisCanvas2.

Reimplemented from KisRunnableBasedStrokeStrategy.

Definition at line 512 of file kis_suspend_projection_updates_stroke_strategy.cpp.

513{
514 KisRunnableStrokeJobDataBase *runnable = dynamic_cast<KisRunnableStrokeJobDataBase*>(data);
515 if (runnable) {
516 runnable->run();
517
518 if (Private::UndoableData *undoable = dynamic_cast<Private::UndoableData*>(data)) {
519 Private::StrokeJobCommand *command = undoable->m_command.take();
520 m_d->executedCommands.append(command);
521 }
522 }
523}
virtual void run()=0

References m_d, and KisRunnable::run().

◆ initStrokeCallback()

void KisSuspendProjectionUpdatesStrokeStrategy::initStrokeCallback ( )
overrideprivatevirtual

Reimplemented from KisSimpleStrokeStrategy.

Definition at line 458 of file kis_suspend_projection_updates_stroke_strategy.cpp.

459{
461
462 if (m_d->suspend) {
463 jobs << new Private::UndoableData(new Private::SuspendUpdatesCommand(m_d.data()));
464 } else {
465 jobs << new Private::UndoableData(new Private::ResumeAndIssueGraphUpdatesCommand(m_d.data()));
466 jobs << new Private::BlockUILodSync(true, this);
467 jobs << new Private::UndoableData(new Private::StartBatchUIUpdatesCommand(this));
468 jobs << new Private::UndoableData(new Private::EndBatchUIUpdatesCommand(this));
469 jobs << new Private::BlockUILodSync(false, this);
470 }
471
473}
KisRunnableStrokeJobsInterface * runnableJobsInterface() const
virtual void addRunnableJobs(const QVector< KisRunnableStrokeJobDataBase * > &list)=0

References KisRunnableStrokeJobsInterface::addRunnableJobs(), m_d, and KisRunnableBasedStrokeStrategy::runnableJobsInterface().

◆ resumeStrokeCallback()

void KisSuspendProjectionUpdatesStrokeStrategy::resumeStrokeCallback ( )
overrideprivatevirtual

Reimplemented from KisSimpleStrokeStrategy.

Definition at line 621 of file kis_suspend_projection_updates_stroke_strategy.cpp.

622{
624
625 Q_FOREACH (Private::StrokeJobCommand *command, m_d->executedCommands) {
626 jobs << new Private::UndoableData(command);
627 }
628 m_d->executedCommands.clear();
629
631}

References KisRunnableStrokeJobsInterface::addRunnableJobs(), m_d, and KisRunnableBasedStrokeStrategy::runnableJobsInterface().

◆ suspendStrokeCallback()

void KisSuspendProjectionUpdatesStrokeStrategy::suspendStrokeCallback ( )
overrideprivatevirtual

The resume stroke can be suspended even when all its jobs are completed. In such a case, we should just ensure that all the internal state is reset to default.

Reimplemented from KisSimpleStrokeStrategy.

Definition at line 599 of file kis_suspend_projection_updates_stroke_strategy.cpp.

600{
608 !m_d->sanityResumingFinished ||
609 (m_d->sanityResumingFinished &&
610 m_d->usedFilters.isEmpty() &&
611 m_d->accumulatedDirtyRects.isEmpty()));
612
613 for (auto it = m_d->executedCommands.rbegin(); it != m_d->executedCommands.rend(); ++it) {
614 (*it)->undo();
615 }
616
617 // reset all the issued updates
618 m_d->updatesEpoch++;
619}
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KIS_SAFE_ASSERT_RECOVER_NOOP, and m_d.

Member Data Documentation

◆ m_d

const QScopedPointer<Private> KisSuspendProjectionUpdatesStrokeStrategy::m_d
private

The documentation for this class was generated from the following files: