src/gui/dialogs/qprogressdialog.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 #ifdef QT_SOFTKEYS_ENABLED
       
   428     delete d->cancelAction;
       
   429     d->cancelAction = 0;
       
   430 #endif
       
   431     d->cancel = cancelButton;
       
   432     if (cancelButton) {
       
   433         if (cancelButton->parentWidget() == this) {
       
   434             cancelButton->hide(); // until we resize
       
   435         } else {
       
   436             cancelButton->setParent(this, 0);
       
   437         }
       
   438         connect(d->cancel, SIGNAL(clicked()), this, SIGNAL(canceled()));
       
   439 #ifndef QT_NO_SHORTCUT
       
   440         d->escapeShortcut = new QShortcut(Qt::Key_Escape, this, SIGNAL(canceled()));
       
   441 #endif
       
   442     } else {
       
   443 #ifndef QT_NO_SHORTCUT
       
   444         delete d->escapeShortcut;
       
   445         d->escapeShortcut = 0;
       
   446 #endif
       
   447     }
       
   448     int w = qMax(isVisible() ? width() : 0, sizeHint().width());
       
   449     int h = qMax(isVisible() ? height() : 0, sizeHint().height());
       
   450     resize(w, h);
       
   451     if (cancelButton)
       
   452 #if !defined(QT_SOFTKEYS_ENABLED)
       
   453         cancelButton->show();
       
   454 #else
       
   455     {
       
   456         d->cancelAction = new QAction(cancelButton->text(), cancelButton);
       
   457         d->cancelAction->setSoftKeyRole(QAction::NegativeSoftKey);
       
   458         connect(d->cancelAction, SIGNAL(triggered()), this, SIGNAL(canceled()));
       
   459         addAction(d->cancelAction);
       
   460     }
       
   461 #endif
       
   462 }
       
   463 
       
   464 /*!
       
   465   Sets the cancel button's text to \a cancelButtonText.  If the text
       
   466   is set to QString() then it will cause the cancel button to be 
       
   467   hidden and deleted.
       
   468 
       
   469   \sa setCancelButton()
       
   470 */
       
   471 
       
   472 void QProgressDialog::setCancelButtonText(const QString &cancelButtonText)
       
   473 {
       
   474     Q_D(QProgressDialog);
       
   475     d->useDefaultCancelText = false;
       
   476 
       
   477     if (!cancelButtonText.isNull()) {
       
   478         if (d->cancel) {
       
   479             d->cancel->setText(cancelButtonText);
       
   480 #ifdef QT_SOFTKEYS_ENABLED
       
   481             d->cancelAction->setText(cancelButtonText);
       
   482 #endif
       
   483         } else {
       
   484             setCancelButton(new QPushButton(cancelButtonText, this));
       
   485         }
       
   486     } else {
       
   487         setCancelButton(0);
       
   488     }
       
   489     int w = qMax(isVisible() ? width() : 0, sizeHint().width());
       
   490     int h = qMax(isVisible() ? height() : 0, sizeHint().height());
       
   491     resize(w, h);
       
   492 }
       
   493 
       
   494 
       
   495 /*!
       
   496   Sets the progress bar widget to \a bar. The progress dialog resizes to
       
   497   fit. The progress dialog takes ownership of the progress \a bar which
       
   498   will be deleted when necessary, so do not use a progress bar
       
   499   allocated on the stack.
       
   500 */
       
   501 
       
   502 void QProgressDialog::setBar(QProgressBar *bar)
       
   503 {
       
   504     Q_D(QProgressDialog);
       
   505     if (!bar) {
       
   506         qWarning("QProgressDialog::setBar: Cannot set a null progress bar");
       
   507         return;
       
   508     }
       
   509 #ifndef QT_NO_DEBUG
       
   510     if (value() > 0)
       
   511         qWarning("QProgressDialog::setBar: Cannot set a new progress bar "
       
   512                   "while the old one is active");
       
   513 #endif
       
   514     delete d->bar;
       
   515     d->bar = bar;
       
   516     int w = qMax(isVisible() ? width() : 0, sizeHint().width());
       
   517     int h = qMax(isVisible() ? height() : 0, sizeHint().height());
       
   518     resize(w, h);
       
   519 }
       
   520 
       
   521 
       
   522 /*!
       
   523   \property QProgressDialog::wasCanceled
       
   524   \brief whether the dialog was canceled
       
   525 */
       
   526 
       
   527 bool QProgressDialog::wasCanceled() const
       
   528 {
       
   529     Q_D(const QProgressDialog);
       
   530     return d->cancellation_flag;
       
   531 }
       
   532 
       
   533 
       
   534 /*!
       
   535     \property QProgressDialog::maximum
       
   536     \brief the highest value represented by the progress bar
       
   537 
       
   538     The default is 0.
       
   539 
       
   540     \sa minimum, setRange()
       
   541 */
       
   542 
       
   543 int QProgressDialog::maximum() const
       
   544 {
       
   545     Q_D(const QProgressDialog);
       
   546     return d->bar->maximum();
       
   547 }
       
   548 
       
   549 void QProgressDialog::setMaximum(int maximum)
       
   550 {
       
   551     Q_D(QProgressDialog);
       
   552     d->bar->setMaximum(maximum);
       
   553 }
       
   554 
       
   555 /*!
       
   556     \property QProgressDialog::minimum
       
   557     \brief the lowest value represented by the progress bar
       
   558 
       
   559     The default is 0.
       
   560 
       
   561     \sa maximum, setRange()
       
   562 */
       
   563 
       
   564 int QProgressDialog::minimum() const
       
   565 {
       
   566     Q_D(const QProgressDialog);
       
   567     return d->bar->minimum();
       
   568 }
       
   569 
       
   570 void QProgressDialog::setMinimum(int minimum)
       
   571 {
       
   572     Q_D(QProgressDialog);
       
   573     d->bar->setMinimum(minimum);
       
   574 }
       
   575 
       
   576 /*!
       
   577     Sets the progress dialog's minimum and maximum values
       
   578     to \a minimum and \a maximum, respectively.
       
   579 
       
   580     If \a maximum is smaller than \a minimum, \a minimum becomes the only
       
   581     legal value.
       
   582 
       
   583     If the current value falls outside the new range, the progress
       
   584     dialog is reset with reset().
       
   585 
       
   586     \sa minimum, maximum
       
   587 */
       
   588 void QProgressDialog::setRange(int minimum, int maximum)
       
   589 {
       
   590     Q_D(QProgressDialog);
       
   591     d->bar->setRange(minimum, maximum);
       
   592 }
       
   593 
       
   594 
       
   595 /*!
       
   596   Resets the progress dialog.
       
   597   The progress dialog becomes hidden if autoClose() is true.
       
   598 
       
   599   \sa setAutoClose(), setAutoReset()
       
   600 */
       
   601 
       
   602 void QProgressDialog::reset()
       
   603 {
       
   604     Q_D(QProgressDialog);
       
   605 #ifndef QT_NO_CURSOR
       
   606     if (value() >= 0) {
       
   607         if (parentWidget())
       
   608             parentWidget()->setCursor(d->parentCursor);
       
   609     }
       
   610 #endif
       
   611     if (d->autoClose || d->forceHide)
       
   612         hide();
       
   613     d->bar->reset();
       
   614     d->cancellation_flag = false;
       
   615     d->shown_once = false;
       
   616     d->forceTimer->stop();
       
   617 
       
   618     /*
       
   619         I wish we could disconnect the user slot provided to open() here but
       
   620         unfortunately reset() is usually called before the slot has been invoked.
       
   621         (reset() is itself invoked when canceled() is emitted.)
       
   622     */
       
   623     if (d->receiverToDisconnectOnClose)
       
   624         QMetaObject::invokeMethod(this, "_q_disconnectOnClose", Qt::QueuedConnection);
       
   625 }
       
   626 
       
   627 /*!
       
   628   Resets the progress dialog. wasCanceled() becomes true until
       
   629   the progress dialog is reset.
       
   630   The progress dialog becomes hidden.
       
   631 */
       
   632 
       
   633 void QProgressDialog::cancel()
       
   634 {
       
   635     Q_D(QProgressDialog);
       
   636     d->forceHide = true;
       
   637     reset();
       
   638     d->forceHide = false;
       
   639     d->cancellation_flag = true;
       
   640 }
       
   641 
       
   642 
       
   643 int QProgressDialog::value() const
       
   644 {
       
   645     Q_D(const QProgressDialog);
       
   646     return d->bar->value();
       
   647 }
       
   648 
       
   649 /*!
       
   650   \property QProgressDialog::value
       
   651   \brief the current amount of progress made.
       
   652 
       
   653   For the progress dialog to work as expected, you should initially set
       
   654   this property to 0 and finally set it to
       
   655   QProgressDialog::maximum(); you can call setValue() any number of times
       
   656   in-between.
       
   657 
       
   658   \warning If the progress dialog is modal
       
   659     (see QProgressDialog::QProgressDialog()),
       
   660     setValue() calls QApplication::processEvents(), so take care that
       
   661     this does not cause undesirable re-entrancy in your code. For example,
       
   662     don't use a QProgressDialog inside a paintEvent()!
       
   663 
       
   664   \sa minimum, maximum
       
   665 */
       
   666 void QProgressDialog::setValue(int progress)
       
   667 {
       
   668     Q_D(QProgressDialog);
       
   669     if (progress == d->bar->value()
       
   670         || (d->bar->value() == -1 && progress == d->bar->maximum()))
       
   671         return;
       
   672 
       
   673     d->bar->setValue(progress);
       
   674 
       
   675     if (d->shown_once) {
       
   676         if (isModal())
       
   677             QApplication::processEvents();
       
   678     } else {
       
   679         if (progress == 0) {
       
   680             d->starttime.start();
       
   681             d->forceTimer->start(d->showTime);
       
   682             return;
       
   683         } else {
       
   684             bool need_show;
       
   685             int elapsed = d->starttime.elapsed();
       
   686             if (elapsed >= d->showTime) {
       
   687                 need_show = true;
       
   688             } else {
       
   689                 if (elapsed > minWaitTime) {
       
   690                     int estimate;
       
   691                     int totalSteps = maximum() - minimum();
       
   692                     int myprogress = progress - minimum();
       
   693                     if ((totalSteps - myprogress) >= INT_MAX / elapsed)
       
   694                         estimate = (totalSteps - myprogress) / myprogress * elapsed;
       
   695                     else
       
   696                         estimate = elapsed * (totalSteps - myprogress) / myprogress;
       
   697                     need_show = estimate >= d->showTime;
       
   698                 } else {
       
   699                     need_show = false;
       
   700                 }
       
   701             }
       
   702             if (need_show) {
       
   703                 int w = qMax(isVisible() ? width() : 0, sizeHint().width());
       
   704                 int h = qMax(isVisible() ? height() : 0, sizeHint().height());
       
   705                 resize(w, h);
       
   706                 show();
       
   707                 d->shown_once = true;
       
   708             }
       
   709         }
       
   710 #ifdef Q_WS_MAC
       
   711         QApplication::flush();
       
   712 #endif
       
   713     }
       
   714 
       
   715     if (progress == d->bar->maximum() && d->autoReset)
       
   716         reset();
       
   717 }
       
   718 
       
   719 /*!
       
   720   Returns a size that fits the contents of the progress dialog.
       
   721   The progress dialog resizes itself as required, so you should not
       
   722   need to call this yourself.
       
   723 */
       
   724 
       
   725 QSize QProgressDialog::sizeHint() const
       
   726 {
       
   727     Q_D(const QProgressDialog);
       
   728     QSize sh = d->label ? d->label->sizeHint() : QSize(0, 0);
       
   729     QSize bh = d->bar->sizeHint();
       
   730     int margin = style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin);
       
   731     int spacing = style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
       
   732     int h = margin * 2 + bh.height() + sh.height() + spacing;
       
   733     if (d->cancel)
       
   734         h += d->cancel->sizeHint().height() + spacing;
       
   735 #ifdef Q_WS_S60
       
   736     if (QApplication::desktop()->size().height() > QApplication::desktop()->size().width())
       
   737         return QSize(qMax(QApplication::desktop()->size().width(), sh.width() + 2 * margin), h);
       
   738     else
       
   739         return QSize(qMax(QApplication::desktop()->size().height(), sh.width() + 2 * margin), h);
       
   740 #else
       
   741     return QSize(qMax(200, sh.width() + 2 * margin), h);
       
   742 #endif
       
   743 }
       
   744 
       
   745 /*!\reimp
       
   746 */
       
   747 void QProgressDialog::resizeEvent(QResizeEvent *)
       
   748 {
       
   749     Q_D(QProgressDialog);
       
   750     d->layout();
       
   751 }
       
   752 
       
   753 /*!
       
   754   \reimp
       
   755 */
       
   756 void QProgressDialog::changeEvent(QEvent *ev)
       
   757 {
       
   758     Q_D(QProgressDialog);
       
   759     if (ev->type() == QEvent::StyleChange) {
       
   760         d->layout();
       
   761     } else if (ev->type() == QEvent::LanguageChange) {
       
   762         d->retranslateStrings();
       
   763     }
       
   764     QDialog::changeEvent(ev);
       
   765 }
       
   766 
       
   767 /*!
       
   768     \property QProgressDialog::minimumDuration
       
   769     \brief the time that must pass before the dialog appears
       
   770 
       
   771     If the expected duration of the task is less than the
       
   772     minimumDuration, the dialog will not appear at all. This prevents
       
   773     the dialog popping up for tasks that are quickly over. For tasks
       
   774     that are expected to exceed the minimumDuration, the dialog will
       
   775     pop up after the minimumDuration time or as soon as any progress
       
   776     is set.
       
   777 
       
   778     If set to 0, the dialog is always shown as soon as any progress is
       
   779     set. The default is 4000 milliseconds.
       
   780 */
       
   781 void QProgressDialog::setMinimumDuration(int ms)
       
   782 {
       
   783     Q_D(QProgressDialog);
       
   784     d->showTime = ms;
       
   785     if (d->bar->value() == 0) {
       
   786         d->forceTimer->stop();
       
   787         d->forceTimer->start(ms);
       
   788     }
       
   789 }
       
   790 
       
   791 int QProgressDialog::minimumDuration() const
       
   792 {
       
   793     Q_D(const QProgressDialog);
       
   794     return d->showTime;
       
   795 }
       
   796 
       
   797 
       
   798 /*!
       
   799   \reimp
       
   800 */
       
   801 
       
   802 void QProgressDialog::closeEvent(QCloseEvent *e)
       
   803 {
       
   804     emit canceled();
       
   805     QDialog::closeEvent(e);
       
   806 }
       
   807 
       
   808 /*!
       
   809   \property QProgressDialog::autoReset
       
   810   \brief whether the progress dialog calls reset() as soon as value() equals maximum()
       
   811 
       
   812   The default is true.
       
   813 
       
   814   \sa setAutoClose()
       
   815 */
       
   816 
       
   817 void QProgressDialog::setAutoReset(bool b)
       
   818 {
       
   819     Q_D(QProgressDialog);
       
   820     d->autoReset = b;
       
   821 }
       
   822 
       
   823 bool QProgressDialog::autoReset() const
       
   824 {
       
   825     Q_D(const QProgressDialog);
       
   826     return d->autoReset;
       
   827 }
       
   828 
       
   829 /*!
       
   830   \property QProgressDialog::autoClose
       
   831   \brief whether the dialog gets hidden by reset()
       
   832 
       
   833   The default is true.
       
   834 
       
   835   \sa setAutoReset()
       
   836 */
       
   837 
       
   838 void QProgressDialog::setAutoClose(bool close)
       
   839 {
       
   840     Q_D(QProgressDialog);
       
   841     d->autoClose = close;
       
   842 }
       
   843 
       
   844 bool QProgressDialog::autoClose() const
       
   845 {
       
   846     Q_D(const QProgressDialog);
       
   847     return d->autoClose;
       
   848 }
       
   849 
       
   850 /*!
       
   851   \reimp
       
   852 */
       
   853 
       
   854 void QProgressDialog::showEvent(QShowEvent *e)
       
   855 {
       
   856     Q_D(QProgressDialog);
       
   857     QDialog::showEvent(e);
       
   858     int w = qMax(isVisible() ? width() : 0, sizeHint().width());
       
   859     int h = qMax(isVisible() ? height() : 0, sizeHint().height());
       
   860     resize(w, h);
       
   861     d->forceTimer->stop();
       
   862 }
       
   863 
       
   864 /*!
       
   865   Shows the dialog if it is still hidden after the algorithm has been started
       
   866   and minimumDuration milliseconds have passed.
       
   867 
       
   868   \sa setMinimumDuration()
       
   869 */
       
   870 
       
   871 void QProgressDialog::forceShow()
       
   872 {
       
   873     Q_D(QProgressDialog);
       
   874     d->forceTimer->stop();
       
   875     if (d->shown_once || d->cancellation_flag)
       
   876         return;
       
   877 
       
   878     show();
       
   879     d->shown_once = true;
       
   880 }
       
   881 
       
   882 /*!
       
   883     \since 4.5
       
   884     \overload
       
   885 
       
   886     Opens the dialog and connects its accepted() signal to the slot specified
       
   887     by \a receiver and \a member.
       
   888 
       
   889     The signal will be disconnected from the slot when the dialog is closed.
       
   890 */
       
   891 void QProgressDialog::open(QObject *receiver, const char *member)
       
   892 {
       
   893     Q_D(QProgressDialog);
       
   894     connect(this, SIGNAL(canceled()), receiver, member);
       
   895     d->receiverToDisconnectOnClose = receiver;
       
   896     d->memberToDisconnectOnClose = member;
       
   897     QDialog::open();
       
   898 }
       
   899 
       
   900 QT_END_NAMESPACE
       
   901 
       
   902 #include "moc_qprogressdialog.cpp"
       
   903 
       
   904 #endif // QT_NO_PROGRESSDIALOG