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 delete d_ptr->speedTimer; 00068 delete d_ptr->uiDelegate; 00069 delete d_ptr; 00070 00071 KGlobal::deref(); 00072 } 00073 00074 void KJob::setUiDelegate( KJobUiDelegate *delegate ) 00075 { 00076 Q_D(KJob); 00077 if ( delegate == 0 || delegate->setJob( this ) ) 00078 { 00079 delete d->uiDelegate; 00080 d->uiDelegate = delegate; 00081 00082 if ( d->uiDelegate ) 00083 { 00084 d->uiDelegate->connectJob( this ); 00085 } 00086 } 00087 } 00088 00089 KJobUiDelegate *KJob::uiDelegate() const 00090 { 00091 return d_func()->uiDelegate; 00092 } 00093 00094 KJob::Capabilities KJob::capabilities() const 00095 { 00096 return d_func()->capabilities; 00097 } 00098 00099 bool KJob::isSuspended() const 00100 { 00101 return d_func()->suspended; 00102 } 00103 00104 bool KJob::kill( KillVerbosity verbosity ) 00105 { 00106 if ( doKill() ) 00107 { 00108 setError( KilledJobError ); 00109 00110 if ( verbosity!=Quietly ) 00111 { 00112 emitResult(); 00113 } 00114 else 00115 { 00116 // If we are displaying a progress dialog, remove it first. 00117 emit finished(this); 00118 00119 if ( isAutoDelete() ) 00120 deleteLater(); 00121 } 00122 00123 return true; 00124 } 00125 else 00126 { 00127 return false; 00128 } 00129 } 00130 00131 bool KJob::suspend() 00132 { 00133 Q_D(KJob); 00134 if ( !d->suspended ) 00135 { 00136 if ( doSuspend() ) 00137 { 00138 d->suspended = true; 00139 emit suspended(this); 00140 00141 return true; 00142 } 00143 } 00144 00145 return false; 00146 } 00147 00148 bool KJob::resume() 00149 { 00150 Q_D(KJob); 00151 if ( d->suspended ) 00152 { 00153 if ( doResume() ) 00154 { 00155 d->suspended = false; 00156 emit resumed(this); 00157 00158 return true; 00159 } 00160 } 00161 00162 return false; 00163 } 00164 00165 bool KJob::doKill() 00166 { 00167 return false; 00168 } 00169 00170 bool KJob::doSuspend() 00171 { 00172 return false; 00173 } 00174 00175 bool KJob::doResume() 00176 { 00177 return false; 00178 } 00179 00180 void KJob::setCapabilities( KJob::Capabilities capabilities ) 00181 { 00182 Q_D(KJob); 00183 d->capabilities = capabilities; 00184 } 00185 00186 bool KJob::exec() 00187 { 00188 Q_D(KJob); 00189 // Usually this job would delete itself, via deleteLater() just after 00190 // emitting result() (unless configured otherwise). Since we use an event 00191 // loop below, that event loop will process the deletion event and we'll 00192 // have been deleted when exec() returns. This crashes, so temporarily 00193 // suspend autodeletion and manually do it afterwards. 00194 const bool wasAutoDelete = isAutoDelete(); 00195 setAutoDelete( false ); 00196 00197 Q_ASSERT( ! d->eventLoop ); 00198 00199 QEventLoop loop( this ); 00200 d->eventLoop = &loop; 00201 00202 start(); 00203 if( !d->isFinished ) { 00204 d->eventLoop->exec(QEventLoop::ExcludeUserInputEvents); 00205 } 00206 d->eventLoop = 0; 00207 00208 if ( wasAutoDelete ) { 00209 deleteLater(); 00210 } 00211 return ( d->error == NoError ); 00212 } 00213 00214 int KJob::error() const 00215 { 00216 return d_func()->error; 00217 } 00218 00219 QString KJob::errorText() const 00220 { 00221 return d_func()->errorText; 00222 } 00223 00224 QString KJob::errorString() const 00225 { 00226 return d_func()->errorText; 00227 } 00228 00229 qulonglong KJob::processedAmount(Unit unit) const 00230 { 00231 return d_func()->processedAmount[unit]; 00232 } 00233 00234 qulonglong KJob::totalAmount(Unit unit) const 00235 { 00236 return d_func()->totalAmount[unit]; 00237 } 00238 00239 unsigned long KJob::percent() const 00240 { 00241 return d_func()->percentage; 00242 } 00243 00244 void KJob::setError( int errorCode ) 00245 { 00246 Q_D(KJob); 00247 d->error = errorCode; 00248 } 00249 00250 void KJob::setErrorText( const QString &errorText ) 00251 { 00252 Q_D(KJob); 00253 d->errorText = errorText; 00254 } 00255 00256 void KJob::setProcessedAmount(Unit unit, qulonglong amount) 00257 { 00258 Q_D(KJob); 00259 bool should_emit = (d->processedAmount[unit] != amount); 00260 00261 d->processedAmount[unit] = amount; 00262 00263 if ( should_emit ) 00264 { 00265 emit processedAmount(this, unit, amount); 00266 if (unit==d->progressUnit) { 00267 emit processedSize(this, amount); 00268 emitPercent(d->processedAmount[unit], d->totalAmount[unit]); 00269 } 00270 } 00271 } 00272 00273 void KJob::setTotalAmount(Unit unit, qulonglong amount) 00274 { 00275 Q_D(KJob); 00276 bool should_emit = (d->totalAmount[unit] != amount); 00277 00278 d->totalAmount[unit] = amount; 00279 00280 if ( should_emit ) 00281 { 00282 emit totalAmount(this, unit, amount); 00283 if (unit==d->progressUnit) { 00284 emit totalSize(this, amount); 00285 emitPercent(d->processedAmount[unit], d->totalAmount[unit]); 00286 } 00287 } 00288 } 00289 00290 void KJob::setPercent( unsigned long percentage ) 00291 { 00292 Q_D(KJob); 00293 if ( d->percentage!=percentage ) 00294 { 00295 d->percentage = percentage; 00296 emit percent( this, percentage ); 00297 } 00298 } 00299 00300 void KJob::emitResult() 00301 { 00302 Q_D(KJob); 00303 d->isFinished = true; 00304 00305 if ( d->eventLoop ) { 00306 d->eventLoop->quit(); 00307 } 00308 00309 // If we are displaying a progress dialog, remove it first. 00310 emit finished( this ); 00311 00312 emit result( this ); 00313 00314 if ( isAutoDelete() ) 00315 deleteLater(); 00316 } 00317 00318 void KJob::emitPercent( qulonglong processedAmount, qulonglong totalAmount ) 00319 { 00320 Q_D(KJob); 00321 // calculate percents 00322 if (totalAmount) { 00323 unsigned long oldPercentage = d->percentage; 00324 d->percentage = (unsigned long)(( (float)(processedAmount) / (float)(totalAmount) ) * 100.0); 00325 if ( d->percentage != oldPercentage ) { 00326 emit percent( this, d->percentage ); 00327 } 00328 } 00329 } 00330 00331 void KJob::emitSpeed(unsigned long value) 00332 { 00333 Q_D(KJob); 00334 if (!d->speedTimer) { 00335 d->speedTimer = new QTimer(this); 00336 connect(d->speedTimer, SIGNAL(timeout()), SLOT(_k_speedTimeout())); 00337 } 00338 00339 emit speed(this, value); 00340 d->speedTimer->start(5000); // 5 seconds interval should be enough 00341 } 00342 00343 void KJobPrivate::_k_speedTimeout() 00344 { 00345 Q_Q(KJob); 00346 // send 0 and stop the timer 00347 // timer will be restarted only when we receive another speed event 00348 emit q->speed(q, 0); 00349 speedTimer->stop(); 00350 } 00351 00352 bool KJob::isAutoDelete() const 00353 { 00354 Q_D(const KJob); 00355 return d->isAutoDelete; 00356 } 00357 00358 void KJob::setAutoDelete( bool autodelete ) 00359 { 00360 Q_D(KJob); 00361 d->isAutoDelete = autodelete; 00362 } 00363 00364 #include "kjob.moc"
KDE 4.6 API Reference