23
#include "PreCompiled.h"
25
# include <QApplication>
26
# include <QElapsedTimer>
28
# include <QMessageBox>
29
# include <QMetaObject>
36
#include "ProgressBar.h"
37
#include "MainWindow.h"
38
#include "ProgressDialog.h"
39
#include "WaitCursor.h"
46
struct SequencerBarPrivate
49
WaitCursor* waitCursor;
50
QElapsedTimer measureTime;
51
QElapsedTimer progressTime;
52
QElapsedTimer checkAbortTime;
57
struct ProgressBarPrivate
59
QTimer* delayShowTimer;
61
int observeEventFilter;
63
bool isModalDialog(QObject* o) const
65
QWidget* parent = qobject_cast<QWidget*>(o);
67
QWindow* window = qobject_cast<QWindow*>(o);
69
parent = QWidget::find(window->winId());
72
auto* dlg = qobject_cast<QMessageBox*>(parent);
73
if (dlg && dlg->isModal())
75
auto* pd = qobject_cast<QProgressDialog*>(parent);
78
parent = parent->parentWidget();
86
SequencerBar* SequencerBar::_pclSingleton = nullptr;
88
SequencerBar* SequencerBar::instance()
93
_pclSingleton = new SequencerBar();
99
SequencerBar::SequencerBar()
101
d = new SequencerBarPrivate;
103
d->waitCursor = nullptr;
107
SequencerBar::~SequencerBar()
112
void SequencerBar::pause()
114
QThread *currentThread = QThread::currentThread();
115
QThread *thr = d->bar->thread();
116
d->bar->leaveControlEvents(d->guiThread);
117
if (thr != currentThread)
121
d->waitCursor->restoreCursor();
122
QApplication::setOverrideCursor(Qt::ArrowCursor);
125
void SequencerBar::resume()
127
QThread *currentThread = QThread::currentThread();
128
QThread *thr = d->bar->thread();
129
if (thr == currentThread) {
130
QApplication::restoreOverrideCursor();
131
d->waitCursor->setWaitCursor();
135
d->bar->enterControlEvents(d->guiThread);
138
void SequencerBar::startStep()
140
QThread *currentThread = QThread::currentThread();
141
QThread *thr = d->bar->thread();
142
if (thr != currentThread) {
143
d->guiThread = false;
144
QMetaObject::invokeMethod(d->bar, "setRangeEx", Qt::QueuedConnection,
145
Q_ARG(int, 0), Q_ARG(int, (int)nTotalSteps));
146
d->progressTime.start();
147
d->checkAbortTime.start();
148
d->measureTime.start();
149
QMetaObject::invokeMethod(d->bar, "aboutToShow", Qt::QueuedConnection);
150
d->bar->enterControlEvents(d->guiThread);
154
d->bar->setRangeEx(0, (int)nTotalSteps);
155
d->progressTime.start();
156
d->checkAbortTime.start();
157
d->measureTime.start();
158
d->waitCursor = new Gui::WaitCursor;
159
d->bar->enterControlEvents(d->guiThread);
160
d->bar->aboutToShow();
164
void SequencerBar::checkAbort()
166
if (d->bar->thread() != QThread::currentThread())
168
if (!wasCanceled()) {
169
if(d->checkAbortTime.elapsed() < 500)
171
d->checkAbortTime.restart();
172
qApp->processEvents();
177
bool ok = d->bar->canAbort();
189
void SequencerBar::nextStep(bool canAbort)
191
QThread *currentThread = QThread::currentThread();
192
QThread *thr = d->bar->thread();
193
if (thr != currentThread) {
194
if (wasCanceled() && canAbort) {
198
setValue((int)nProgress + 1);
202
if (wasCanceled() && canAbort) {
205
bool ok = d->bar->canAbort();
214
setValue((int)nProgress+1);
218
setValue((int)nProgress+1);
223
void SequencerBar::setProgress(size_t step)
225
QThread* currentThread = QThread::currentThread();
226
QThread* thr = d->bar->thread();
227
if (thr != currentThread) {
228
QMetaObject::invokeMethod(d->bar, "show", Qt::QueuedConnection);
237
void SequencerBar::setValue(int step)
239
QThread *currentThread = QThread::currentThread();
240
QThread *thr = d->bar->thread();
242
if (nTotalSteps == 0) {
243
int elapsed = d->progressTime.elapsed();
246
d->progressTime.restart();
247
if (thr != currentThread) {
248
QMetaObject::invokeMethod(d->bar, "setValueEx", Qt::QueuedConnection,
249
Q_ARG(int,d->bar->value()+1));
252
d->bar->setValueEx(d->bar->value()+1);
253
qApp->processEvents();
258
int elapsed = d->progressTime.elapsed();
261
d->progressTime.restart();
262
if (thr != currentThread) {
263
QMetaObject::invokeMethod(d->bar, "setValueEx", Qt::QueuedConnection,
265
if (d->bar->isVisible())
269
d->bar->setValueEx(step);
270
if (d->bar->isVisible())
272
d->bar->resetObserveEventFilter();
273
qApp->processEvents();
279
void SequencerBar::showRemainingTime()
281
QThread *currentThread = QThread::currentThread();
282
QThread *thr = d->bar->thread();
284
int elapsed = d->measureTime.elapsed();
285
int progress = d->bar->value();
286
int totalSteps = d->bar->maximum() - d->bar->minimum();
288
QString txt = d->text;
290
if (progress * 20 > totalSteps || elapsed > 5000) {
291
int rest = (int) ( (double) totalSteps/progress * elapsed ) - elapsed;
294
if (elapsed > 1000 && rest > 100) {
296
time = time.addSecs( rest/1000 );
297
QString remain = Gui::ProgressBar::tr("Remaining: %1").arg(time.toString());
298
QString status = QString::fromLatin1("%1\t[%2]").arg(txt, remain);
300
if (thr != currentThread) {
301
QMetaObject::invokeMethod(getMainWindow(), "showMessage",
302
Qt::QueuedConnection,
303
Q_ARG(QString,status));
306
getMainWindow()->showMessage(status);
312
void SequencerBar::resetData()
314
QThread *currentThread = QThread::currentThread();
315
QThread *thr = d->bar->thread();
316
if (thr != currentThread) {
317
QMetaObject::invokeMethod(d->bar, "resetEx", Qt::QueuedConnection);
318
QMetaObject::invokeMethod(d->bar, "aboutToHide", Qt::QueuedConnection);
319
QMetaObject::invokeMethod(getMainWindow(), "showMessage",
320
Qt::QueuedConnection,
321
Q_ARG(QString,QString()));
322
QMetaObject::invokeMethod(getMainWindow(), "setPaneText",
323
Qt::QueuedConnection,
325
Q_ARG(QString,QString()));
326
d->bar->leaveControlEvents(d->guiThread);
333
d->bar->aboutToHide();
334
delete d->waitCursor;
335
d->waitCursor = nullptr;
336
d->bar->leaveControlEvents(d->guiThread);
337
getMainWindow()->setPaneText(1, QString());
338
getMainWindow()->showMessage(QString());
341
SequencerBase::resetData();
344
void SequencerBar::abort()
348
Base::AbortException exc("User aborted");
352
void SequencerBar::setText (const char* pszTxt)
354
QThread *currentThread = QThread::currentThread();
355
QThread *thr = d->bar->thread();
358
d->text = pszTxt ? QString::fromUtf8(pszTxt) : QLatin1String("");
359
if (thr != currentThread) {
360
QMetaObject::invokeMethod(getMainWindow(), "showMessage",
361
Qt::QueuedConnection,
362
Q_ARG(QString,d->text));
365
getMainWindow()->showMessage(d->text);
369
bool SequencerBar::isBlocking() const
374
QProgressBar* SequencerBar::getProgressBar(QWidget* parent)
377
d->bar = new ProgressBar(this, parent);
385
ProgressBar::ProgressBar (SequencerBar* s, QWidget * parent)
386
: QProgressBar(parent), sequencer(s)
388
#ifdef QT_WINEXTRAS_LIB
389
m_taskbarButton = nullptr;
390
m_taskbarButton = nullptr;
392
d = new Gui::ProgressBarPrivate;
393
d->minimumDuration = 2000;
394
d->delayShowTimer = new QTimer(this);
395
d->delayShowTimer->setSingleShot(true);
396
connect(d->delayShowTimer, &QTimer::timeout, this, &ProgressBar::delayedShow);
397
d->observeEventFilter = 0;
402
setAlignment(Qt::AlignHCenter);
406
ProgressBar::~ProgressBar ()
408
disconnect(d->delayShowTimer, &QTimer::timeout, this, &ProgressBar::delayedShow);
409
delete d->delayShowTimer;
413
int ProgressBar::minimumDuration() const
415
return d->minimumDuration;
418
void ProgressBar::resetEx()
420
QProgressBar::reset();
421
#ifdef QT_WINEXTRAS_LIB
422
setupTaskBarProgress();
423
m_taskbarProgress->reset();
427
void ProgressBar::setRangeEx(int minimum, int maximum)
429
QProgressBar::setRange(minimum, maximum);
430
#ifdef QT_WINEXTRAS_LIB
431
setupTaskBarProgress();
432
m_taskbarProgress->setRange(minimum, maximum);
436
void ProgressBar::setValueEx(int value)
438
QProgressBar::setValue(value);
439
#ifdef QT_WINEXTRAS_LIB
440
setupTaskBarProgress();
441
m_taskbarProgress->setValue(value);
445
void ProgressBar::setMinimumDuration (int ms)
449
d->delayShowTimer->stop();
450
d->delayShowTimer->start(ms);
453
d->minimumDuration = ms;
456
void ProgressBar::aboutToShow()
459
d->delayShowTimer->start(d->minimumDuration);
460
#ifdef QT_WINEXTRAS_LIB
461
setupTaskBarProgress();
462
m_taskbarProgress->show();
466
void ProgressBar::delayedShow()
468
if (!isVisible() && !sequencer->wasCanceled() && sequencer->isRunning()) {
473
void ProgressBar::aboutToHide()
476
#ifdef QT_WINEXTRAS_LIB
477
setupTaskBarProgress();
478
m_taskbarProgress->hide();
482
bool ProgressBar::canAbort() const
484
auto ret = QMessageBox::question(getMainWindow(),tr("Aborting"),
485
tr("Do you really want to abort the operation?"), QMessageBox::Yes | QMessageBox::No,
488
return (ret == QMessageBox::Yes) ? true : false;
491
void ProgressBar::showEvent(QShowEvent* e)
493
QProgressBar::showEvent(e);
494
d->delayShowTimer->stop();
497
void ProgressBar::hideEvent(QHideEvent* e)
499
QProgressBar::hideEvent(e);
500
d->delayShowTimer->stop();
503
void ProgressBar::resetObserveEventFilter()
505
d->observeEventFilter = 0;
508
void ProgressBar::enterControlEvents(bool grab)
510
qApp->installEventFilter(this);
514
#if defined(Q_OS_LINUX)
522
void ProgressBar::leaveControlEvents(bool release)
524
qApp->removeEventFilter(this);
526
#if defined(Q_OS_LINUX)
535
#ifdef QT_WINEXTRAS_LIB
536
void ProgressBar::setupTaskBarProgress()
538
if (!m_taskbarButton || !m_taskbarProgress)
540
m_taskbarButton = new QWinTaskbarButton(this);
541
m_taskbarButton->setWindow(MainWindow::getInstance()->windowHandle());
544
m_taskbarProgress = m_taskbarButton->progress();
549
bool ProgressBar::eventFilter(QObject* o, QEvent* e)
551
if (sequencer->isRunning() && e) {
552
QThread* currentThread = QThread::currentThread();
553
QThread* thr = this->thread();
554
if (thr != currentThread) {
555
if (e->type() == QEvent::KeyPress) {
556
auto ke = static_cast<QKeyEvent*>(e);
557
if (ke->key() == Qt::Key_Escape) {
559
sequencer->tryToCancel();
563
return QProgressBar::eventFilter(o, e);
570
case QEvent::KeyPress:
572
auto ke = static_cast<QKeyEvent*>(e);
573
if (ke->key() == Qt::Key_Escape) {
575
if (d->observeEventFilter > 50) {
577
if (ke->modifiers() & (Qt::ControlModifier | Qt::AltModifier)) {
578
sequencer->resetData();
584
sequencer->tryToCancel();
591
case QEvent::KeyRelease:
594
case QEvent::MouseButtonDblClick:
595
case QEvent::MouseButtonRelease:
596
case QEvent::MouseMove:
597
case QEvent::NativeGesture:
598
case QEvent::ContextMenu:
600
if (!d->isModalDialog(o))
609
if (o == getMainWindow()) {
616
case QEvent::MouseButtonPress:
618
if (!d->isModalDialog(o)) {
619
QApplication::beep();
629
d->observeEventFilter++;
632
return QProgressBar::eventFilter(o, e);
636
#include "moc_ProgressBar.cpp"