KDECore
kjob.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2000 Stephan Kulow <coolo@kde.org> 00003 David Faure <faure@kde.org> 00004 Copyright (C) 2006 Kevin Ottens <ervin@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 00020 */ 00021 00022 #include "kjob.h" 00023 #include "kjob_p.h" 00024 00025 #include "kjobuidelegate.h" 00026 00027 #include <kglobal.h> 00028 #include <QEventLoop> 00029 #include <QMap> 00030 #include <QMetaType> 00031 #include <QTimer> 00032 00033 bool KJobPrivate::_k_kjobUnitEnumRegistered = false; 00034 KJobPrivate::KJobPrivate() 00035 : q_ptr(0), uiDelegate(0), error(KJob::NoError), 00036 progressUnit(KJob::Bytes), percentage(0), 00037 suspended(false), capabilities(KJob::NoCapabilities), 00038 speedTimer(0), isAutoDelete(true), eventLoop(0), isFinished(false) 00039 { 00040 if (!_k_kjobUnitEnumRegistered) { 00041 _k_kjobUnitEnumRegistered = qRegisterMetaType<KJob::Unit>("KJob::Unit"); 00042 } 00043 } 00044 00045 KJobPrivate::~KJobPrivate() 00046 { 00047 } 00048 00049 KJob::KJob(QObject *parent) 00050 : QObject(parent), d_ptr(new KJobPrivate) 00051 { 00052 d_ptr->q_ptr = this; 00053 // Don't exit while this job is running 00054 KGlobal::ref(); 00055 } 00056 00057 KJob::KJob(KJobPrivate &dd, QObject *parent) 00058 : QObject(parent), d_ptr(&dd) 00059 { 00060 d_ptr->q_ptr = this; 00061 // Don't exit while this job is running 00062 KGlobal::ref(); 00063 } 00064 00065 KJob::~KJob() 00066 { 00067 if (!d_ptr->isFinished) { 00068 emit finished(this); 00069 } 00070 00071 delete d_ptr->speedTimer; 00072 delete d_ptr->uiDelegate; 00073 delete d_ptr; 00074 00075 KGlobal::deref(); 00076 } 00077 00078 void KJob::setUiDelegate( KJobUiDelegate *delegate ) 00079 { 00080 Q_D(KJob); 00081 if ( delegate == 0 || delegate->setJob( this ) ) 00082 { 00083 delete d->uiDelegate; 00084 d->uiDelegate = delegate; 00085 00086 if ( d->uiDelegate ) 00087 { 00088 d->uiDelegate->connectJob( this ); 00089 } 00090 } 00091 } 00092 00093 KJobUiDelegate *KJob::uiDelegate() const 00094 { 00095 return d_func()->uiDelegate; 00096 } 00097 00098 KJob::Capabilities KJob::capabilities() const 00099 { 00100 return d_func()->capabilities; 00101 } 00102 00103 bool KJob::isSuspended() const 00104 { 00105 return d_func()->suspended; 00106 } 00107 00108 bool KJob::kill( KillVerbosity verbosity ) 00109 { 00110 Q_D(KJob); 00111 if ( doKill() ) 00112 { 00113 setError( KilledJobError ); 00114 00115 if ( verbosity!=Quietly ) 00116 { 00117 emitResult(); 00118 } 00119 else 00120 { 00121 // If we are displaying a progress dialog, remove it first. 00122 d->isFinished = true; 00123 emit finished(this); 00124 00125 if ( isAutoDelete() ) 00126 deleteLater(); 00127 } 00128 00129 return true; 00130 } 00131 else 00132 { 00133 return false; 00134 } 00135 } 00136 00137 bool KJob::suspend() 00138 { 00139 Q_D(KJob); 00140 if ( !d->suspended ) 00141 { 00142 if ( doSuspend() ) 00143 { 00144 d->suspended = true; 00145 emit suspended(this); 00146 00147 return true; 00148 } 00149 } 00150 00151 return false; 00152 } 00153 00154 bool KJob::resume() 00155 { 00156 Q_D(KJob); 00157 if ( d->suspended ) 00158 { 00159 if ( doResume() ) 00160 { 00161 d->suspended = false; 00162 emit resumed(this); 00163 00164 return true; 00165 } 00166 } 00167 00168 return false; 00169 } 00170 00171 bool KJob::doKill() 00172 { 00173 return false; 00174 } 00175 00176 bool KJob::doSuspend() 00177 { 00178 return false; 00179 } 00180 00181 bool KJob::doResume() 00182 { 00183 return false; 00184 } 00185 00186 void KJob::setCapabilities( KJob::Capabilities capabilities ) 00187 { 00188 Q_D(KJob); 00189 d->capabilities = capabilities; 00190 } 00191 00192 bool KJob::exec() 00193 { 00194 Q_D(KJob); 00195 // Usually this job would delete itself, via deleteLater() just after 00196 // emitting result() (unless configured otherwise). Since we use an event 00197 // loop below, that event loop will process the deletion event and we'll 00198 // have been deleted when exec() returns. This crashes, so temporarily 00199 // suspend autodeletion and manually do it afterwards. 00200 const bool wasAutoDelete = isAutoDelete(); 00201 setAutoDelete( false ); 00202 00203 Q_ASSERT( ! d->eventLoop ); 00204 00205 QEventLoop loop( this ); 00206 d->eventLoop = &loop; 00207 00208 start(); 00209 if( !d->isFinished ) { 00210 d->eventLoop->exec(QEventLoop::ExcludeUserInputEvents); 00211 } 00212 d->eventLoop = 0; 00213 00214 if ( wasAutoDelete ) { 00215 deleteLater(); 00216 } 00217 return ( d->error == NoError ); 00218 } 00219 00220 int KJob::error() const 00221 { 00222 return d_func()->error; 00223 } 00224 00225 QString KJob::errorText() const 00226 { 00227 return d_func()->errorText; 00228 } 00229 00230 QString KJob::errorString() const 00231 { 00232 return d_func()->errorText; 00233 } 00234 00235 qulonglong KJob::processedAmount(Unit unit) const 00236 { 00237 return d_func()->processedAmount[unit]; 00238 } 00239 00240 qulonglong KJob::totalAmount(Unit unit) const 00241 { 00242 return d_func()->totalAmount[unit]; 00243 } 00244 00245 unsigned long KJob::percent() const 00246 { 00247 return d_func()->percentage; 00248 } 00249 00250 void KJob::setError( int errorCode ) 00251 { 00252 Q_D(KJob); 00253 d->error = errorCode; 00254 } 00255 00256 void KJob::setErrorText( const QString &errorText ) 00257 { 00258 Q_D(KJob); 00259 d->errorText = errorText; 00260 } 00261 00262 void KJob::setProcessedAmount(Unit unit, qulonglong amount) 00263 { 00264 Q_D(KJob); 00265 bool should_emit = (d->processedAmount[unit] != amount); 00266 00267 d->processedAmount[unit] = amount; 00268 00269 if ( should_emit ) 00270 { 00271 emit processedAmount(this, unit, amount); 00272 if (unit==d->progressUnit) { 00273 emit processedSize(this, amount); 00274 emitPercent(d->processedAmount[unit], d->totalAmount[unit]); 00275 } 00276 } 00277 } 00278 00279 void KJob::setTotalAmount(Unit unit, qulonglong amount) 00280 { 00281 Q_D(KJob); 00282 bool should_emit = (d->totalAmount[unit] != amount); 00283 00284 d->totalAmount[unit] = amount; 00285 00286 if ( should_emit ) 00287 { 00288 emit totalAmount(this, unit, amount); 00289 if (unit==d->progressUnit) { 00290 emit totalSize(this, amount); 00291 emitPercent(d->processedAmount[unit], d->totalAmount[unit]); 00292 } 00293 } 00294 } 00295 00296 void KJob::setPercent( unsigned long percentage ) 00297 { 00298 Q_D(KJob); 00299 if ( d->percentage!=percentage ) 00300 { 00301 d->percentage = percentage; 00302 emit percent( this, percentage ); 00303 } 00304 } 00305 00306 void KJob::emitResult() 00307 { 00308 Q_D(KJob); 00309 d->isFinished = true; 00310 00311 if ( d->eventLoop ) { 00312 d->eventLoop->quit(); 00313 } 00314 00315 // If we are displaying a progress dialog, remove it first. 00316 emit finished( this ); 00317 00318 emit result( this ); 00319 00320 if ( isAutoDelete() ) 00321 deleteLater(); 00322 } 00323 00324 void KJob::emitPercent( qulonglong processedAmount, qulonglong totalAmount ) 00325 { 00326 Q_D(KJob); 00327 // calculate percents 00328 if (totalAmount) { 00329 unsigned long oldPercentage = d->percentage; 00330 d->percentage = (unsigned long)(( (float)(processedAmount) / (float)(totalAmount) ) * 100.0); 00331 if ( d->percentage != oldPercentage ) { 00332 emit percent( this, d->percentage ); 00333 } 00334 } 00335 } 00336 00337 void KJob::emitSpeed(unsigned long value) 00338 { 00339 Q_D(KJob); 00340 if (!d->speedTimer) { 00341 d->speedTimer = new QTimer(this); 00342 connect(d->speedTimer, SIGNAL(timeout()), SLOT(_k_speedTimeout())); 00343 } 00344 00345 emit speed(this, value); 00346 d->speedTimer->start(5000); // 5 seconds interval should be enough 00347 } 00348 00349 void KJobPrivate::_k_speedTimeout() 00350 { 00351 Q_Q(KJob); 00352 // send 0 and stop the timer 00353 // timer will be restarted only when we receive another speed event 00354 emit q->speed(q, 0); 00355 speedTimer->stop(); 00356 } 00357 00358 bool KJob::isAutoDelete() const 00359 { 00360 Q_D(const KJob); 00361 return d->isAutoDelete; 00362 } 00363 00364 void KJob::setAutoDelete( bool autodelete ) 00365 { 00366 Q_D(KJob); 00367 d->isAutoDelete = autodelete; 00368 } 00369 00370 #include "kjob.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:05:02 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:05:02 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.