~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/widgets/dialogs/qprogressdialog.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

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