PageRenderTime 74ms CodeModel.GetById 54ms app.highlight 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/VBox/Frontends/VirtualBox/src/widgets/VBoxProgressDialog.cpp

https://gitlab.com/ufo/virtualbox-ose-3-1-8
C++ | 277 lines | 195 code | 37 blank | 45 comment | 46 complexity | 63784f78d759b185c1199b93ebdf311b MD5 | raw file
  1/** @file
  2 *
  3 * VBox frontends: Qt GUI ("VirtualBox"):
  4 * VBoxProgressDialog class implementation
  5 */
  6
  7/*
  8 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
  9 *
 10 * This file is part of VirtualBox Open Source Edition (OSE), as
 11 * available from http://www.virtualbox.org. This file is free software;
 12 * you can redistribute it and/or modify it under the terms of the GNU
 13 * General Public License (GPL) as published by the Free Software
 14 * Foundation, in version 2 as it comes in the "COPYING" file of the
 15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 17 *
 18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 20 * additional information or have any questions.
 21 */
 22
 23/* VBox includes */
 24#include "COMDefs.h"
 25#include "QIDialogButtonBox.h"
 26#include "QILabel.h"
 27#include "VBoxGlobal.h"
 28#include "VBoxProgressDialog.h"
 29#include "VBoxSpecialControls.h"
 30#ifdef Q_WS_MAC
 31# include "VBoxUtils-darwin.h"
 32#endif
 33
 34/* Qt includes */
 35#include <QCloseEvent>
 36#include <QEventLoop>
 37#include <QProgressBar>
 38#include <QTime>
 39#include <QTimer>
 40#include <QVBoxLayout>
 41
 42#define VBOX_SECOND 1
 43#define VBOX_MINUTE VBOX_SECOND * 60
 44#define VBOX_HOUR VBOX_MINUTE * 60
 45#define VBOX_DAY VBOX_HOUR * 24
 46
 47const char *VBoxProgressDialog::sOpDescTpl = "%1... (%2/%3)";
 48
 49VBoxProgressDialog::VBoxProgressDialog (CProgress &aProgress,
 50                                        const QString &aTitle,
 51                                        int aMinDuration /* = 2000 */,
 52                                        QWidget *aParent /* = 0 */)
 53//  : QIDialog (aParent, Qt::Sheet | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)
 54  : QIDialog (aParent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)
 55  , mProgress (aProgress)
 56  , mCancelBtn (0)
 57  , mCancelEnabled (false)
 58  , mOpCount (mProgress.GetOperationCount())
 59  , mCurOp (mProgress.GetOperation() + 1)
 60  , mEnded (false)
 61{
 62    setModal (true);
 63
 64    QVBoxLayout *pLayout1 = new QVBoxLayout (this);
 65
 66#ifdef Q_WS_MAC
 67    ::darwinSetHidesAllTitleButtons (this);
 68    ::darwinSetShowsResizeIndicator (this, false);
 69    VBoxGlobal::setLayoutMargin (pLayout1, 6);
 70#endif /* Q_WS_MAC */
 71
 72    mLabel = new QILabel (this);
 73    pLayout1->addWidget (mLabel, 0, Qt::AlignHCenter);
 74
 75    QHBoxLayout *pLayout2 = new QHBoxLayout();
 76    pLayout2->setMargin (0);
 77    pLayout1->addLayout (pLayout2);
 78
 79    mProgressBar = new QProgressBar (this);
 80    pLayout2->addWidget (mProgressBar, 0, Qt::AlignVCenter);
 81
 82    if (mOpCount > 1)
 83        mLabel->setText (QString (sOpDescTpl)
 84                         .arg (mProgress.GetOperationDescription())
 85                         .arg (mCurOp).arg (mOpCount));
 86    else
 87        mLabel->setText (QString ("%1...")
 88                         .arg (mProgress.GetOperationDescription()));
 89    mProgressBar->setMaximum (100);
 90    setWindowTitle (QString ("%1: %2").arg (aTitle, mProgress.GetDescription()));
 91    mProgressBar->setValue (0);
 92    mCancelEnabled = aProgress.GetCancelable();
 93    if (mCancelEnabled)
 94    {
 95        mCancelBtn = new VBoxMiniCancelButton (this);
 96        mCancelBtn->setFocusPolicy (Qt::ClickFocus);
 97        pLayout2->addWidget (mCancelBtn, 0, Qt::AlignVCenter);
 98        connect (mCancelBtn, SIGNAL (clicked()), this, SLOT (cancelOperation()));
 99    }
100
101    mETA = new QILabel (this);
102    pLayout1->addWidget (mETA, 0, Qt::AlignLeft | Qt::AlignVCenter);
103
104    setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
105
106    retranslateUi();
107
108    /* The progress dialog will be shown automatically after
109     * the duration is over if progress is not finished yet. */
110    QTimer::singleShot (aMinDuration, this, SLOT (showDialog()));
111}
112
113void VBoxProgressDialog::retranslateUi()
114{
115    mCancelText = tr ("Canceling...");
116    if (mCancelBtn)
117    {
118        mCancelBtn->setText (tr ("&Cancel"));
119        mCancelBtn->setToolTip (tr ("Cancel the current operation"));
120    }
121}
122
123int VBoxProgressDialog::run (int aRefreshInterval)
124{
125    if (mProgress.isOk())
126    {
127        /* Start refresh timer */
128        int id = startTimer (aRefreshInterval);
129
130        /* Set busy cursor */
131        QApplication::setOverrideCursor (QCursor (Qt::WaitCursor));
132
133        /* Enter the modal loop, but don't show the window immediately */
134        exec (false);
135
136        /* Kill refresh timer */
137        killTimer (id);
138
139        QApplication::restoreOverrideCursor();
140
141        return result();
142    }
143    return Rejected;
144}
145
146void VBoxProgressDialog::showDialog()
147{
148    /* We should not show progress-dialog
149     * if it was already finalized but not yet closed.
150     * This could happens in case of some other
151     * modal dialog prevents our event-loop from
152     * being exit overlapping 'this'. */
153    if (!mEnded)
154        show();
155}
156
157void VBoxProgressDialog::cancelOperation()
158{
159    if (mCancelBtn)
160        mCancelBtn->setEnabled (false);
161    mProgress.Cancel();
162}
163
164void VBoxProgressDialog::timerEvent (QTimerEvent * /* aEvent */)
165{
166    /* We should hide progress-dialog
167     * if it was already finalized but not yet closed.
168     * This could happens in case of some other
169     * modal dialog prevents our event-loop from
170     * being exit overlapping 'this'. */
171    if (mEnded && !isHidden())
172    {
173        hide();
174        return;
175    }
176    else if (mEnded)
177        return;
178
179    if (!mEnded && (!mProgress.isOk() || mProgress.GetCompleted()))
180    {
181        /* Progress finished */
182        if (mProgress.isOk())
183        {
184            mProgressBar->setValue (100);
185            done (Accepted);
186        }
187        /* Progress is not valid */
188        else
189            done (Rejected);
190
191        /* Request to exit loop */
192        mEnded = true;
193        return;
194    }
195
196    if (!mProgress.GetCanceled())
197    {
198        /* Update the progress dialog */
199        /* First ETA */
200        long newTime = mProgress.GetTimeRemaining();
201        QDateTime time;
202        time.setTime_t (newTime);
203        QDateTime refTime;
204        refTime.setTime_t (0);
205
206        int days = refTime.daysTo (time);
207        int hours = time.addDays (-days).time().hour();
208        int minutes = time.addDays (-days).time().minute();
209        int seconds = time.addDays (-days).time().second();
210
211        QString strDays = VBoxGlobal::daysToString(days);
212        QString strHours = VBoxGlobal::hoursToString(hours);
213        QString strMinutes = VBoxGlobal::minutesToString(minutes);
214        QString strSeconds = VBoxGlobal::secondsToString(seconds);
215
216        QString strTwoComp = tr ("%1, %2 remaining", "You may wish to translate this more like \"Time remaining: %1, %2\"");
217        QString strOneComp = tr ("%1 remaining", "You may wish to translate this more like \"Time remaining: %1\"");
218
219        if (newTime > VBOX_DAY * 2 + VBOX_HOUR)
220            mETA->setText (strTwoComp.arg (strDays).arg (strHours));
221        else if (newTime > VBOX_DAY * 2 + VBOX_MINUTE * 5)
222            mETA->setText (strTwoComp.arg (strDays).arg (strMinutes));
223        else if (newTime > VBOX_DAY * 2)
224            mETA->setText (strOneComp.arg (strDays));
225        else if (newTime > VBOX_DAY + VBOX_HOUR)
226            mETA->setText (strTwoComp.arg (strDays).arg (strHours));
227        else if (newTime > VBOX_DAY + VBOX_MINUTE * 5)
228            mETA->setText (strTwoComp.arg (strDays).arg (strMinutes));
229        else if (newTime > VBOX_HOUR * 23 + VBOX_MINUTE * 55)
230            mETA->setText (strOneComp.arg (strDays));
231        else if (newTime >= VBOX_HOUR * 2)
232            mETA->setText (strTwoComp.arg (strHours).arg (strMinutes));
233        else if (newTime > VBOX_HOUR + VBOX_MINUTE * 5)
234            mETA->setText (strTwoComp.arg (strHours).arg (strMinutes));
235        else if (newTime > VBOX_MINUTE * 55)
236            mETA->setText (strOneComp.arg (strHours));
237        else if (newTime > VBOX_MINUTE * 2)
238            mETA->setText (strOneComp.arg (strMinutes));
239        else if (newTime > VBOX_MINUTE + VBOX_SECOND * 5)
240            mETA->setText (strTwoComp.arg (strMinutes).arg (strSeconds));
241        else if (newTime > VBOX_SECOND * 55)
242            mETA->setText (strOneComp.arg (strMinutes));
243        else if (newTime > VBOX_SECOND * 5)
244            mETA->setText (strOneComp.arg (strSeconds));
245        else if (newTime >= 0)
246            mETA->setText (tr ("A few seconds remaining"));
247        else
248            mETA->clear();
249
250        /* Then operation text if changed */
251        ulong newOp = mProgress.GetOperation() + 1;
252        if (newOp != mCurOp)
253        {
254            mCurOp = newOp;
255            mLabel->setText (QString (sOpDescTpl)
256                             .arg (mProgress.GetOperationDescription())
257                             .arg (mCurOp).arg (mOpCount));
258        }
259        mProgressBar->setValue (mProgress.GetPercent());
260    }else
261        mETA->setText (mCancelText);
262}
263
264void VBoxProgressDialog::reject()
265{
266    if (mCancelEnabled)
267        cancelOperation();
268}
269
270void VBoxProgressDialog::closeEvent (QCloseEvent *aEvent)
271{
272    if (mCancelEnabled)
273        cancelOperation();
274    else
275        aEvent->ignore();
276}
277