1
/***************************************************************************
2
* Copyright (c) 2009 Werner Mayer <wmayer@users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
24
#include "PreCompiled.h"
26
#include "ProgressDialog.h"
27
#include "MainWindow.h"
34
struct SequencerDialogPrivate
45
SequencerDialog* SequencerDialog::_pclSingleton = 0;
47
SequencerDialog* SequencerDialog::instance()
51
_pclSingleton = new SequencerDialog();
55
SequencerDialog::SequencerDialog ()
57
d = new SequencerDialogPrivate;
58
d->dlg = new ProgressDialog(this,getMainWindow());
62
SequencerDialog::~SequencerDialog()
67
void SequencerDialog::pause()
69
QThread *currentThread = QThread::currentThread();
70
QThread *thr = d->dlg->thread(); // this is the main thread
71
if (thr == currentThread)
72
// allow key handling of dialog
73
d->dlg->leaveControlEvents();
76
void SequencerDialog::resume()
78
QThread *currentThread = QThread::currentThread();
79
QThread *thr = d->dlg->thread(); // this is the main thread
80
if (thr == currentThread)
81
d->dlg->enterControlEvents(); // grab again
84
void SequencerDialog::startStep()
86
QThread *currentThread = QThread::currentThread();
87
QThread *thr = d->dlg->thread(); // this is the main thread
88
if (thr != currentThread) {
90
d->dlg->setRange(0, (int)nTotalSteps);
91
d->dlg->setModal(false);
92
if (nTotalSteps == 0) {
93
d->progressTime.start();
96
d->measureTime.start();
97
QMetaObject::invokeMethod(d->dlg, "setValue", Qt::QueuedConnection,
98
QGenericReturnArgument(), Q_ARG(int,0));
102
d->dlg->setRange(0, (int)nTotalSteps);
103
d->dlg->setModal(true);
104
if (nTotalSteps == 0) {
105
d->progressTime.start();
108
d->measureTime.start();
110
d->dlg->enterControlEvents();
114
void SequencerDialog::nextStep(bool canAbort)
116
QThread *currentThread = QThread::currentThread();
117
QThread *thr = d->dlg->thread(); // this is the main thread
118
if (thr != currentThread) {
119
setProgress((int)nProgress+1);
122
if (wasCanceled() && canAbort) {
125
bool ok = d->dlg->canAbort();
126
// continue and show up wait cursor if needed
129
// force to abort the operation
134
setProgress((int)nProgress+1);
138
setProgress((int)nProgress+1);
143
void SequencerDialog::setProgress(int step)
145
QThread *currentThread = QThread::currentThread();
146
QThread *thr = d->dlg->thread(); // this is the main thread
147
// if number of total steps is unknown then increment only by one
148
if (nTotalSteps == 0) {
149
int elapsed = d->progressTime.elapsed();
150
// allow an update every 500 milliseconds only
152
d->progressTime.restart();
153
if (thr != currentThread) {
154
QMetaObject::invokeMethod(d->dlg, "setValue", Qt::/*Blocking*/QueuedConnection,
155
QGenericReturnArgument(), Q_ARG(int,d->dlg->value()+1));
158
d->dlg->setValue(d->dlg->value()+1);
159
qApp->processEvents();
164
if (thr != currentThread) {
165
QMetaObject::invokeMethod(d->dlg, "setValue", Qt::/*Blocking*/QueuedConnection,
166
QGenericReturnArgument(), Q_ARG(int,step));
167
if (d->dlg->isVisible())
171
d->dlg->setValue(step);
172
if (d->dlg->isVisible())
174
qApp->processEvents();
179
void SequencerDialog::showRemainingTime()
181
QThread *currentThread = QThread::currentThread();
182
QThread *thr = d->dlg->thread(); // this is the main thread
184
int elapsed = d->measureTime.elapsed();
185
int progress = d->dlg->value();
186
int totalSteps = d->dlg->maximum() - d->dlg->minimum();
188
QString txt = d->text;
189
// More than 5 percent complete or more than 5 secs have elapsed.
190
if (progress * 20 > totalSteps || elapsed > 5000) {
191
int rest = (int) ( (double) totalSteps/progress * elapsed ) - elapsed;
193
// more than 1 secs have elapsed and at least 100 ms are remaining
194
if (elapsed > 1000 && rest > 100) {
196
time = time.addSecs( rest/1000 );
197
QString remain = Gui::ProgressDialog::tr("Remaining: %1").arg(time.toString());
198
QString status = QString::fromAscii("%1\t[%2]").arg(txt).arg(remain);
200
if (thr != currentThread) {
201
QMetaObject::invokeMethod(d->dlg, "setLabelText",
202
Qt::/*Blocking*/QueuedConnection,
203
QGenericReturnArgument(),
204
Q_ARG(QString,status));
207
d->dlg->setLabelText(status);
213
void SequencerDialog::resetData()
215
QThread *currentThread = QThread::currentThread();
216
QThread *thr = d->dlg->thread(); // this is the main thread
217
if (thr != currentThread) {
218
QMetaObject::invokeMethod(d->dlg, "reset", Qt::QueuedConnection);
219
QMetaObject::invokeMethod(d->dlg, "hide", Qt::QueuedConnection);
220
QMetaObject::invokeMethod(d->dlg, "setLabelText",
221
Qt::/*Blocking*/QueuedConnection,
222
QGenericReturnArgument(),
223
Q_ARG(QString,QString()));
227
// Note: Under Qt 4.1.4 this forces to run QWindowsStyle::eventFilter() twice
228
// handling the same event thus a warning is printed. Possibly, this is a bug
229
// in Qt. The message is QEventDispatcherUNIX::unregisterTimer: invalid argument.
231
d->dlg->setLabelText(QString());
232
d->dlg->leaveControlEvents();
235
SequencerBase::resetData();
238
void SequencerDialog::abort()
242
Base::AbortException exc("Aborting...");
246
void SequencerDialog::setText (const char* pszTxt)
248
QThread *currentThread = QThread::currentThread();
249
QThread *thr = d->dlg->thread(); // this is the main thread
251
// set label text of the dialog
252
d->text = pszTxt ? QString::fromUtf8(pszTxt) : QLatin1String("");
253
if (thr != currentThread) {
254
QMetaObject::invokeMethod(d->dlg, "setLabelText",
255
Qt::/*Blocking*/QueuedConnection,
256
QGenericReturnArgument(),
257
Q_ARG(QString,d->text));
260
d->dlg->setLabelText(d->text);
264
bool SequencerDialog::isBlocking() const
269
// -------------------------------------------------------
271
/* TRANSLATOR Gui::ProgressDialog */
273
ProgressDialog::ProgressDialog (SequencerDialog* s, QWidget * parent)
274
: QProgressDialog(parent, Qt::FramelessWindowHint), sequencer(s)
276
connect(this, SIGNAL(canceled()), this, SLOT(onCancel()));
279
ProgressDialog::~ProgressDialog ()
283
void ProgressDialog::onCancel()
285
sequencer->tryToCancel();
288
bool ProgressDialog::canAbort() const
290
int ret = QMessageBox::question(getMainWindow(),tr("Aborting"),
291
tr("Do you really want to abort the operation?"), QMessageBox::Yes,
292
QMessageBox::No|QMessageBox::Default);
294
return (ret == QMessageBox::Yes) ? true : false;
297
void ProgressDialog::enterControlEvents()
299
qApp->installEventFilter(this);
301
// Make sure that we get the key events, otherwise the Inventor viewer usurps the key events
302
// This also disables accelerators.
306
void ProgressDialog::leaveControlEvents()
308
qApp->removeEventFilter(this);
310
// relase the keyboard again
314
bool ProgressDialog::eventFilter(QObject* o, QEvent* e)
316
if (sequencer->isRunning() && e != 0) {
320
case QEvent::KeyPress:
322
QKeyEvent* ke = (QKeyEvent*)e;
323
if (ke->key() == Qt::Key_Escape) {
324
// cancel the operation
331
// ignore all these events
332
case QEvent::KeyRelease:
335
case QEvent::MouseButtonDblClick:
336
case QEvent::ContextMenu:
341
// special case if the main window's close button was pressed
344
// avoid to exit while app is working
345
// note: all other widget types are allowed to be closed anyway
346
if (o == getMainWindow()) {
352
// do a system beep and ignore the event
353
case QEvent::MouseButtonPress:
355
QApplication::beep();
365
return QProgressDialog::eventFilter(o, e);
368
#include "moc_ProgressDialog.cpp"