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

#include <KoProgressUpdater.h>

+ Inheritance diagram for KoProgressUpdater:

Public Types

enum  Mode { Threaded , Unthreaded }
 

Public Slots

void cancel ()
 

Signals

void triggerUpdateAsynchronously ()
 

Public Member Functions

bool autoNestNames () const
 
void clearState ()
 
bool interrupted () const
 
 KoProgressUpdater (KoProgressProxy *progressProxy, Mode mode=Threaded)
 
 KoProgressUpdater (QPointer< KoUpdater > updater)
 a special constructor for connecting the progress updater to a self-destructible KoUpdater object.
 
 Private (KoProgressUpdater *_q, KoProgressProxy *proxy, QPointer< KoUpdater > parentUpdater, Mode _mode)
 
KoProgressProxyprogressProxy ()
 
void removePersistentSubtask (QPointer< KoUpdater > updater)
 
void setAutoNestNames (bool value)
 
void setUpdateInterval (int ms)
 
void start (int range=100, const QString &text="")
 
QPointer< KoUpdaterstartSubtask (int weight=1, const QString &name=QString(), bool isPersistent=false)
 
int updateInterval () const
 
void updateParentText ()
 
 ~KoProgressUpdater () override
 destructor
 

Public Attributes

bool autoNestNames = false
 
bool canceled
 
int currentProgress = 0
 
bool isStarted = false
 
bool isUndefinedState = false
 
Mode mode
 
QMutex mutex
 
KoProgressUpdaterq
 
QList< QPointer< KoUpdaterPrivate > > subtasks
 
int taskMax = 99
 
QString taskName
 
KisSignalCompressorupdateCompressor
 
int updateInterval = 250
 

Private Slots

void update ()
 
void updateUi ()
 

Private Attributes

Private *const d
 
KoProgressProxyparentProgressProxy
 
QPointer< KoUpdaterparentUpdater
 
- Private Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 

Additional Inherited Members

- Private Member Functions inherited from Private
 Private (KisCanvas2 *c)
 

Detailed Description

Allow multiple subtasks to safely update and report progress. This class is able to update a progress bar with the total progress of a project that may be separated into different subtasks. Each subtask will use one KoUpdater which that subtask can then report progress to. Each KoUpdater.setProgress() call will automatically calculate the total progress over the whole tasks made and update the progress bar with the total progress so far.

This class is created specifically with threading in mind so that subtasks can report their progress from their personal subthread and the progress bar will be updated correctly and not more often than repaints can occur.

Typical usage can be:

KoProgressUpdater *pu = new KoProgressUpdater(myProgressBar);
pu->start(100);
// create the subtasks
KoUpdater smooth = pu->startSubtask(5);
KoUpdater scale = pu->startSubtask(5);
KoUpdater cleanup = pu->startSubtask(1);
void start(int range=100, const QString &text="")
QPointer< KoUpdater > startSubtask(int weight=1, const QString &name=QString(), bool isPersistent=false)
KoProgressUpdater(KoProgressProxy *progressProxy, Mode mode=Threaded)

Doing a smooth.setProgress(50) will move the progress bar to 50% of the share of task 'smooth' which is 5 / 11 of the total and thus to 22.

KoProgressUpdater should be created in the main thread; KoProgressProxy must be, if it is gui subclass in the QApplication main thread. The other objects can be created in whatever thread one wants.

Also to prevent jumps in the progress-calculation and -display it is recommend to first create all the subtasks and then start to use setProgress on them.

Definition at line 23 of file KoProgressUpdater.cpp.

Member Enumeration Documentation

◆ Mode

Enumerator
Threaded 
Unthreaded 

Definition at line 58 of file KoProgressUpdater.h.

Constructor & Destructor Documentation

◆ KoProgressUpdater() [1/2]

KoProgressUpdater::KoProgressUpdater ( KoProgressProxy * progressProxy,
Mode mode = Threaded )
explicit

Constructor.

Parameters
progressBarthe progress bar to update.

Definition at line 70 of file KoProgressUpdater.cpp.

71 : d (new Private(this, progressProxy, 0, mode))
72{
74 connect(d->updateCompressor, SIGNAL(timeout()), SLOT(updateUi()));
75 connect(this, SIGNAL(triggerUpdateAsynchronously()), d->updateCompressor, SLOT(start()));
77}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KoProgressProxy * progressProxy()
void triggerUpdateAsynchronously()
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75

References connect(), d, KIS_ASSERT_RECOVER_RETURN, progressProxy(), start(), triggerUpdateAsynchronously(), and updateUi().

◆ KoProgressUpdater() [2/2]

KoProgressUpdater::KoProgressUpdater ( QPointer< KoUpdater > updater)
explicit

a special constructor for connecting the progress updater to a self-destructible KoUpdater object.

HACK ALERT: KoUpdater inherits KoProgressProxy, so be careful when constructing the updater and check which override is actually used.

Definition at line 79 of file KoProgressUpdater.cpp.

80 : d (new Private(this, 0, updater, Unthreaded))
81{
83 connect(d->updateCompressor, SIGNAL(timeout()), SLOT(updateUi()));
84 connect(this, SIGNAL(triggerUpdateAsynchronously()), d->updateCompressor, SLOT(start()));
86}

References connect(), d, KIS_ASSERT_RECOVER_RETURN, start(), triggerUpdateAsynchronously(), and updateUi().

◆ ~KoProgressUpdater()

KoProgressUpdater::~KoProgressUpdater ( )
override

destructor

Definition at line 88 of file KoProgressUpdater.cpp.

89{
90 if (d->progressProxy()) {
91 d->progressProxy()->setRange(0, d->taskMax);
92 d->progressProxy()->setValue(d->progressProxy()->maximum());
93 }
94
95 // make sure to stop the timer to avoid accessing
96 // the data we are going to delete right now
97 d->updateCompressor->stop();
98
99 qDeleteAll(d->subtasks);
100 d->subtasks.clear();
101
102 delete d;
103}

References d.

Member Function Documentation

◆ autoNestNames()

bool KoProgressUpdater::autoNestNames ( ) const

◆ cancel

void KoProgressUpdater::cancel ( )
slot

Cancelling the action will make each subtask be marked as 'interrupted' and set the total progress to 100%.

NOTE: cancelling mush happen from the same thread that KoProgressUpdater resides, which is usually GUI thread.

Definition at line 163 of file KoProgressUpdater.cpp.

164{
165 KIS_SAFE_ASSERT_RECOVER_RETURN(QThread::currentThread() == this->thread());
166
168
169 {
170 QMutexLocker l(&d->mutex);
171 subtasks = d->subtasks;
172 }
173
174 Q_FOREACH (QPointer<KoUpdaterPrivate> updater, subtasks) {
175 if (!updater) continue;
176
177 updater->setProgress(100);
178 updater->setInterrupted(true);
179 }
180 d->canceled = true;
181
183}
QList< QPointer< KoUpdaterPrivate > > subtasks
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References d, KIS_SAFE_ASSERT_RECOVER_RETURN, subtasks, and triggerUpdateAsynchronously().

◆ clearState()

void KoProgressUpdater::clearState ( )

◆ interrupted()

bool KoProgressUpdater::interrupted ( ) const
Returns
true when the processing is interrupted

Definition at line 324 of file KoProgressUpdater.cpp.

325{
326 return d->canceled;
327}

References d.

◆ Private()

KoProgressUpdater::Private ( KoProgressUpdater * _q,
KoProgressProxy * proxy,
QPointer< KoUpdater > parentUpdater,
Mode _mode )
inline

Definition at line 27 of file KoProgressUpdater.cpp.

◆ progressProxy()

KoProgressProxy * KoProgressUpdater::progressProxy ( )
inline

Definition at line 61 of file KoProgressUpdater.cpp.

◆ removePersistentSubtask()

void KoProgressUpdater::removePersistentSubtask ( QPointer< KoUpdater > updater)

Definition at line 143 of file KoProgressUpdater.cpp.

144{
145 {
146 QMutexLocker l(&d->mutex);
147
148 for (auto it = d->subtasks.begin(); it != d->subtasks.end();) {
149 if ((*it)->connectedUpdater() != updater) {
150 ++it;
151 } else {
152 KIS_SAFE_ASSERT_RECOVER_NOOP((*it)->isPersistent());
153 (*it)->deleteLater();
154 it = d->subtasks.erase(it);
155 break;
156 }
157 }
158 }
159
161}
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References d, KIS_SAFE_ASSERT_RECOVER_NOOP, and triggerUpdateAsynchronously().

◆ setAutoNestNames()

void KoProgressUpdater::setAutoNestNames ( bool value)

Definition at line 339 of file KoProgressUpdater.cpp.

340{
341 d->autoNestNames = value;
342}
float value(const T *src, size_t ch)

References d, and value().

◆ setUpdateInterval()

void KoProgressUpdater::setUpdateInterval ( int ms)

Definition at line 329 of file KoProgressUpdater.cpp.

330{
331 d->updateCompressor->setDelay(ms);
332}

References d.

◆ start()

void KoProgressUpdater::start ( int range = 100,
const QString & text = "" )

Start a new task.

This will invalidate any previously created subtasks and set the range of the progressBar as well as the text in the progressbar.

Parameters
rangethe total range of progress bar makes.
textThe text to show in the progressBar.
See also
KoProgressProxy::setRange()
KoProgressProxy::setFormat()

Definition at line 105 of file KoProgressUpdater.cpp.

106{
107 {
108 QMutexLocker l(&d->mutex);
109 d->clearState();
110 d->taskName = text;
111 d->taskMax = range - 1;
112 d->isStarted = true;
113 d->currentProgress = 0;
114 }
115
117}

References d, and triggerUpdateAsynchronously().

◆ startSubtask()

QPointer< KoUpdater > KoProgressUpdater::startSubtask ( int weight = 1,
const QString & name = QString(),
bool isPersistent = false )

After calling start() you can create any number of Updaters, one for each subtask.

Parameters
weightuse a weight to specify the weight this subtask has compared to the rest of the subtasks.

KoProgressUpdater will delete the KoUpdater instances when a start() is called or when it is deleted. The KoUpdater pointers are packed in a QPointer so you can check whether they have been deleted before dereferencing.

Definition at line 119 of file KoProgressUpdater.cpp.

122{
123 if (!d->isStarted) {
124 // lazy initialization for intermediate proxies
125 start();
126 }
127
128 KoUpdaterPrivate *p = new KoUpdaterPrivate(weight, name, isPersistent);
129
130 {
131 QMutexLocker l(&d->mutex);
132 d->subtasks.append(p);
133 }
134 connect(p, SIGNAL(sigUpdated()), SLOT(update()));
135 connect(p, SIGNAL(sigCancelled()), SLOT(cancel()));
136
137 QPointer<KoUpdater> updater = p->connectedUpdater();
138
140 return updater;
141}
const Params2D p

References cancel(), connect(), d, p, start(), triggerUpdateAsynchronously(), and update().

◆ triggerUpdateAsynchronously

void KoProgressUpdater::triggerUpdateAsynchronously ( )
signal

◆ update

void KoProgressUpdater::update ( )
privateslot

Definition at line 185 of file KoProgressUpdater.cpp.

186{
187 KIS_SAFE_ASSERT_RECOVER_RETURN(QThread::currentThread() == this->thread());
188
189 if (d->mode == Unthreaded) {
190 qApp->processEvents();
191 }
192
193 d->updateCompressor->start();
194}

References d, KIS_SAFE_ASSERT_RECOVER_RETURN, and Unthreaded.

◆ updateInterval()

int KoProgressUpdater::updateInterval ( ) const

◆ updateParentText()

void KoProgressUpdater::updateParentText ( )

◆ updateUi

void KoProgressUpdater::updateUi ( )
privateslot

Definition at line 196 of file KoProgressUpdater.cpp.

197{
198 KIS_SAFE_ASSERT_RECOVER_RETURN(QThread::currentThread() == this->thread());
199
200 // This function runs in the app main thread. All the progress
201 // updates arrive at the KoUpdaterPrivate instances through
202 // queued connections, so until we relinquish control to the
203 // event loop, the progress values cannot change, and that
204 // won't happen until we return from this function (which is
205 // triggered by a timer)
206
207 {
208 QMutexLocker l(&d->mutex);
209
210 if (!d->subtasks.isEmpty()) {
211 int totalProgress = 0;
212 int totalWeight = 0;
213 d->isUndefinedState = false;
214
215 Q_FOREACH (QPointer<KoUpdaterPrivate> updater, d->subtasks) {
216 if (updater->interrupted()) {
217 d->currentProgress = -1;
218 break;
219 }
220
221 if (!updater->hasValidRange()) {
222 totalWeight = 0;
223 totalProgress = 0;
224 d->isUndefinedState = true;
225 break;
226 }
227
228 if (updater->isPersistent() && updater->isCompleted()) {
229 continue;
230 }
231
232 const int progress = qBound(0, updater->progress(), 100);
233 totalProgress += progress * updater->weight();
234 totalWeight += updater->weight();
235 }
236
237 const int progressPercent = totalWeight > 0 ? totalProgress / totalWeight : -1;
238
239 d->currentProgress =
240 d->taskMax == 99 ?
241 progressPercent :
242 qRound(qreal(progressPercent) * d->taskMax / 99.0);
243 }
244
245 }
246
247 if (d->progressProxy()) {
248 if (!d->isUndefinedState) {
249 d->progressProxy()->setRange(0, d->taskMax);
250
251 if (d->currentProgress == -1) {
252 d->currentProgress = d->progressProxy()->maximum();
253 }
254
255 if (d->currentProgress >= d->progressProxy()->maximum()) {
256 {
257 QMutexLocker l(&d->mutex);
258 d->clearState();
259 }
260 d->progressProxy()->setRange(0, d->taskMax);
261 d->progressProxy()->setValue(d->progressProxy()->maximum());
262 } else {
263 d->progressProxy()->setValue(d->currentProgress);
264 }
265 } else {
266 d->progressProxy()->setRange(0,0);
267 d->progressProxy()->setValue(0);
268 }
269
270 d->updateParentText();
271 }
272}

References d, and KIS_SAFE_ASSERT_RECOVER_RETURN.

Member Data Documentation

◆ autoNestNames

bool KoProgressUpdater::autoNestNames = false

Definition at line 51 of file KoProgressUpdater.cpp.

◆ canceled

bool KoProgressUpdater::canceled

Definition at line 49 of file KoProgressUpdater.cpp.

◆ currentProgress

int KoProgressUpdater::currentProgress = 0

Definition at line 45 of file KoProgressUpdater.cpp.

◆ d

Private* const KoProgressUpdater::d
private

Definition at line 142 of file KoProgressUpdater.h.

◆ isStarted

bool KoProgressUpdater::isStarted = false

Definition at line 54 of file KoProgressUpdater.cpp.

◆ isUndefinedState

bool KoProgressUpdater::isUndefinedState = false

Definition at line 46 of file KoProgressUpdater.cpp.

◆ mode

Mode KoProgressUpdater::mode

Definition at line 44 of file KoProgressUpdater.cpp.

◆ mutex

QMutex KoProgressUpdater::mutex

Definition at line 56 of file KoProgressUpdater.cpp.

◆ parentProgressProxy

KoProgressProxy* KoProgressUpdater::parentProgressProxy
private

Definition at line 40 of file KoProgressUpdater.cpp.

◆ parentUpdater

QPointer<KoUpdater> KoProgressUpdater::parentUpdater
private

Definition at line 41 of file KoProgressUpdater.cpp.

◆ q

KoProgressUpdater* KoProgressUpdater::q

Definition at line 37 of file KoProgressUpdater.cpp.

◆ subtasks

QList<QPointer<KoUpdaterPrivate> > KoProgressUpdater::subtasks

Definition at line 48 of file KoProgressUpdater.cpp.

◆ taskMax

int KoProgressUpdater::taskMax = 99

Definition at line 53 of file KoProgressUpdater.cpp.

◆ taskName

QString KoProgressUpdater::taskName

Definition at line 52 of file KoProgressUpdater.cpp.

◆ updateCompressor

KisSignalCompressor* KoProgressUpdater::updateCompressor

Definition at line 47 of file KoProgressUpdater.cpp.

◆ updateInterval

int KoProgressUpdater::updateInterval = 250

Definition at line 50 of file KoProgressUpdater.cpp.


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