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