KCoreAddons

kjob.cpp
1/*
2 This file is part of the KDE project
3
4 SPDX-FileCopyrightText: 2000 Stephan Kulow <coolo@kde.org>
5 SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
6 SPDX-FileCopyrightText: 2006 Kevin Ottens <ervin@kde.org>
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9*/
10
11#include "kjob.h"
12#include "kjob_p.h"
13
14#include "kcoreaddons_debug.h"
15#include "kjobuidelegate.h"
16
17#include <QEventLoop>
18#include <QTimer>
19
20KJobPrivate::KJobPrivate()
21{
22}
23
24KJobPrivate::~KJobPrivate()
25{
26}
27
29 : QObject(parent)
30 , d_ptr(new KJobPrivate)
31{
32 d_ptr->q_ptr = this;
33}
34
35KJob::KJob(KJobPrivate &dd, QObject *parent)
36 : QObject(parent)
37 , d_ptr(&dd)
38{
39 d_ptr->q_ptr = this;
40}
41
43{
44 if (!d_ptr->isFinished) {
45 d_ptr->isFinished = true;
46 Q_EMIT finished(this, QPrivateSignal());
47 }
48
49 delete d_ptr->speedTimer;
50 delete d_ptr->uiDelegate;
51}
52
54{
55 Q_D(KJob);
56 if (!delegate) {
57 delete d->uiDelegate;
58 d->uiDelegate = nullptr;
59 return;
60 }
61
62 if (delegate->setJob(this)) {
63 delete d->uiDelegate;
64 d->uiDelegate = delegate;
65 d->uiDelegate->connectJob(this);
66 }
67}
68
70{
71 return d_func()->uiDelegate;
72}
73
74KJob::Capabilities KJob::capabilities() const
75{
76 return d_func()->capabilities;
77}
78
80{
81 return d_func()->suspended;
82}
83
84void KJob::finishJob(bool emitResult)
85{
86 Q_D(KJob);
87 Q_ASSERT(!d->isFinished);
88 d->isFinished = true;
89
90 if (d->eventLoop) {
91 d->eventLoop->quit();
92 }
93
94 // If we are displaying a progress dialog, remove it first.
95 Q_EMIT finished(this, QPrivateSignal());
96
97 if (emitResult) {
98 Q_EMIT result(this, QPrivateSignal());
99 }
100
101 if (isAutoDelete()) {
102 deleteLater();
103 }
104}
105
106bool KJob::kill(KillVerbosity verbosity)
107{
108 Q_D(KJob);
109 if (d->isFinished) {
110 return true;
111 }
112
113 if (doKill()) {
114 // A subclass can (but should not) call emitResult() or kill()
115 // from doKill() and thus set isFinished to true.
116 if (!d->isFinished) {
117 setError(KilledJobError);
118 finishJob(verbosity != Quietly);
119 }
120 return true;
121 } else {
122 return false;
123 }
124}
125
127{
128 Q_D(KJob);
129 if (!d->suspended) {
130 if (doSuspend()) {
131 d->suspended = true;
132 Q_EMIT suspended(this, QPrivateSignal());
133
134 return true;
135 }
136 }
137
138 return false;
139}
140
142{
143 Q_D(KJob);
144 if (d->suspended) {
145 if (doResume()) {
146 d->suspended = false;
147 Q_EMIT resumed(this, QPrivateSignal());
148
149 return true;
150 }
151 }
152
153 return false;
154}
155
157{
158 return false;
159}
160
162{
163 return false;
164}
165
167{
168 return false;
169}
170
172{
173 Q_D(KJob);
174 d->capabilities = capabilities;
175}
176
178{
179 Q_D(KJob);
180 // Usually this job would delete itself, via deleteLater() just after
181 // emitting result() (unless configured otherwise). Since we use an event
182 // loop below, that event loop will process the deletion event and we'll
183 // have been deleted when exec() returns. This crashes, so temporarily
184 // suspend autodeletion and manually do it afterwards.
185 const bool wasAutoDelete = isAutoDelete();
186 setAutoDelete(false);
187
188 Q_ASSERT(!d->eventLoop);
189
190 QEventLoop loop(this);
191 d->eventLoop = &loop;
192
193 start();
194 if (!d->isFinished) {
195 d->m_startedWithExec = true;
196 d->eventLoop->exec(QEventLoop::ExcludeUserInputEvents);
197 }
198 d->eventLoop = nullptr;
199
200 if (wasAutoDelete) {
201 deleteLater();
202 }
203 return (d->error == NoError);
204}
205
206int KJob::error() const
207{
208 return d_func()->error;
209}
210
211QString KJob::errorText() const
212{
213 return d_func()->errorText;
214}
215
216QString KJob::errorString() const
217{
218 return d_func()->errorText;
219}
220
221qulonglong KJob::processedAmount(Unit unit) const
222{
223 if (unit >= UnitsCount) {
224 qCWarning(KCOREADDONS_DEBUG) << "KJob::processedAmount() was called on an invalid Unit" << unit;
225 return 0;
226 }
227
228 return d_func()->m_jobAmounts[unit].processedAmount;
229}
230
231qulonglong KJob::totalAmount(Unit unit) const
232{
233 if (unit >= UnitsCount) {
234 qCWarning(KCOREADDONS_DEBUG) << "KJob::totalAmount() was called on an invalid Unit" << unit;
235 return 0;
236 }
237
238 return d_func()->m_jobAmounts[unit].totalAmount;
239}
240
241unsigned long KJob::percent() const
242{
243 return d_func()->percentage;
244}
245
247{
248 return d_func()->isFinished;
249}
250
251void KJob::setError(int errorCode)
252{
253 Q_D(KJob);
254 d->error = errorCode;
255}
256
257void KJob::setErrorText(const QString &errorText)
258{
259 Q_D(KJob);
260 d->errorText = errorText;
261}
262
263void KJob::setProcessedAmount(Unit unit, qulonglong amount)
264{
265 if (unit >= UnitsCount) {
266 qCWarning(KCOREADDONS_DEBUG) << "KJob::setProcessedAmount() was called on an invalid Unit" << unit;
267 return;
268 }
269
270 Q_D(KJob);
271
272 auto &[processed, total] = d->m_jobAmounts[unit];
273
274 const bool should_emit = (processed != amount);
275
276 processed = amount;
277
278 if (should_emit) {
279 Q_EMIT processedAmountChanged(this, unit, amount, QPrivateSignal{});
280 if (unit == d->progressUnit) {
281 Q_EMIT processedSize(this, amount);
282 emitPercent(processed, total);
283 }
284 }
285}
286
287void KJob::setTotalAmount(Unit unit, qulonglong amount)
288{
289 if (unit >= UnitsCount) {
290 qCWarning(KCOREADDONS_DEBUG) << "KJob::setTotalAmount() was called on an invalid Unit" << unit;
291 return;
292 }
293
294 Q_D(KJob);
295
296 auto &[processed, total] = d->m_jobAmounts[unit];
297
298 const bool should_emit = (total != amount);
299
300 total = amount;
301
302 if (should_emit) {
303 Q_EMIT totalAmountChanged(this, unit, amount, QPrivateSignal{});
304 if (unit == d->progressUnit) {
305 Q_EMIT totalSize(this, amount);
306 emitPercent(processed, total);
307 }
308 }
309}
310
312{
313 Q_D(KJob);
314 d->progressUnit = unit;
315}
316
317void KJob::setPercent(unsigned long percentage)
318{
319 Q_D(KJob);
320 if (d->percentage != percentage) {
321 d->percentage = percentage;
322 Q_EMIT percentChanged(this, percentage, QPrivateSignal{});
323 }
324}
325
327{
328 if (!d_func()->isFinished) {
329 finishJob(true);
330 }
331}
332
333void KJob::emitPercent(qulonglong processedAmount, qulonglong totalAmount)
334{
335 if (totalAmount != 0) {
337 }
338}
339
340void KJob::emitSpeed(unsigned long value)
341{
342 Q_D(KJob);
343 if (!d->speedTimer) {
344 d->speedTimer = new QTimer(this);
345 connect(d->speedTimer, &QTimer::timeout, this, [d]() {
346 d->speedTimeout();
347 });
348 }
349
350 Q_EMIT speed(this, value);
351 d->speedTimer->start(5000); // 5 seconds interval should be enough
352}
353
354void KJobPrivate::speedTimeout()
355{
356 Q_Q(KJob);
357 // send 0 and stop the timer
358 // timer will be restarted only when we receive another speed event
359 Q_EMIT q->speed(q, 0);
360 speedTimer->stop();
361}
362
364{
365 Q_D(const KJob);
366 return d->isAutoDelete;
367}
368
369void KJob::setAutoDelete(bool autodelete)
370{
371 Q_D(KJob);
372 d->isAutoDelete = autodelete;
373}
374
376{
377 Q_D(KJob);
378 d->m_hideFinishedNotification = hide;
379}
380
382{
383 Q_D(const KJob);
384 return d->m_hideFinishedNotification;
385}
386
388{
389 Q_D(const KJob);
390 return d->m_startedWithExec;
391}
392
393#include "moc_kjob.cpp"
The base class for all KJob UI delegate.
virtual bool setJob(KJob *job)
Attach this UI delegate to a job.
The base class for all jobs.
Definition kjob.h:74
void resumed(KJob *job)
Emitted when the job is resumed.
bool exec()
Executes the job synchronously.
Definition kjob.cpp:177
void setErrorText(const QString &errorText)
Sets the error text.
Definition kjob.cpp:257
Unit
Describes the unit used in the methods that handle reporting the job progress info.
Definition kjob.h:87
@ UnitsCount
Definition kjob.h:94
bool resume()
Resumes this job.
Definition kjob.cpp:141
bool suspend()
Suspends this job.
Definition kjob.cpp:126
void setTotalAmount(Unit unit, qulonglong amount)
Sets the total size.
Definition kjob.cpp:287
void emitResult()
Utility function to emit the result signal, and end this job.
Definition kjob.cpp:326
Q_SCRIPTABLE qulonglong totalAmount(Unit unit) const
Returns the total amount of a given unit for this job.
Definition kjob.cpp:231
bool isFinished() const
Returns if the job has been finished and has emitted the finished() signal.
Definition kjob.cpp:246
void processedSize(KJob *job, qulonglong size)
Regularly emitted to show the progress of this job (current data size in bytes for transfers,...
void result(KJob *job)
Emitted when the job is finished (except when killed with KJob::Quietly).
virtual bool doKill()
Aborts this job quietly.
Definition kjob.cpp:156
bool isSuspended() const
Returns if the job was suspended with the suspend() call.
Definition kjob.cpp:79
virtual bool doSuspend()
Suspends this job.
Definition kjob.cpp:161
void totalAmountChanged(KJob *job, KJob::Unit unit, qulonglong amount)
Emitted when we know the amount the job will have to process.
void finished(KJob *job)
Emitted when the job is finished, in any case.
Q_SCRIPTABLE qulonglong processedAmount(Unit unit) const
Returns the processed amount of a given unit for this job.
Definition kjob.cpp:221
bool isFinishedNotificationHidden() const
Whether to not show a finished notification when a job's finished signal is emitted.
Definition kjob.cpp:381
void setPercent(unsigned long percentage)
Sets the overall progress of the job.
Definition kjob.cpp:317
void setError(int errorCode)
Sets the error code.
Definition kjob.cpp:251
KJobUiDelegate * uiDelegate() const
Retrieves the delegate attached to this job.
Definition kjob.cpp:69
bool isAutoDelete() const
Returns whether this job automatically deletes itself once the job is finished.
Definition kjob.cpp:363
void totalSize(KJob *job, qulonglong size)
Emitted when we know the size of this job (data size in bytes for transfers, number of entries for li...
void setCapabilities(Capabilities capabilities)
Sets the capabilities for this job.
Definition kjob.cpp:171
void setProgressUnit(Unit unit)
Sets the unit that will be used internally to calculate the progress percentage.
Definition kjob.cpp:311
void processedAmountChanged(KJob *job, KJob::Unit unit, qulonglong amount)
Regularly emitted to show the progress of this job by giving the current amount.
void suspended(KJob *job)
Emitted when the job is suspended.
bool isStartedWithExec() const
Returns true if this job was started with exec(), which starts a nested event-loop (with QEventLoop::...
Definition kjob.cpp:387
void emitPercent(qulonglong processedAmount, qulonglong totalAmount)
Utility function for inherited jobs.
Definition kjob.cpp:333
virtual Q_SCRIPTABLE void start()=0
Starts the job asynchronously.
virtual bool doResume()
Resumes this job.
Definition kjob.cpp:166
void setAutoDelete(bool autodelete)
Sets the auto-delete property of the job.
Definition kjob.cpp:369
KJob(QObject *parent=nullptr)
Creates a new KJob object.
Definition kjob.cpp:28
void setProcessedAmount(Unit unit, qulonglong amount)
Sets the processed size.
Definition kjob.cpp:263
~KJob() override
Destroys a KJob object.
Definition kjob.cpp:42
bool kill(KJob::KillVerbosity verbosity=KJob::Quietly)
Aborts this job.
Definition kjob.cpp:106
void setUiDelegate(KJobUiDelegate *delegate)
Attach a UI delegate to this job.
Definition kjob.cpp:53
void emitSpeed(unsigned long speed)
Utility function for inherited jobs.
Definition kjob.cpp:340
void percentChanged(KJob *job, unsigned long percent)
Progress signal showing the overall progress of the job.
void speed(KJob *job, unsigned long speed)
Emitted to display information about the speed of this job.
void setFinishedNotificationHidden(bool hide=true)
This method can be used to indicate to classes listening to signals from a job that they should ideal...
Definition kjob.cpp:375
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
void timeout()
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 21 2024 12:03:20 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.