VirtualBox

Ignore:
Timestamp:
Oct 30, 2009 11:07:40 AM (15 years ago)
Author:
vboxsync
Message:

FE/Qt4: Relayout the progress dialog a bit & make the ETA text more user friendly.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/include/QIDialog.h

    r23031 r24182  
    66
    77/*
    8  * Copyright (C) 2008 Sun Microsystems, Inc.
     8 * Copyright (C) 2008-2009 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2727#include <QDialog>
    2828
     29/* Qt forwards declarations */
     30class QEventLoop;
     31
    2932class QIDialog: public QDialog
    3033{
     
    3235
    3336public:
    34 
    3537    QIDialog (QWidget *aParent = 0, Qt::WindowFlags aFlags = 0);
     38    void setVisible (bool aVisible);
    3639
    3740public slots:
    38     int exec();
     41    int exec (bool aShow = true);
    3942
    4043protected:
    41 
    4244    void showEvent (QShowEvent *aEvent);
    4345
     46private:
     47    /* Private member vars */
    4448    bool mPolished;
     49    QEventLoop *mEventLoop;
    4550};
    4651
    4752#endif /* __QIDialog_h__ */
     53
  • trunk/src/VBox/Frontends/VirtualBox/include/VBoxCocoaSpecialControls.h

    r24107 r24182  
    4949    QSize sizeHint() const;
    5050
     51    void setText (const QString& aText);
    5152    void setToolTip (const QString& aTip);
    5253
  • trunk/src/VBox/Frontends/VirtualBox/include/VBoxProgressDialog.h

    r20594 r24182  
    3030class CProgress;
    3131class QILabel;
     32class VBoxMiniCancelButton;
    3233
    3334/* Qt forward declarations */
    34 class QEventLoop;
    3535class QProgressBar;
    3636
     
    5353
    5454public:
    55 
    5655    VBoxProgressDialog (CProgress &aProgress, const QString &aTitle,
    5756                        int aMinDuration = 2000, QWidget *aParent = 0);
     
    6160
    6261protected:
    63 
    6462    virtual void retranslateUi();
    6563
     
    7068
    7169private slots:
    72 
    7370    void showDialog();
    7471    void cancelOperation();
    7572
    7673private:
    77 
    7874    /* Private member vars */
    7975    CProgress &mProgress;
    8076    QILabel *mLabel;
    8177    QILabel *mETA;
    82     QString mETAText;
     78    QString mETAText[14];
     79    QString mCancelText;
    8380    QProgressBar *mProgressBar;
    84     QEventLoop *mEventLoop;
     81    VBoxMiniCancelButton *mCancelBtn;
    8582    bool mCancelEnabled;
    8683    const ulong mOpCount;
  • trunk/src/VBox/Frontends/VirtualBox/include/VBoxSpecialControls.h

    r24107 r24182  
    4747    VBoxMiniCancelButton (QWidget *aParent = 0);
    4848
     49    void setText (const QString &aText) { mButton->setText (aText); }
    4950    void setToolTip (const QString &aTip) { mButton->setToolTip (aTip); }
    5051
  • trunk/src/VBox/Frontends/VirtualBox/src/QIDialog.cpp

    r23031 r24182  
    66
    77/*
    8  * Copyright (C) 2008 Sun Microsystems, Inc.
     8 * Copyright (C) 2008-2009 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2121 */
    2222
    23 
     23/* VBox includes */
    2424#include "QIDialog.h"
    2525#include "VBoxGlobal.h"
    2626#ifdef Q_WS_MAC
    27 #include "VBoxUtils.h"
     27# include "VBoxUtils.h"
    2828#endif /* Q_WS_MAC */
    2929
    30 QIDialog::QIDialog (QWidget *aParent, Qt::WindowFlags aFlags)
     30/* Qt includes */
     31#include <QPointer>
     32
     33QIDialog::QIDialog (QWidget *aParent /* = 0 */, Qt::WindowFlags aFlags /* = 0 */)
    3134    : QDialog (aParent, aFlags)
    3235    , mPolished (false)
     36    , mEventLoop (0)
    3337{
    3438}
     
    6165}
    6266
    63 int QIDialog::exec()
     67int QIDialog::exec (bool aShow /* = true */)
    6468{
    65 #if QT_VERSION >= 0x040500
    66     /* After 4.5 exec ignores the Qt::Sheet flag. See "New Ways of Using
    67      * Dialogs" in http://doc.trolltech.com/qq/QtQuarterly30.pdf why. Because
    68      * we are lazy, we recreate the old behavior. */
     69    /* Reset the result code */
     70    setResult (QDialog::Rejected);
     71
     72    bool wasDeleteOnClose = testAttribute (Qt::WA_DeleteOnClose);
     73    setAttribute (Qt::WA_DeleteOnClose, false);
     74#if defined(Q_WS_MAC) && QT_VERSION >= 0x040500
     75    /* After 4.5 Qt changed the behavior of Sheets for the window/application
     76     * modal case. See "New Ways of Using Dialogs" in
     77     * http://doc.trolltech.com/qq/QtQuarterly30.pdf why. We want the old
     78     * behavior back, where all modal windows where shown as sheets. So make
     79     * the modal mode window, but be application modal in any case. */
     80    Qt::WindowModality winModality = windowModality();
     81    bool wasSetWinModality = testAttribute (Qt::WA_SetWindowModality);
    6982    if ((windowFlags() & Qt::Sheet) == Qt::Sheet)
    7083    {
    71         QEventLoop eventLoop;
    72         connect(this, SIGNAL(finished(int)),
    73                 &eventLoop, SLOT(quit()));
    74         /* Use the new open call. */
    75         open();
    76         eventLoop.exec();
     84        setWindowModality (Qt::WindowModal);
     85        setAttribute (Qt::WA_SetWindowModality, false);
     86    }
     87#endif /* defined(Q_WS_MAC) && QT_VERSION >= 0x040500 */
     88    /* The dialog has to modal in any case. Save the current modality to
     89     * restore it later. */
     90    bool wasShowModal = testAttribute (Qt::WA_ShowModal);
     91    setAttribute (Qt::WA_ShowModal, true);
    7792
    78         return result();
     93    /* Create a local event loop */
     94    mEventLoop = new QEventLoop();
     95    /* Show the window if requested */
     96    if (aShow)
     97        show();
     98    /* A guard to ourself for the case we destroy ourself. */
     99    QPointer<QIDialog> guard = this;
     100    /* Start the event loop. This blocks. */
     101    mEventLoop->exec();
     102    /* Delete the event loop */
     103    delete mEventLoop;
     104    mEventLoop = 0;
     105    /* Are we valid anymore? */
     106    if (guard.isNull())
     107        return QDialog::Rejected;
     108    /* Save the result code in case we delete ourself */
     109    QDialog::DialogCode res = (QDialog::DialogCode)result();
     110#if defined(Q_WS_MAC) && QT_VERSION >= 0x040500
     111    /* Restore old modality mode */
     112    if ((windowFlags() & Qt::Sheet) == Qt::Sheet)
     113    {
     114        setWindowModality (winModality);
     115        setAttribute (Qt::WA_SetWindowModality, wasSetWinModality);
    79116    }
    80     else
    81 #endif /* QT_VERSION >= 0x040500 */
    82         return QDialog::exec();
     117#endif /* defined(Q_WS_MAC) && QT_VERSION >= 0x040500 */
     118    /* Set the old show modal attribute */
     119    setAttribute (Qt::WA_ShowModal, wasShowModal);
     120    /* Delete us in the case we should do so on close */
     121    if (wasDeleteOnClose)
     122        delete this;
     123    /* Return the final result */
     124    return res;
    83125}
     126
     127void QIDialog::setVisible (bool aVisible)
     128{
     129    QDialog::setVisible (aVisible);
     130    /* Exit from the event loop if there is any and we are changing our state
     131     * from visible to invisible. */
     132    if (mEventLoop && !aVisible)
     133        mEventLoop->exit();
     134}
     135
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxProgressDialog.cpp

    r20594 r24182  
    2727#include "VBoxGlobal.h"
    2828#include "VBoxProgressDialog.h"
    29 
     29#include "VBoxSpecialControls.h"
    3030#ifdef Q_WS_MAC
    3131# include "VBoxUtils-darwin.h"
     
    4040#include <QVBoxLayout>
    4141
     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
    4247const char *VBoxProgressDialog::sOpDescTpl = "%1... (%2/%3)";
    4348
     
    4651                                        int aMinDuration /* = 2000 */,
    4752                                        QWidget *aParent /* = 0 */)
     53//  : QIDialog (aParent, Qt::Sheet | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)
    4854  : QIDialog (aParent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint)
    4955  , mProgress (aProgress)
    50   , mEventLoop (new QEventLoop (this))
     56  , mCancelBtn (0)
    5157  , mCancelEnabled (false)
    5258  , mOpCount (mProgress.GetOperationCount())
     
    5662    setModal (true);
    5763
    58     QVBoxLayout *pMainLayout = new QVBoxLayout (this);
     64    QVBoxLayout *pLayout1 = new QVBoxLayout (this);
    5965
    6066#ifdef Q_WS_MAC
    6167    ::darwinSetHidesAllTitleButtons (this);
    6268    ::darwinSetShowsResizeIndicator (this, false);
    63     VBoxGlobal::setLayoutMargin (pMainLayout, 6);
     69    VBoxGlobal::setLayoutMargin (pLayout1, 6);
    6470#endif /* Q_WS_MAC */
    6571
    6672    mLabel = new QILabel (this);
    67     pMainLayout->addWidget (mLabel);
    68     pMainLayout->setAlignment (mLabel, Qt::AlignHCenter);
     73    pLayout1->addWidget (mLabel, 0, Qt::AlignHCenter);
     74
     75    QHBoxLayout *pLayout2 = new QHBoxLayout();
     76    pLayout2->setMargin (0);
     77    pLayout1->addLayout (pLayout2);
    6978
    7079    mProgressBar = new QProgressBar (this);
    71     pMainLayout->addWidget (mProgressBar);
    72 
    73     QHBoxLayout *pLayout1 = new QHBoxLayout();
    74     pLayout1->setMargin (0);
    75     mETA = new QILabel (this);
    76     pLayout1->addWidget (mETA);
    77     pMainLayout->addLayout (pLayout1);
     80    pLayout2->addWidget (mProgressBar, 0, Qt::AlignVCenter);
    7881
    7982    if (mOpCount > 1)
     
    9093    if (mCancelEnabled)
    9194    {
    92         QDialogButtonBox *pBtnBox = new QDialogButtonBox (QDialogButtonBox::Cancel,
    93                                                           Qt::Horizontal, this);
    94         pLayout1->addWidget (pBtnBox);
    95         connect (pBtnBox, SIGNAL (rejected()), this, SLOT (cancelOperation()));
    96     }
     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);
    97105
    98106    retranslateUi();
     
    105113void VBoxProgressDialog::retranslateUi()
    106114{
    107     mETAText = tr ("Time remaining: %1");
     115    mETAText[ 0] = tr ("%1 days, %2 hours remaining");
     116    mETAText[ 1] = tr ("%1 days, %2 minutes remaining");
     117    mETAText[ 2] = tr ("%1 days remaining");
     118    mETAText[ 3] = tr ("1 day, %1 hours remaining");
     119    mETAText[ 4] = tr ("1 day, %1 minutes remaining");
     120    mETAText[ 5] = tr ("1 day remaining");
     121    mETAText[ 6] = tr ("%1 hours, %2 minutes remaining");
     122    mETAText[ 7] = tr ("1 hour, %1 minutes remaining");
     123    mETAText[ 8] = tr ("1 hour remaining");
     124    mETAText[ 9] = tr ("%1 minutes remaining");
     125    mETAText[10] = tr ("1 minute, %2 seconds remaining");
     126    mETAText[11] = tr ("1 minute remaining");
     127    mETAText[12] = tr ("%1 seconds remaining");
     128    mETAText[13] = tr ("A few seconds remaining");
     129
     130    mCancelText = tr ("Canceling...");
     131    if (mCancelBtn)
     132    {
     133        mCancelBtn->setText (tr ("&Cancel"));
     134        mCancelBtn->setToolTip (tr ("Cancel the current operation"));
     135    }
    108136}
    109137
     
    118146        QApplication::setOverrideCursor (QCursor (Qt::WaitCursor));
    119147
    120         /* Enter the modal loop */
    121         mEventLoop->exec();
     148        /* Enter the modal loop, but don't show the window immediately */
     149        exec (false);
    122150
    123151        /* Kill refresh timer */
    124152        killTimer (id);
     153
     154        QApplication::restoreOverrideCursor();
    125155
    126156        return result();
     
    142172void VBoxProgressDialog::cancelOperation()
    143173{
     174    if (mCancelBtn)
     175        mCancelBtn->setEnabled (false);
    144176    mProgress.Cancel();
    145177}
     
    153185     * being exit overlapping 'this'. */
    154186    if (mEnded && !isHidden())
     187    {
    155188        hide();
     189        return;
     190    }
     191    else if (mEnded)
     192        return;
    156193
    157194    if (!mEnded && (!mProgress.isOk() || mProgress.GetCompleted()))
     
    161198        {
    162199            mProgressBar->setValue (100);
    163             setResult (Accepted);
     200            done (Accepted);
    164201        }
    165202        /* Progress is not valid */
    166203        else
    167             setResult (Rejected);
     204            done (Rejected);
    168205
    169206        /* Request to exit loop */
    170207        mEnded = true;
    171 
    172         /* The progress will be finalized
    173          * on next timer iteration. */
    174         return;
    175     }
    176 
    177     if (mEnded)
    178     {
    179         if (mEventLoop->isRunning())
    180         {
    181             /* Exit loop if it is running */
    182             mEventLoop->quit();
    183 
    184             /* Restore normal cursor */
    185             QApplication::restoreOverrideCursor();
    186         }
    187208        return;
    188209    }
     
    193214        /* First ETA */
    194215        long newTime = mProgress.GetTimeRemaining();
    195         if (newTime >= 0)
    196         {
    197             QTime time (0, 0);
    198             time = time.addSecs (newTime);
    199             mETA->setText (mETAText.arg (time.toString()));
    200         }
     216        QDateTime time;
     217        time.setTime_t (newTime);
     218        QDateTime refTime;
     219        refTime.setTime_t (0);
     220
     221        int days = refTime.daysTo (time);
     222        int hours = time.addDays (-days).time().hour();
     223        int minutes = time.addDays (-days).time().minute();
     224        int seconds = time.addDays (-days).time().second();
     225        if (newTime > VBOX_DAY * 2 + VBOX_HOUR)
     226            mETA->setText (mETAText[ 0].arg (days).arg (hours));
     227        else if (newTime > VBOX_DAY * 2 + VBOX_MINUTE * 5)
     228            mETA->setText (mETAText[ 1].arg (days).arg (minutes));
     229        else if (newTime > VBOX_DAY * 2)
     230            mETA->setText (mETAText[ 2].arg (days));
     231        else if (newTime > VBOX_DAY + VBOX_HOUR)
     232            mETA->setText (mETAText[ 3].arg (hours));
     233        else if (newTime > VBOX_DAY + VBOX_MINUTE * 5)
     234            mETA->setText (mETAText[ 4].arg (minutes));
     235        else if (newTime > VBOX_HOUR * 23 + VBOX_MINUTE * 55)
     236            mETA->setText (mETAText[ 5]);
     237        else if (newTime > VBOX_HOUR * 2)
     238            mETA->setText (mETAText[ 6].arg (hours).arg (minutes));
     239        else if (newTime > VBOX_HOUR + VBOX_MINUTE * 5)
     240            mETA->setText (mETAText[ 7].arg (hours).arg (minutes));
     241        else if (newTime > VBOX_MINUTE * 55)
     242            mETA->setText (mETAText[ 8]);
     243        else if (newTime > VBOX_MINUTE * 2)
     244            mETA->setText (mETAText[ 9].arg (minutes));
     245        else if (newTime > VBOX_MINUTE + VBOX_SECOND * 5)
     246            mETA->setText (mETAText[10].arg (seconds));
     247        else if (newTime > VBOX_SECOND * 55)
     248            mETA->setText (mETAText[11]);
     249        else if (newTime > VBOX_SECOND * 5)
     250            mETA->setText (mETAText[12].arg (seconds));
     251        else if (newTime >= 0)
     252            mETA->setText (mETAText[13]);
    201253        else
    202254            mETA->clear();
     255
    203256        /* Then operation text if changed */
    204257        ulong newOp = mProgress.GetOperation() + 1;
     
    211264        }
    212265        mProgressBar->setValue (mProgress.GetPercent());
    213     }
     266    }else
     267        mETA->setText (mCancelText);
    214268}
    215269
     
    217271{
    218272    if (mCancelEnabled)
    219         QIDialog::reject();
     273        cancelOperation();
    220274}
    221275
     
    223277{
    224278    if (mCancelEnabled)
    225         QIDialog::closeEvent (aEvent);
     279        cancelOperation();
    226280    else
    227281        aEvent->ignore();
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxSpecialControls.cpp

    r24107 r24182  
    7575    setFocusPolicy (Qt::TabFocus);
    7676    setShortcut (QKeySequence (Qt::Key_Escape));
    77     setIcon (VBoxGlobal::iconSet (":/delete_16px.png",
    78                                   ":/delete_dis_16px.png"));
     77    QIcon cancelIcon = style()->standardIcon (QStyle::SP_DialogCancelButton);
     78    if (cancelIcon.isNull())
     79        cancelIcon = VBoxGlobal::iconSet (":/delete_16px.png",
     80                                          ":/delete_dis_16px.png");
     81    setIcon (cancelIcon);
    7982}
    8083
  • trunk/src/VBox/Frontends/VirtualBox/src/darwin/VBoxCocoaSpecialControls.mm

    r24107 r24182  
    248248}
    249249
     250void VBoxCocoaButton::setText (const QString& aText)
     251{
     252    QString s (aText);
     253    /* Set it for accessibility reasons as alternative title */
     254    [mNativeRef setAlternateTitle: ::darwinQStringToNSString (s.remove ('&'))];
     255}
     256
    250257void VBoxCocoaButton::setToolTip (const QString& aTip)
    251258{
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette