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

source code of qtbase/src/widgets/dialogs/qprogressdialog.cpp