~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/qt3support/dialogs/q3progressdialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the Qt 3 compatibility classes of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "q3progressdialog.h"
 
30
 
 
31
#ifndef QT_NO_PROGRESSDIALOG
 
32
 
 
33
#include "q3progressbar.h"
 
34
#include "qapplication.h"
 
35
#include "qcursor.h"
 
36
#include "qdatetime.h"
 
37
#include "qlabel.h"
 
38
#include "qpainter.h"
 
39
#include "qpushbutton.h"
 
40
#include "qshortcut.h"
 
41
#include "qstyle.h"
 
42
#include "qtimer.h"
 
43
#include <limits.h>
 
44
 
 
45
// If the operation is expected to take this long (as predicted by
 
46
// progress time), show the progress dialog.
 
47
static const int defaultShowTime    = 4000;
 
48
// Wait at least this long before attempting to make a prediction.
 
49
static const int minWaitTime = 50;
 
50
 
 
51
// Various layout values
 
52
static const int margin_lr   = 10;
 
53
static const int margin_tb   = 10;
 
54
static const int spacing     = 4;
 
55
 
 
56
 
 
57
class Q3ProgressDialogData
 
58
{
 
59
public:
 
60
    Q3ProgressDialogData(Q3ProgressDialog* that, QWidget* parent,
 
61
                   const QString& labelText,
 
62
                   int totalSteps) :
 
63
        creator(parent),
 
64
        label(new QLabel(labelText,that)),
 
65
        cancel(0),
 
66
        bar(new Q3ProgressBar(totalSteps, that)),
 
67
        shown_once(false),
 
68
        cancellation_flag(false),
 
69
        showTime(defaultShowTime)
 
70
    {
 
71
        int align = that->style()->styleHint(QStyle::SH_ProgressDialog_TextLabelAlignment, 0, that);
 
72
        label->setAlignment(Qt::Alignment(align));
 
73
    }
 
74
 
 
75
    QWidget         *creator;
 
76
    QLabel         *label;
 
77
    QPushButton         *cancel;
 
78
    Q3ProgressBar *bar;
 
79
    bool          shown_once;
 
80
    bool          cancellation_flag;
 
81
    QTime          starttime;
 
82
#ifndef QT_NO_CURSOR
 
83
    QCursor          parentCursor;
 
84
#endif
 
85
    int                  showTime;
 
86
    bool autoClose;
 
87
    bool autoReset;
 
88
    bool forceHide;
 
89
};
 
90
 
 
91
 
 
92
/*!
 
93
  \class Q3ProgressDialog qprogressdialog.h
 
94
  \brief The Q3ProgressDialog class provides feedback on the progress of a slow operation.
 
95
 
 
96
  \compat
 
97
 
 
98
  A progress dialog is used to give the user an indication of how long
 
99
  an operation is going to take, and to demonstrate that the
 
100
  application has not frozen. It can also give the user an opportunity
 
101
  to abort the operation.
 
102
 
 
103
  A common problem with progress dialogs is that it is difficult to know
 
104
  when to use them; operations take different amounts of time on different
 
105
  hardware.  Q3ProgressDialog offers a solution to this problem:
 
106
  it estimates the time the operation will take (based on time for
 
107
  steps), and only shows itself if that estimate is beyond minimumDuration()
 
108
  (4 seconds by default).
 
109
 
 
110
  Use setTotalSteps() (or the constructor) to set the number of
 
111
  "steps" in the operation and call setProgress() as the operation
 
112
  progresses. The step value can be chosen arbitrarily. It can be the
 
113
  number of files copied, the number of bytes received, the number of
 
114
  iterations through the main loop of your algorithm, or some other
 
115
  suitable unit.  Progress starts at 0, and the progress dialog shows
 
116
  that the operation has finished when you call setProgress() with
 
117
  totalSteps() as its argument.
 
118
 
 
119
  The dialog automatically resets and hides itself at the end of the
 
120
  operation. Use setAutoReset() and setAutoClose() to change this
 
121
  behavior.
 
122
 
 
123
  There are two ways of using Q3ProgressDialog: modal and modeless.
 
124
 
 
125
  Using a modal Q3ProgressDialog is simpler for the programmer, but you
 
126
  must call QApplication::processEvents() or
 
127
  QEventLoop::processEvents(ExcludeUserInput) to keep the event loop
 
128
  running to ensure that the application doesn't freeze. Do the
 
129
  operation in a loop, call \l setProgress() at intervals, and check
 
130
  for cancellation with wasCanceled(). For example:
 
131
\code
 
132
Q3ProgressDialog progress("Copying files...", "Abort Copy", numFiles,
 
133
                          this, "progress", true);
 
134
for (int i = 0; i < numFiles; i++) {
 
135
    progress.setProgress(i);
 
136
    qApp->processEvents();
 
137
 
 
138
    if (progress.wasCanceled())
 
139
        break;
 
140
    //... copy one file
 
141
}
 
142
progress.setProgress(numFiles);
 
143
\endcode
 
144
 
 
145
  A modeless progress dialog is suitable for operations that take
 
146
  place in the background, where the user is able to interact with the
 
147
  application. Such operations are typically based on QTimer (or
 
148
  QObject::timerEvent()), QSocketNotifier, or QUrlOperator; or performed
 
149
  in a separate thread. A Q3ProgressBar in the status bar of your main window
 
150
  is often an alternative to a modeless progress dialog.
 
151
 
 
152
  You need to have an event loop to be running, connect the
 
153
  canceled() signal to a slot that stops the operation, and call \l
 
154
  setProgress() at intervals. For example:
 
155
\code
 
156
Operation::Operation(QObject *parent = 0)
 
157
    : QObject(parent), steps(0)
 
158
{
 
159
    pd = new Q3ProgressDialog("Operation in progress.", "Cancel", 100);
 
160
    connect(pd, SIGNAL(canceled()), this, SLOT(cancel()));
 
161
    t = new QTimer(this);
 
162
    connect(t, SIGNAL(timeout()), this, SLOT(perform()));
 
163
    t->start(0);
 
164
}
 
165
 
 
166
void Operation::perform()
 
167
{
 
168
    pd->setProgress(steps);
 
169
    //... perform one percent of the operation
 
170
    steps++;
 
171
    if (steps > pd->totalSteps())
 
172
        t->stop();
 
173
}
 
174
 
 
175
void Operation::cancel()
 
176
{
 
177
    t->stop();
 
178
    //... cleanup
 
179
}
 
180
\endcode
 
181
 
 
182
 
 
183
  In both modes the progress dialog may be customized by
 
184
  replacing the child widgets with custom widgets by using setLabel(),
 
185
  setBar(), and setCancelButton().
 
186
  The functions setLabelText() and setCancelButtonText()
 
187
  set the texts shown.
 
188
 
 
189
  \inlineimage qprogdlg-m.png Screenshot in Motif style
 
190
  \inlineimage qprogdlg-w.png Screenshot in Windows style
 
191
 
 
192
  \sa QDialog, Q3ProgressBar, {fowler}{GUI Design Handbook: Progress Indicator}
 
193
*/
 
194
 
 
195
 
 
196
/*!
 
197
  Returns the QLabel currently being displayed above the progress bar.
 
198
  This QLabel is owned by the Q3ProgressDialog.
 
199
 
 
200
  \sa setLabel()
 
201
*/
 
202
QLabel *Q3ProgressDialog::label() const
 
203
{
 
204
    return d->label;
 
205
}
 
206
 
 
207
/*!
 
208
  Returns the Q3ProgressBar currently being used to display progress.
 
209
  This Q3ProgressBar is owned by the Q3ProgressDialog.
 
210
 
 
211
  \sa setBar()
 
212
*/
 
213
Q3ProgressBar *Q3ProgressDialog::bar() const
 
214
{
 
215
    return d->bar;
 
216
}
 
217
 
 
218
 
 
219
/*!
 
220
  \obsolete
 
221
  Constructs a progress dialog.
 
222
 
 
223
  Default settings:
 
224
  \list
 
225
  \i The label text is empty.
 
226
  \i The cancel button text is (translated) "Cancel".
 
227
  \i The total number of steps is 100.
 
228
  \endlist
 
229
 
 
230
  The \a creator argument is the widget to use as the dialog's parent.
 
231
  The \a name, \a modal, and the widget flags, \a f, are
 
232
  passed to the QDialog::QDialog() constructor. If \a modal is false (the
 
233
  default), you must have an event loop proceeding for any redrawing
 
234
  of the dialog to occur. If \a modal is true, the dialog ensures that
 
235
  events are processed when needed.
 
236
 
 
237
  \sa setLabelText(), setLabel(), setCancelButtonText(), setCancelButton(),
 
238
  setTotalSteps()
 
239
*/
 
240
 
 
241
Q3ProgressDialog::Q3ProgressDialog(QWidget *creator, const char *name,
 
242
                                  bool modal, Qt::WFlags f)
 
243
    : QDialog(creator, f)
 
244
{
 
245
    setObjectName(name);
 
246
    setModal(modal);
 
247
    init(creator, QString::fromLatin1(""), tr("Cancel"), 100);
 
248
}
 
249
 
 
250
/*!
 
251
  \obsolete
 
252
  Constructs a progress dialog.
 
253
 
 
254
   The \a labelText is text used to remind the user what is progressing.
 
255
 
 
256
   The \a cancelButtonText is the text to display on the cancel button,
 
257
            or 0 if no cancel button is to be shown.
 
258
 
 
259
   The \a totalSteps is the total number of steps in the operation for
 
260
   which this progress dialog shows progress.  For example, if the
 
261
   operation is to examine 50 files, this value would be 50. Before
 
262
   examining the first file, call setProgress(0). As each file is
 
263
   processed call setProgress(1), setProgress(2), etc., finally
 
264
   calling setProgress(50) after examining the last file.
 
265
 
 
266
   The \a creator argument is the widget to use as the dialog's parent.
 
267
   The \a name, \a modal, and widget flags, \a f, are passed to the
 
268
   QDialog::QDialog() constructor. If \a modal is false (the default),
 
269
   you will must have an event loop proceeding for any redrawing of
 
270
   the dialog to occur. If \a modal is true, the dialog ensures that
 
271
   events are processed when needed.
 
272
 
 
273
 
 
274
  \sa setLabelText(), setLabel(), setCancelButtonText(), setCancelButton(),
 
275
  setTotalSteps()
 
276
*/
 
277
 
 
278
Q3ProgressDialog::Q3ProgressDialog(const QString &labelText,
 
279
                                  const QString &cancelButtonText,
 
280
                                  int totalSteps,
 
281
                                  QWidget *creator, const char *name,
 
282
                                  bool modal, Qt::WFlags f)
 
283
    : QDialog(creator, f)
 
284
{
 
285
    setObjectName(name);
 
286
    setModal(modal);
 
287
    init(creator, labelText, cancelButtonText, totalSteps);
 
288
}
 
289
 
 
290
/*!
 
291
  Constructs a progress dialog.
 
292
 
 
293
  Default settings:
 
294
  \list
 
295
      \i The label text is empty.
 
296
      \i The cancel button text is (translated) "Cancel".
 
297
      \i The total number of steps is 100.
 
298
  \endlist
 
299
 
 
300
  The \a creator argument is the widget to use as the dialog's parent.
 
301
  The widget flags, \a f, are passed to the QDialog::QDialog() constructor.
 
302
 
 
303
  \sa setLabelText(), setLabel(), setCancelButtonText(), setCancelButton(),
 
304
  setTotalSteps()
 
305
*/
 
306
Q3ProgressDialog::Q3ProgressDialog(QWidget *creator, Qt::WFlags f)
 
307
    : QDialog(creator, f)
 
308
{
 
309
    init(creator, QString::fromLatin1(""), tr("Cancel"), 100);
 
310
}
 
311
 
 
312
/*!
 
313
  Constructs a progress dialog.
 
314
 
 
315
   The \a labelText is text used to remind the user what is progressing.
 
316
 
 
317
   The \a cancelButtonText is the text to display on the cancel button,
 
318
            or 0 if no cancel button is to be shown.
 
319
 
 
320
   The \a totalSteps is the total number of steps in the operation for
 
321
   which this progress dialog shows progress.  For example, if the
 
322
   operation is to examine 50 files, this value would be 50. Before
 
323
   examining the first file, call setProgress(0). As each file is
 
324
   processed call setProgress(1), setProgress(2), etc., finally
 
325
   calling setProgress(50) after examining the last file.
 
326
 
 
327
   The \a creator argument is the widget to use as the dialog's parent.
 
328
   The widget flags, \a f, are passed to the
 
329
   QDialog::QDialog() constructor.
 
330
 
 
331
  \sa setLabelText(), setLabel(), setCancelButtonText(), setCancelButton(),
 
332
  setTotalSteps()
 
333
*/
 
334
Q3ProgressDialog::Q3ProgressDialog(const QString &labelText,
 
335
                                  const QString &cancelButtonText,
 
336
                                  int totalSteps, QWidget *creator, Qt::WFlags f)
 
337
    : QDialog(creator, f)
 
338
{
 
339
    init(creator, labelText, cancelButtonText, totalSteps);
 
340
}
 
341
 
 
342
/*!
 
343
  Destroys the progress dialog.
 
344
*/
 
345
 
 
346
Q3ProgressDialog::~Q3ProgressDialog()
 
347
{
 
348
#ifndef QT_NO_CURSOR
 
349
    if (d->creator)
 
350
        d->creator->setCursor(d->parentCursor);
 
351
#endif
 
352
    delete d;
 
353
}
 
354
 
 
355
void Q3ProgressDialog::init(QWidget *creator,
 
356
                            const QString& lbl, const QString& canc,
 
357
                            int totstps)
 
358
{
 
359
    d = new Q3ProgressDialogData(this, creator, lbl, totstps);
 
360
    d->autoClose = true;
 
361
    d->autoReset = true;
 
362
    d->forceHide = false;
 
363
    setCancelButtonText(canc);
 
364
    connect(this, SIGNAL(canceled()), this, SLOT(cancel()));
 
365
    forceTimer = new QTimer(this);
 
366
    connect(forceTimer, SIGNAL(timeout()), this, SLOT(forceShow()));
 
367
    layout();
 
368
}
 
369
 
 
370
/*!
 
371
  \fn void Q3ProgressDialog::canceled()
 
372
 
 
373
  This signal is emitted when the cancel button is clicked.
 
374
  It is connected to the cancel() slot by default.
 
375
 
 
376
  \sa wasCanceled()
 
377
*/
 
378
 
 
379
 
 
380
/*!
 
381
  Sets the label to \a label. The progress dialog resizes to fit. The
 
382
  label becomes owned by the progress dialog and will be deleted when
 
383
  necessary, so do not pass the address of an object on the stack.
 
384
 
 
385
  \sa setLabelText()
 
386
*/
 
387
 
 
388
void Q3ProgressDialog::setLabel(QLabel *label)
 
389
{
 
390
    delete d->label;
 
391
    d->label = label;
 
392
    if (label) {
 
393
        if (label->parentWidget() == this) {
 
394
            label->hide(); // until we resize
 
395
        } else {
 
396
            label->setParent(this, 0);
 
397
        }
 
398
    }
 
399
    int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
400
    int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
401
    resize(w, h);
 
402
    if (label)
 
403
        label->show();
 
404
}
 
405
 
 
406
 
 
407
/*!
 
408
  \property Q3ProgressDialog::labelText
 
409
  \brief the label's text
 
410
 
 
411
  The default text is an empty string.
 
412
*/
 
413
 
 
414
QString Q3ProgressDialog::labelText() const
 
415
{
 
416
    if (label())
 
417
        return label()->text();
 
418
    return QString();
 
419
}
 
420
 
 
421
void Q3ProgressDialog::setLabelText(const QString &text)
 
422
{
 
423
    if (label()) {
 
424
        label()->setText(text);
 
425
        int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
426
        int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
427
        resize(w, h);
 
428
    }
 
429
}
 
430
 
 
431
 
 
432
/*!
 
433
  Sets the cancel button to the push button, \a cancelButton. The
 
434
  progress dialog takes ownership of this button which will be deleted
 
435
  when necessary, so do not pass the address of an object that is on
 
436
  the stack, i.e. use new() to create the button.
 
437
 
 
438
  \sa setCancelButtonText()
 
439
*/
 
440
 
 
441
void Q3ProgressDialog::setCancelButton(QPushButton *cancelButton)
 
442
{
 
443
    delete d->cancel;
 
444
    d->cancel = cancelButton;
 
445
    if (cancelButton) {
 
446
        if (cancelButton->parentWidget() == this) {
 
447
            cancelButton->hide(); // until we resize
 
448
        } else {
 
449
            cancelButton->setParent(this, 0);
 
450
        }
 
451
        connect(d->cancel, SIGNAL(clicked()), this, SIGNAL(canceled()));
 
452
        new QShortcut(Qt::Key_Escape, this, SIGNAL(canceled()));
 
453
    }
 
454
    int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
455
    int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
456
    resize(w, h);
 
457
    if (cancelButton)
 
458
        cancelButton->show();
 
459
}
 
460
 
 
461
/*!
 
462
  Sets the cancel button's text to \a cancelButtonText.
 
463
  \sa setCancelButton()
 
464
*/
 
465
 
 
466
void Q3ProgressDialog::setCancelButtonText(const QString &cancelButtonText)
 
467
{
 
468
    if (!cancelButtonText.isNull()) {
 
469
        if (d->cancel)
 
470
            d->cancel->setText(cancelButtonText);
 
471
        else
 
472
            setCancelButton(new QPushButton(cancelButtonText, this));
 
473
    } else {
 
474
        setCancelButton(0);
 
475
    }
 
476
    int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
477
    int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
478
    resize(w, h);
 
479
}
 
480
 
 
481
 
 
482
/*!
 
483
  Sets the progress bar widget to \a bar. The progress dialog resizes to
 
484
  fit. The progress dialog takes ownership of the progress \a bar which
 
485
  will be deleted when necessary, so do not use a progress bar
 
486
  allocated on the stack.
 
487
*/
 
488
 
 
489
void Q3ProgressDialog::setBar(Q3ProgressBar *bar)
 
490
{
 
491
#ifndef QT_NO_DEBUG
 
492
    if (progress() > 0)
 
493
        qWarning("Q3ProgressDialog::setBar: Cannot set a new progress bar "
 
494
                  "while the old one is active");
 
495
#endif
 
496
    delete d->bar;
 
497
    d->bar = bar;
 
498
    int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
499
    int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
500
    resize(w, h);
 
501
}
 
502
 
 
503
 
 
504
/*!
 
505
  \property Q3ProgressDialog::wasCanceled
 
506
  \brief whether the dialog was canceled
 
507
 
 
508
  \sa setProgress()
 
509
*/
 
510
 
 
511
bool Q3ProgressDialog::wasCanceled() const
 
512
{
 
513
    return d->cancellation_flag;
 
514
}
 
515
 
 
516
 
 
517
/*!
 
518
  \property Q3ProgressDialog::totalSteps
 
519
  \brief the total number of steps
 
520
 
 
521
  The default is 0.
 
522
*/
 
523
 
 
524
int Q3ProgressDialog::totalSteps() const
 
525
{
 
526
    if (d && d->bar)
 
527
        return bar()->totalSteps();
 
528
    return 0;
 
529
}
 
530
 
 
531
void Q3ProgressDialog::setTotalSteps(int totalSteps)
 
532
{
 
533
    bar()->setTotalSteps(totalSteps);
 
534
}
 
535
 
 
536
 
 
537
/*!
 
538
  Resets the progress dialog.
 
539
  The progress dialog becomes hidden if autoClose() is true.
 
540
 
 
541
  \sa setAutoClose(), setAutoReset()
 
542
*/
 
543
 
 
544
void Q3ProgressDialog::reset()
 
545
{
 
546
#ifndef QT_NO_CURSOR
 
547
    if (progress() >= 0) {
 
548
        if (d->creator)
 
549
            d->creator->setCursor(d->parentCursor);
 
550
    }
 
551
#endif
 
552
    if (d->autoClose || d->forceHide)
 
553
        hide();
 
554
    bar()->reset();
 
555
    d->cancellation_flag = false;
 
556
    d->shown_once = false;
 
557
    forceTimer->stop();
 
558
}
 
559
 
 
560
/*!
 
561
  Resets the progress dialog. wasCanceled() becomes true until
 
562
  the progress dialog is reset.
 
563
  The progress dialog becomes hidden.
 
564
*/
 
565
 
 
566
void Q3ProgressDialog::cancel()
 
567
{
 
568
    d->forceHide = true;
 
569
    reset();
 
570
    d->forceHide = false;
 
571
    d->cancellation_flag = true;
 
572
}
 
573
 
 
574
/*!
 
575
  \property Q3ProgressDialog::progress
 
576
  \brief the current amount of progress made.
 
577
 
 
578
  For the progress dialog to work as expected, you should initially set
 
579
  this property to 0 and finally set it to
 
580
  Q3ProgressDialog::totalSteps(); you can call setProgress() any number of times
 
581
  in-between.
 
582
 
 
583
  \warning If the progress dialog is modal
 
584
    (see Q3ProgressDialog::Q3ProgressDialog()),
 
585
    this function calls QApplication::processEvents(), so take care that
 
586
    this does not cause undesirable re-entrancy in your code. For example,
 
587
    don't use a Q3ProgressDialog inside a paintEvent()!
 
588
 
 
589
  \sa totalSteps
 
590
*/
 
591
 
 
592
int Q3ProgressDialog::progress() const
 
593
{
 
594
    return bar()->progress();
 
595
}
 
596
 
 
597
void Q3ProgressDialog::setProgress(int progress)
 
598
{
 
599
    if (progress == bar()->progress() ||
 
600
         bar()->progress() == -1 && progress == bar()->totalSteps())
 
601
        return;
 
602
 
 
603
    bar()->setProgress(progress);
 
604
 
 
605
    if (d->shown_once) {
 
606
        if (isModal())
 
607
            qApp->processEvents();
 
608
    } else {
 
609
        if (progress == 0) {
 
610
#ifndef QT_NO_CURSOR
 
611
            if (d->creator) {
 
612
                d->parentCursor = d->creator->cursor();
 
613
                d->creator->setCursor(Qt::WaitCursor);
 
614
            }
 
615
#endif
 
616
            d->starttime.start();
 
617
            forceTimer->start(d->showTime);
 
618
            return;
 
619
        } else {
 
620
            bool need_show;
 
621
            int elapsed = d->starttime.elapsed();
 
622
            if (elapsed >= d->showTime) {
 
623
                need_show = true;
 
624
            } else {
 
625
                if (elapsed > minWaitTime) {
 
626
                    int estimate;
 
627
                    if ((totalSteps() - progress) >= INT_MAX / elapsed)
 
628
                        estimate = (totalSteps() - progress) / progress * elapsed;
 
629
                    else
 
630
                        estimate = elapsed * (totalSteps() - progress) / progress;
 
631
                    need_show = estimate >= d->showTime;
 
632
                } else {
 
633
                    need_show = false;
 
634
                }
 
635
            }
 
636
            if (need_show) {
 
637
                int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
638
                int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
639
                resize(w, h);
 
640
                show();
 
641
                d->shown_once = true;
 
642
            }
 
643
        }
 
644
#ifdef Q_WS_MAC
 
645
        QApplication::flush();
 
646
#endif
 
647
    }
 
648
 
 
649
    if (progress == bar()->totalSteps() && d->autoReset)
 
650
        reset();
 
651
}
 
652
 
 
653
/*!
 
654
  \overload
 
655
 
 
656
  Sets the current amount of progress to \a progress and the total number of
 
657
  steps to \a totalSteps.
 
658
 
 
659
  \sa setTotalSteps()
 
660
*/
 
661
 
 
662
void Q3ProgressDialog::setProgress(int progress, int totalSteps)
 
663
{
 
664
    setTotalSteps(totalSteps);
 
665
    setProgress(progress);
 
666
}
 
667
 
 
668
/*!
 
669
  Returns a size that fits the contents of the progress dialog.
 
670
  The progress dialog resizes itself as required, so you should not
 
671
  need to call this yourself.
 
672
*/
 
673
 
 
674
QSize Q3ProgressDialog::sizeHint() const
 
675
{
 
676
    QSize sh = label()->sizeHint();
 
677
    QSize bh = bar()->sizeHint();
 
678
    int h = margin_tb*2 + bh.height() + sh.height() + spacing;
 
679
    if (d->cancel)
 
680
        h += d->cancel->sizeHint().height() + spacing;
 
681
    return QSize(qMax(200, sh.width() + 2*margin_lr), h);
 
682
}
 
683
 
 
684
/*!\reimp
 
685
*/
 
686
void Q3ProgressDialog::resizeEvent(QResizeEvent *)
 
687
{
 
688
    layout();
 
689
}
 
690
 
 
691
/*!
 
692
  \reimp
 
693
*/
 
694
void Q3ProgressDialog::changeEvent(QEvent *ev)
 
695
{
 
696
    if(ev->type() == QEvent::StyleChange)
 
697
        layout();
 
698
    QDialog::changeEvent(ev);
 
699
}
 
700
 
 
701
void Q3ProgressDialog::layout()
 
702
{
 
703
    int sp = spacing;
 
704
    int mtb = margin_tb;
 
705
    int mlr = qMin(width()/10, margin_lr);
 
706
    const bool centered =
 
707
        bool(style()->styleHint(QStyle::SH_ProgressDialog_CenterCancelButton, 0, this));
 
708
 
 
709
    QSize cs = d->cancel ? d->cancel->sizeHint() : QSize(0,0);
 
710
    QSize bh = bar()->sizeHint();
 
711
    int cspc;
 
712
    int lh = 0;
 
713
 
 
714
    // Find spacing and sizes that fit.  It is important that a progress
 
715
    // dialog can be made very small if the user demands it so.
 
716
    for (int attempt=5; attempt--;) {
 
717
        cspc = d->cancel ? cs.height() + sp : 0;
 
718
        lh = qMax(0, height() - mtb - bh.height() - sp - cspc);
 
719
 
 
720
        if (lh < height()/4) {
 
721
            // Getting cramped
 
722
            sp /= 2;
 
723
            mtb /= 2;
 
724
            if (d->cancel) {
 
725
                cs.setHeight(qMax(4,cs.height()-sp-2));
 
726
            }
 
727
            bh.setHeight(qMax(4,bh.height()-sp-1));
 
728
        } else {
 
729
            break;
 
730
        }
 
731
    }
 
732
 
 
733
    if (d->cancel) {
 
734
        d->cancel->setGeometry(
 
735
            centered ? width()/2 - cs.width()/2 : width() - mlr - cs.width(),
 
736
            height() - mtb - cs.height() + sp,
 
737
            cs.width(), cs.height());
 
738
    }
 
739
 
 
740
    label()->setGeometry(mlr, 0, width()-mlr*2, lh);
 
741
    bar()->setGeometry(mlr, lh+sp, width()-mlr*2, bh.height());
 
742
}
 
743
 
 
744
/*!
 
745
    \property Q3ProgressDialog::minimumDuration
 
746
    \brief the time that must pass before the dialog appears
 
747
 
 
748
    If the expected duration of the task is less than the
 
749
    minimumDuration, the dialog will not appear at all. This prevents
 
750
    the dialog popping up for tasks that are quickly over. For tasks
 
751
    that are expected to exceed the minimumDuration, the dialog will
 
752
    pop up after the minimumDuration time or as soon as any progress
 
753
    is set.
 
754
 
 
755
    If set to 0, the dialog is always shown as soon as any progress is
 
756
    set. The default is 4000 milliseconds.
 
757
*/
 
758
void Q3ProgressDialog::setMinimumDuration(int ms)
 
759
{
 
760
    d->showTime = ms;
 
761
    if (bar()->progress() == 0) {
 
762
        forceTimer->stop();
 
763
        forceTimer->start(ms);
 
764
    }
 
765
}
 
766
 
 
767
int Q3ProgressDialog::minimumDuration() const
 
768
{
 
769
    return d->showTime;
 
770
}
 
771
 
 
772
 
 
773
/*!
 
774
  \reimp
 
775
*/
 
776
 
 
777
void Q3ProgressDialog::closeEvent(QCloseEvent *e)
 
778
{
 
779
    emit canceled();
 
780
    QDialog::closeEvent(e);
 
781
}
 
782
 
 
783
/*!
 
784
  \property Q3ProgressDialog::autoReset
 
785
  \brief whether the progress dialog calls reset() as soon as progress() equals totalSteps()
 
786
 
 
787
  The default is true.
 
788
 
 
789
  \sa setAutoClose()
 
790
*/
 
791
 
 
792
void Q3ProgressDialog::setAutoReset(bool b)
 
793
{
 
794
    d->autoReset = b;
 
795
}
 
796
 
 
797
bool Q3ProgressDialog::autoReset() const
 
798
{
 
799
    return d->autoReset;
 
800
}
 
801
 
 
802
/*!
 
803
  \property Q3ProgressDialog::autoClose
 
804
  \brief whether the dialog gets hidden by reset()
 
805
 
 
806
  The default is true.
 
807
 
 
808
  \sa setAutoReset()
 
809
*/
 
810
 
 
811
void Q3ProgressDialog::setAutoClose(bool b)
 
812
{
 
813
    d->autoClose = b;
 
814
}
 
815
 
 
816
bool Q3ProgressDialog::autoClose() const
 
817
{
 
818
    return d->autoClose;
 
819
}
 
820
 
 
821
/*!
 
822
  \reimp
 
823
*/
 
824
 
 
825
void Q3ProgressDialog::showEvent(QShowEvent *e)
 
826
{
 
827
    QDialog::showEvent(e);
 
828
    int w = qMax(isVisible() ? width() : 0, sizeHint().width());
 
829
    int h = qMax(isVisible() ? height() : 0, sizeHint().height());
 
830
    resize(w, h);
 
831
    forceTimer->stop();
 
832
}
 
833
 
 
834
/*!
 
835
  Shows the dialog if it is still hidden after the algorithm has been started
 
836
  and minimumDuration milliseconds have passed.
 
837
 
 
838
  \sa setMinimumDuration()
 
839
*/
 
840
 
 
841
void Q3ProgressDialog::forceShow()
 
842
{
 
843
    if (d->shown_once || d->cancellation_flag)
 
844
        return;
 
845
 
 
846
    show();
 
847
    d->shown_once = true;
 
848
}
 
849
 
 
850
 
 
851
#endif