KCoreAddons

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

KDE's Doxygen guidelines are available online.