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