00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <QApplication>
00027 # include <QGenericReturnArgument>
00028 # include <QKeyEvent>
00029 # include <QMessageBox>
00030 # include <QMetaObject>
00031 # include <QStatusBar>
00032 # include <QThread>
00033 # include <QTime>
00034 # include <QTimer>
00035 #endif
00036
00037 #include "ProgressBar.h"
00038 #include "MainWindow.h"
00039 #include "WaitCursor.h"
00040
00041 using namespace Gui;
00042
00043
00044 namespace Gui {
00045 struct SequencerPrivate
00046 {
00047 ProgressBar* bar;
00048 WaitCursor* waitCursor;
00049 QTime measureTime;
00050 QTime progressTime;
00051 QString text;
00052 bool guiThread;
00053 };
00054
00055 struct ProgressBarPrivate
00056 {
00057 QTimer* delayShowTimer;
00058 int minimumDuration;
00059 int observeEventFilter;
00060
00061 bool isModalDialog(QObject* o) const
00062 {
00063 QWidget* parent = qobject_cast<QWidget*>(o);
00064 while (parent) {
00065 QMessageBox* dlg = qobject_cast<QMessageBox*>(parent);
00066 if (dlg && dlg->isModal())
00067 return true;
00068 parent = parent->parentWidget();
00069 }
00070
00071 return false;
00072 }
00073 };
00074 }
00075
00076 Sequencer* Sequencer::_pclSingleton = 0;
00077
00078 Sequencer* Sequencer::instance()
00079 {
00080
00081 if (!_pclSingleton)
00082 {
00083 _pclSingleton = new Sequencer();
00084 }
00085
00086 return _pclSingleton;
00087 }
00088
00089 Sequencer::Sequencer ()
00090 {
00091 d = new SequencerPrivate;
00092 d->bar = 0;
00093 d->waitCursor = 0;
00094 d->guiThread = true;
00095 }
00096
00097 Sequencer::~Sequencer ()
00098 {
00099 delete d;
00100 }
00101
00102 void Sequencer::pause()
00103 {
00104 QThread *currentThread = QThread::currentThread();
00105 QThread *thr = d->bar->thread();
00106 if (thr != currentThread)
00107 return;
00108
00109
00110 d->bar->leaveControlEvents();
00111 d->waitCursor->restoreCursor();
00112 QApplication::setOverrideCursor(Qt::ArrowCursor);
00113 }
00114
00115 void Sequencer::resume()
00116 {
00117 QThread *currentThread = QThread::currentThread();
00118 QThread *thr = d->bar->thread();
00119 if (thr != currentThread)
00120 return;
00121
00122 QApplication::restoreOverrideCursor();
00123 d->waitCursor->setWaitCursor();
00124
00125 d->bar->enterControlEvents();
00126 }
00127
00128 void Sequencer::startStep()
00129 {
00130 QThread *currentThread = QThread::currentThread();
00131 QThread *thr = d->bar->thread();
00132 if (thr != currentThread) {
00133 d->guiThread = false;
00134 d->bar->setRange(0, (int)nTotalSteps);
00135 if (nTotalSteps == 0) {
00136 d->progressTime.start();
00137 }
00138 d->measureTime.start();
00139 QMetaObject::invokeMethod(d->bar, "aboutToShow", Qt::QueuedConnection);
00140 }
00141 else {
00142 d->guiThread = true;
00143 d->bar->setRange(0, (int)nTotalSteps);
00144 if (nTotalSteps == 0) {
00145 d->progressTime.start();
00146 }
00147
00148 d->measureTime.start();
00149 d->waitCursor = new Gui::WaitCursor;
00150 d->bar->enterControlEvents();
00151 d->bar->aboutToShow();
00152 }
00153 }
00154
00155 void Sequencer::nextStep(bool canAbort)
00156 {
00157 QThread *currentThread = QThread::currentThread();
00158 QThread *thr = d->bar->thread();
00159 if (thr != currentThread) {
00160 setValue((int)nProgress+1);
00161 }
00162 else {
00163 if (wasCanceled() && canAbort) {
00164
00165 pause();
00166 bool ok = d->bar->canAbort();
00167
00168 resume();
00169
00170
00171 if ( ok ) {
00172 abort();
00173 } else {
00174 rejectCancel();
00175 setValue((int)nProgress+1);
00176 }
00177 }
00178 else {
00179 setValue((int)nProgress+1);
00180 }
00181 }
00182 }
00183
00184 void Sequencer::setProgress(size_t step)
00185 {
00186 d->bar->show();
00187 setValue((int)step);
00188 }
00189
00190 void Sequencer::setValue(int step)
00191 {
00192 QThread *currentThread = QThread::currentThread();
00193 QThread *thr = d->bar->thread();
00194
00195 if (nTotalSteps == 0) {
00196 int elapsed = d->progressTime.elapsed();
00197
00198 if (elapsed > 500) {
00199 d->progressTime.restart();
00200 if (thr != currentThread) {
00201 QMetaObject::invokeMethod(d->bar, "setValue", Qt::QueuedConnection,
00202 QGenericReturnArgument(), Q_ARG(int,d->bar->value()+1));
00203 }
00204 else {
00205 d->bar->setValue(d->bar->value()+1);
00206 qApp->processEvents();
00207 }
00208 }
00209 }
00210 else {
00211 if (thr != currentThread) {
00212 QMetaObject::invokeMethod(d->bar, "setValue", Qt::QueuedConnection,
00213 QGenericReturnArgument(), Q_ARG(int,step));
00214 if (d->bar->isVisible())
00215 showRemainingTime();
00216 }
00217 else {
00218 d->bar->setValue(step);
00219 if (d->bar->isVisible())
00220 showRemainingTime();
00221 d->bar->resetObserveEventFilter();
00222 qApp->processEvents();
00223 }
00224 }
00225 }
00226
00227 void Sequencer::showRemainingTime()
00228 {
00229 QThread *currentThread = QThread::currentThread();
00230 QThread *thr = d->bar->thread();
00231
00232 int elapsed = d->measureTime.elapsed();
00233 int progress = d->bar->value();
00234 int totalSteps = d->bar->maximum() - d->bar->minimum();
00235
00236 QString txt = d->text;
00237
00238 if (progress * 20 > totalSteps || elapsed > 5000) {
00239 int rest = (int) ( (double) totalSteps/progress * elapsed ) - elapsed;
00240
00241
00242 if (elapsed > 1000 && rest > 100) {
00243 QTime time( 0,0, 0);
00244 time = time.addSecs( rest/1000 );
00245 QString remain = Gui::ProgressBar::tr("Remaining: %1").arg(time.toString());
00246 QString status = QString::fromAscii("%1\t[%2]").arg(txt).arg(remain);
00247
00248 if (thr != currentThread) {
00249 QMetaObject::invokeMethod(getMainWindow()->statusBar(), "showMessage",
00250 Qt::QueuedConnection,
00251 QGenericReturnArgument(),
00252 Q_ARG(QString,status));
00253 }
00254 else {
00255 getMainWindow()->statusBar()->showMessage(status);
00256 }
00257 }
00258 }
00259 }
00260
00261 void Sequencer::resetData()
00262 {
00263 QThread *currentThread = QThread::currentThread();
00264 QThread *thr = d->bar->thread();
00265 if (thr != currentThread) {
00266 QMetaObject::invokeMethod(d->bar, "reset", Qt::QueuedConnection);
00267 QMetaObject::invokeMethod(d->bar, "hide", Qt::QueuedConnection);
00268 QMetaObject::invokeMethod(getMainWindow()->statusBar(), "showMessage",
00269 Qt::QueuedConnection,
00270 QGenericReturnArgument(),
00271 Q_ARG(QString,QString()));
00272 QMetaObject::invokeMethod(getMainWindow(), "setPaneText",
00273 Qt::QueuedConnection,
00274 QGenericReturnArgument(),
00275 Q_ARG(int,1),
00276 Q_ARG(QString,QString()));
00277 }
00278 else {
00279 d->bar->reset();
00280
00281
00282
00283 d->bar->hide();
00284 delete d->waitCursor;
00285 d->waitCursor = 0;
00286 d->bar->leaveControlEvents();
00287 getMainWindow()->setPaneText(1, QString());
00288 getMainWindow()->statusBar()->showMessage(QString());
00289 }
00290
00291 SequencerBase::resetData();
00292 }
00293
00294 void Sequencer::abort()
00295 {
00296
00297 resetData();
00298 Base::AbortException exc("Aborting...");
00299 throw exc;
00300 }
00301
00302 void Sequencer::setText (const char* pszTxt)
00303 {
00304 QThread *currentThread = QThread::currentThread();
00305 QThread *thr = d->bar->thread();
00306
00307
00308 d->text = pszTxt ? QString::fromUtf8(pszTxt) : QLatin1String("");
00309 if (thr != currentThread) {
00310 QMetaObject::invokeMethod(getMainWindow()->statusBar(), "showMessage",
00311 Qt::QueuedConnection,
00312 QGenericReturnArgument(),
00313 Q_ARG(QString,d->text));
00314 }
00315 else {
00316 getMainWindow()->statusBar()->showMessage(d->text);
00317 }
00318 }
00319
00320 bool Sequencer::isBlocking() const
00321 {
00322 return d->guiThread;
00323 }
00324
00325 QProgressBar* Sequencer::getProgressBar(QWidget* parent)
00326 {
00327 if (!d->bar)
00328 d->bar = new ProgressBar(this, parent);
00329 return d->bar;
00330 }
00331
00332
00333
00334
00335
00336 ProgressBar::ProgressBar (Sequencer* s, QWidget * parent)
00337 : QProgressBar(parent), sequencer(s)
00338 {
00339 d = new Gui::ProgressBarPrivate;
00340 d->minimumDuration = 2000;
00341 d->delayShowTimer = new QTimer(this);
00342 d->delayShowTimer->setSingleShot(true);
00343 connect(d->delayShowTimer, SIGNAL(timeout()), this, SLOT(delayedShow()));
00344 d->observeEventFilter = 0;
00345
00346 setFixedWidth(120);
00347
00348
00349 setAlignment(Qt::AlignHCenter);
00350 hide();
00351 }
00352
00353 ProgressBar::~ProgressBar ()
00354 {
00355 disconnect(d->delayShowTimer, SIGNAL(timeout()), this, SLOT(delayedShow()));
00356 delete d->delayShowTimer;
00357 delete d;
00358 }
00359
00360 int ProgressBar::minimumDuration() const
00361 {
00362 return d->minimumDuration;
00363 }
00364
00365 void ProgressBar::setMinimumDuration (int ms)
00366 {
00367 if (value() == 0)
00368 {
00369 d->delayShowTimer->stop();
00370 d->delayShowTimer->start(ms);
00371 }
00372
00373 d->minimumDuration = ms;
00374 }
00375
00376 void ProgressBar::aboutToShow()
00377 {
00378
00379 d->delayShowTimer->start(d->minimumDuration);
00380 }
00381
00382 void ProgressBar::delayedShow()
00383 {
00384 if (!isVisible() && !sequencer->wasCanceled() && sequencer->isRunning())
00385 show();
00386 }
00387
00388 bool ProgressBar::canAbort() const
00389 {
00390 int ret = QMessageBox::question(getMainWindow(),tr("Aborting"),
00391 tr("Do you really want to abort the operation?"), QMessageBox::Yes,
00392 QMessageBox::No|QMessageBox::Default);
00393
00394 return (ret == QMessageBox::Yes) ? true : false;
00395 }
00396
00397 void ProgressBar::showEvent(QShowEvent* e)
00398 {
00399 QProgressBar::showEvent(e);
00400 d->delayShowTimer->stop();
00401 }
00402
00403 void ProgressBar::hideEvent(QHideEvent* e)
00404 {
00405 QProgressBar::hideEvent(e);
00406 d->delayShowTimer->stop();
00407 }
00408
00409 void ProgressBar::resetObserveEventFilter()
00410 {
00411 d->observeEventFilter = 0;
00412 }
00413
00414 void ProgressBar::enterControlEvents()
00415 {
00416 qApp->installEventFilter(this);
00417
00418
00419
00420 grabKeyboard();
00421 }
00422
00423 void ProgressBar::leaveControlEvents()
00424 {
00425 qApp->removeEventFilter(this);
00426
00427
00428 releaseKeyboard();
00429 }
00430
00431 bool ProgressBar::eventFilter(QObject* o, QEvent* e)
00432 {
00433 if (sequencer->isRunning() && e != 0) {
00434 switch ( e->type() )
00435 {
00436
00437 case QEvent::KeyPress:
00438 {
00439 QKeyEvent* ke = (QKeyEvent*)e;
00440 if (ke->key() == Qt::Key_Escape) {
00441
00442 if (d->observeEventFilter > 50) {
00443
00444 if (ke->modifiers() & (Qt::ControlModifier | Qt::AltModifier)) {
00445 sequencer->resetData();
00446 return true;
00447 }
00448 }
00449
00450
00451 sequencer->tryToCancel();
00452 }
00453
00454 return true;
00455 } break;
00456
00457
00458 case QEvent::KeyRelease:
00459 case QEvent::Enter:
00460 case QEvent::Leave:
00461 case QEvent::MouseButtonDblClick:
00462 case QEvent::ContextMenu:
00463 {
00464 return true;
00465 } break;
00466
00467
00468 case QEvent::Close:
00469 {
00470
00471
00472 if (o == getMainWindow()) {
00473 e->ignore();
00474 return true;
00475 }
00476 } break;
00477
00478
00479 case QEvent::MouseButtonPress:
00480 {
00481 if (d->isModalDialog(o))
00482 return false;
00483 QApplication::beep();
00484 return true;
00485 } break;
00486
00487 default:
00488 {
00489 } break;
00490 }
00491
00492 d->observeEventFilter++;
00493 }
00494
00495 return QProgressBar::eventFilter(o, e);
00496 }
00497
00498
00499 #include "moc_ProgressBar.cpp"