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