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
00026 #include "ProgressDialog.h"
00027 #include "MainWindow.h"
00028
00029
00030 using namespace Gui;
00031
00032
00033 namespace Gui {
00034 struct SequencerDialogPrivate
00035 {
00036 ProgressDialog* dlg;
00037 QTime measureTime;
00038 QTime progressTime;
00039 QString text;
00040 bool guiThread;
00041 };
00042 }
00043
00044
00045 SequencerDialog* SequencerDialog::_pclSingleton = 0;
00046
00047 SequencerDialog* SequencerDialog::instance()
00048 {
00049
00050 if (!_pclSingleton)
00051 _pclSingleton = new SequencerDialog();
00052 return _pclSingleton;
00053 }
00054
00055 SequencerDialog::SequencerDialog ()
00056 {
00057 d = new SequencerDialogPrivate;
00058 d->dlg = new ProgressDialog(this,getMainWindow());
00059 d->guiThread = true;
00060 }
00061
00062 SequencerDialog::~SequencerDialog()
00063 {
00064 delete d;
00065 }
00066
00067 void SequencerDialog::pause()
00068 {
00069 QThread *currentThread = QThread::currentThread();
00070 QThread *thr = d->dlg->thread();
00071 if (thr == currentThread)
00072
00073 d->dlg->leaveControlEvents();
00074 }
00075
00076 void SequencerDialog::resume()
00077 {
00078 QThread *currentThread = QThread::currentThread();
00079 QThread *thr = d->dlg->thread();
00080 if (thr == currentThread)
00081 d->dlg->enterControlEvents();
00082 }
00083
00084 void SequencerDialog::startStep()
00085 {
00086 QThread *currentThread = QThread::currentThread();
00087 QThread *thr = d->dlg->thread();
00088 if (thr != currentThread) {
00089 d->guiThread = false;
00090 d->dlg->setRange(0, (int)nTotalSteps);
00091 d->dlg->setModal(false);
00092 if (nTotalSteps == 0) {
00093 d->progressTime.start();
00094 }
00095
00096 d->measureTime.start();
00097 QMetaObject::invokeMethod(d->dlg, "setValue", Qt::QueuedConnection,
00098 QGenericReturnArgument(), Q_ARG(int,0));
00099 }
00100 else {
00101 d->guiThread = true;
00102 d->dlg->setRange(0, (int)nTotalSteps);
00103 d->dlg->setModal(true);
00104 if (nTotalSteps == 0) {
00105 d->progressTime.start();
00106 }
00107
00108 d->measureTime.start();
00109 d->dlg->setValue(0);
00110 d->dlg->enterControlEvents();
00111 }
00112 }
00113
00114 void SequencerDialog::nextStep(bool canAbort)
00115 {
00116 QThread *currentThread = QThread::currentThread();
00117 QThread *thr = d->dlg->thread();
00118 if (thr != currentThread) {
00119 setProgress((int)nProgress+1);
00120 }
00121 else {
00122 if (wasCanceled() && canAbort) {
00123
00124 pause();
00125 bool ok = d->dlg->canAbort();
00126
00127 resume();
00128
00129
00130 if ( ok ) {
00131 abort();
00132 } else {
00133 rejectCancel();
00134 setProgress((int)nProgress+1);
00135 }
00136 }
00137 else {
00138 setProgress((int)nProgress+1);
00139 }
00140 }
00141 }
00142
00143 void SequencerDialog::setProgress(int step)
00144 {
00145 QThread *currentThread = QThread::currentThread();
00146 QThread *thr = d->dlg->thread();
00147
00148 if (nTotalSteps == 0) {
00149 int elapsed = d->progressTime.elapsed();
00150
00151 if (elapsed > 500) {
00152 d->progressTime.restart();
00153 if (thr != currentThread) {
00154 QMetaObject::invokeMethod(d->dlg, "setValue", Qt::QueuedConnection,
00155 QGenericReturnArgument(), Q_ARG(int,d->dlg->value()+1));
00156 }
00157 else {
00158 d->dlg->setValue(d->dlg->value()+1);
00159 qApp->processEvents();
00160 }
00161 }
00162 }
00163 else {
00164 if (thr != currentThread) {
00165 QMetaObject::invokeMethod(d->dlg, "setValue", Qt::QueuedConnection,
00166 QGenericReturnArgument(), Q_ARG(int,step));
00167 if (d->dlg->isVisible())
00168 showRemainingTime();
00169 }
00170 else {
00171 d->dlg->setValue(step);
00172 if (d->dlg->isVisible())
00173 showRemainingTime();
00174 qApp->processEvents();
00175 }
00176 }
00177 }
00178
00179 void SequencerDialog::showRemainingTime()
00180 {
00181 QThread *currentThread = QThread::currentThread();
00182 QThread *thr = d->dlg->thread();
00183
00184 int elapsed = d->measureTime.elapsed();
00185 int progress = d->dlg->value();
00186 int totalSteps = d->dlg->maximum() - d->dlg->minimum();
00187
00188 QString txt = d->text;
00189
00190 if (progress * 20 > totalSteps || elapsed > 5000) {
00191 int rest = (int) ( (double) totalSteps/progress * elapsed ) - elapsed;
00192
00193
00194 if (elapsed > 1000 && rest > 100) {
00195 QTime time( 0,0, 0);
00196 time = time.addSecs( rest/1000 );
00197 QString remain = Gui::ProgressDialog::tr("Remaining: %1").arg(time.toString());
00198 QString status = QString::fromAscii("%1\t[%2]").arg(txt).arg(remain);
00199
00200 if (thr != currentThread) {
00201 QMetaObject::invokeMethod(d->dlg, "setLabelText",
00202 Qt::QueuedConnection,
00203 QGenericReturnArgument(),
00204 Q_ARG(QString,status));
00205 }
00206 else {
00207 d->dlg->setLabelText(status);
00208 }
00209 }
00210 }
00211 }
00212
00213 void SequencerDialog::resetData()
00214 {
00215 QThread *currentThread = QThread::currentThread();
00216 QThread *thr = d->dlg->thread();
00217 if (thr != currentThread) {
00218 QMetaObject::invokeMethod(d->dlg, "reset", Qt::QueuedConnection);
00219 QMetaObject::invokeMethod(d->dlg, "hide", Qt::QueuedConnection);
00220 QMetaObject::invokeMethod(d->dlg, "setLabelText",
00221 Qt::QueuedConnection,
00222 QGenericReturnArgument(),
00223 Q_ARG(QString,QString()));
00224 }
00225 else {
00226 d->dlg->reset();
00227
00228
00229
00230 d->dlg->hide();
00231 d->dlg->setLabelText(QString());
00232 d->dlg->leaveControlEvents();
00233 }
00234
00235 SequencerBase::resetData();
00236 }
00237
00238 void SequencerDialog::abort()
00239 {
00240
00241 resetData();
00242 Base::AbortException exc("Aborting...");
00243 throw exc;
00244 }
00245
00246 void SequencerDialog::setText (const char* pszTxt)
00247 {
00248 QThread *currentThread = QThread::currentThread();
00249 QThread *thr = d->dlg->thread();
00250
00251
00252 d->text = pszTxt ? QString::fromUtf8(pszTxt) : QLatin1String("");
00253 if (thr != currentThread) {
00254 QMetaObject::invokeMethod(d->dlg, "setLabelText",
00255 Qt::QueuedConnection,
00256 QGenericReturnArgument(),
00257 Q_ARG(QString,d->text));
00258 }
00259 else {
00260 d->dlg->setLabelText(d->text);
00261 }
00262 }
00263
00264 bool SequencerDialog::isBlocking() const
00265 {
00266 return d->guiThread;
00267 }
00268
00269
00270
00271
00272
00273 ProgressDialog::ProgressDialog (SequencerDialog* s, QWidget * parent)
00274 : QProgressDialog(parent, Qt::FramelessWindowHint), sequencer(s)
00275 {
00276 connect(this, SIGNAL(canceled()), this, SLOT(onCancel()));
00277 }
00278
00279 ProgressDialog::~ProgressDialog ()
00280 {
00281 }
00282
00283 void ProgressDialog::onCancel()
00284 {
00285 sequencer->tryToCancel();
00286 }
00287
00288 bool ProgressDialog::canAbort() const
00289 {
00290 int ret = QMessageBox::question(getMainWindow(),tr("Aborting"),
00291 tr("Do you really want to abort the operation?"), QMessageBox::Yes,
00292 QMessageBox::No|QMessageBox::Default);
00293
00294 return (ret == QMessageBox::Yes) ? true : false;
00295 }
00296
00297 void ProgressDialog::enterControlEvents()
00298 {
00299 qApp->installEventFilter(this);
00300
00301
00302
00303 grabKeyboard();
00304 }
00305
00306 void ProgressDialog::leaveControlEvents()
00307 {
00308 qApp->removeEventFilter(this);
00309
00310
00311 releaseKeyboard();
00312 }
00313
00314 bool ProgressDialog::eventFilter(QObject* o, QEvent* e)
00315 {
00316 if (sequencer->isRunning() && e != 0) {
00317 switch ( e->type() )
00318 {
00319
00320 case QEvent::KeyPress:
00321 {
00322 QKeyEvent* ke = (QKeyEvent*)e;
00323 if (ke->key() == Qt::Key_Escape) {
00324
00325 this->cancel();
00326 }
00327
00328 return true;
00329 } break;
00330
00331
00332 case QEvent::KeyRelease:
00333 case QEvent::Enter:
00334 case QEvent::Leave:
00335 case QEvent::MouseButtonDblClick:
00336 case QEvent::ContextMenu:
00337 {
00338 return true;
00339 } break;
00340
00341
00342 case QEvent::Close:
00343 {
00344
00345
00346 if (o == getMainWindow()) {
00347 e->ignore();
00348 return true;
00349 }
00350 } break;
00351
00352
00353 case QEvent::MouseButtonPress:
00354 {
00355 QApplication::beep();
00356 return true;
00357 } break;
00358
00359 default:
00360 {
00361 } break;
00362 }
00363 }
00364
00365 return QProgressDialog::eventFilter(o, e);
00366 }
00367
00368 #include "moc_ProgressDialog.cpp"