VirtualBox

Ignore:
Timestamp:
Mar 18, 2009 4:53:59 PM (16 years ago)
Author:
vboxsync
Message:

FE/Qt4: 3627: Shorten error dialogs. Added support for chained-messages.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r17784 r18071  
    294294# Sources containing local definitions of classes that use the Q_OBJECT macro.
    295295VirtualBox_QT_MOCSRCS = \
     296        src/QIMessageBox.cpp \
    296297        src/VBoxSelectorWnd.cpp \
    297298        src/VBoxConsoleWnd.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/include/QIMessageBox.h

    r17108 r18071  
    2828
    2929/* Qt includes */
     30#include <QCheckBox>
    3031#include <QMessageBox>
    31 #include <QCheckBox>
    3232#include <QTextEdit>
    3333
     
    4242class QPushButton;
    4343class QSpacerItem;
    44 class QToolButton;
    45 class QVBoxLayout;
    46 
    47 /** @class QIArrowButton
    48  *
    49  *  The QIArrowButton class is an arrow tool-botton with text-label.
    50  *  It is declared here until moved into separate file in case
    51  *  of it will be used somewhere except problem-reporter dialog.
    52  */
    53 class QIArrowButton : public QWidget
    54 {
    55     Q_OBJECT;
    56 
    57 public:
    58 
    59     QIArrowButton (const QString &aName, QWidget *aParent = 0);
    60 
    61     bool isExpanded() const;
    62 
    63     void animateClick();
    64 
    65 signals:
    66 
    67     void clicked();
    68 
    69 private slots:
    70 
    71     void buttonClicked();
    72 
    73 private:
    74 
    75     void updateIcon();
    76 
    77     bool eventFilter (QObject *aObject, QEvent *aEvent);
    78 
    79     void paintEvent (QPaintEvent *aEvent);
    80 
    81     bool mIsExpanded;
    82     QToolButton *mButton;
    83     QLabel *mLabel;
    84 };
    85 
    86 /** @class QIArrowSplitter
    87  *
    88  *  The QIArrowSplitter class is a folding widget placeholder.
    89  *  It is declared here until moved into separate file in case
    90  *  of it will be used somewhere except problem-reporter dialog.
    91  */
    92 class QIArrowSplitter : public QWidget
    93 {
    94     Q_OBJECT;
    95 
    96 public:
    97 
    98     QIArrowSplitter (QWidget *aParent = 0);
    99 
    100     void addWidget (const QString &aName, QWidget *aWidget);
    101 
    102 public slots:
    103 
    104     void toggleWidget();
    105 
    106 private:
    107 
    108     bool eventFilter (QObject *aObject, QEvent *aEvent);
    109 
    110     QVBoxLayout *mMainLayout;
    111     QList <QIArrowButton*> mButtonsList;
    112     QList <QWidget*> mWidgetsList;
    113 };
    11444
    11545/** @class QIMessageBox
     
    16292    void setDetailsText (const QString &aText);
    16393
    164     bool isDetailsShown() const { return mDetailsVBox->isVisible(); }
    165     void setDetailsShown (bool aShown);
    166 
    16794    QPixmap standardPixmap (QIMessageBox::Icon aIcon);
    16895
     
    174101    void showEvent (QShowEvent *e);
    175102
     103    void refreshDetails();
     104    void setDetailsShown (bool aShown);
     105
    176106private slots:
     107
     108    void detailsBack();
     109    void detailsNext();
    177110
    178111    void done0() { mWasDone = true; done (mButton0 & ButtonMask); }
     
    194127    QSpacerItem *mSpacer;
    195128    QIDialogButtonBox *mButtonBox;
     129    QString mText;
     130    QList < QPair <QString, QString> > mDetailsList;
     131    int mDetailsIndex;
    196132    bool mWasDone : 1;
    197133    bool mWasPolished : 1;
  • trunk/src/VBox/Frontends/VirtualBox/src/QIMessageBox.cpp

    r17640 r18071  
    3939#include <QToolButton>
    4040
    41 /** @class QIArrowButton
    42  *
    43  *  The QIArrowButton class is an arrow tool-botton with text-label.
    44  */
    45 QIArrowButton::QIArrowButton (const QString &aName, QWidget *aParent)
    46     : QWidget (aParent)
    47     , mIsExpanded (false)
    48     , mButton (new QToolButton())
    49     , mLabel (new QLabel (aName))
    50 {
    51     /* Setup itself */
    52     setFocusPolicy (Qt::StrongFocus);
    53 
    54     /* Setup tool-button */
    55     mButton->setAutoRaise (true);
    56     mButton->setFixedSize (17, 16);
    57     mButton->setFocusPolicy (Qt::NoFocus);
    58     mButton->setStyleSheet ("QToolButton {border: 0px none black;}");
    59     connect (mButton, SIGNAL (clicked (bool)), this, SLOT (buttonClicked()));
    60     updateIcon();
    61 
    62     /* Setup text-label */
    63     mLabel->setBuddy (mButton);
    64     mLabel->setStyleSheet ("QLabel {padding: 2px 0px 2px 0px;}");
    65 
    66     /* Setup main-layout */
    67     QHBoxLayout *mainLayout = new QHBoxLayout (this);
    68     VBoxGlobal::setLayoutMargin (mainLayout, 0);
    69     mainLayout->setSpacing (0);
    70     mainLayout->addWidget (mButton);
    71     mainLayout->addWidget (mLabel);
    72     mainLayout->addStretch();
    73 
    74     /* Install event-filter */
    75     qApp->installEventFilter (this);
    76 }
    77 
    78 bool QIArrowButton::isExpanded() const
    79 {
    80     return mIsExpanded;
    81 }
    82 
    83 void QIArrowButton::animateClick()
    84 {
    85     mButton->animateClick();
    86 }
    87 
    88 void QIArrowButton::buttonClicked()
    89 {
    90     mIsExpanded = !mIsExpanded;
    91     updateIcon();
    92     emit clicked();
    93 }
    94 
    95 void QIArrowButton::updateIcon()
    96 {
    97     mButton->setIcon (VBoxGlobal::iconSet (mIsExpanded ?
    98                       ":/arrow_down_10px.png" : ":/arrow_right_10px.png"));
    99 }
    100 
    101 bool QIArrowButton::eventFilter (QObject *aObject, QEvent *aEvent)
    102 {
    103     /* Process only QIArrowButton or children */
    104     if (!(aObject == this || children().contains (aObject)))
     41/** @class QIRichToolButton
     42 *
     43 *  The QIRichToolButton class is a tool-botton with separate text-label.
     44 *  It is declared here until moved into separate file in case
     45 *  of it will be used somewhere except problem-reporter dialog.
     46 */
     47class QIRichToolButton : public QWidget
     48{
     49    Q_OBJECT;
     50
     51public:
     52
     53    QIRichToolButton (const QString &aName = QString::null, QWidget *aParent = 0)
     54        : QWidget (aParent)
     55        , mButton (new QToolButton())
     56        , mLabel (new QLabel (aName))
     57    {
     58        /* Setup itself */
     59        setFocusPolicy (Qt::StrongFocus);
     60
     61        /* Setup tool-button */
     62        mButton->setAutoRaise (true);
     63        mButton->setFixedSize (17, 16);
     64        mButton->setFocusPolicy (Qt::NoFocus);
     65        mButton->setStyleSheet ("QToolButton {border: 0px none black;}");
     66        connect (mButton, SIGNAL (clicked (bool)), this, SLOT (buttonClicked()));
     67
     68        /* Setup text-label */
     69        mLabel->setBuddy (mButton);
     70        mLabel->setStyleSheet ("QLabel {padding: 2px 0px 2px 0px;}");
     71
     72        /* Setup main-layout */
     73        QHBoxLayout *mainLayout = new QHBoxLayout (this);
     74        VBoxGlobal::setLayoutMargin (mainLayout, 0);
     75        mainLayout->setSpacing (0);
     76        mainLayout->addWidget (mButton);
     77        mainLayout->addWidget (mLabel);
     78
     79        /* Install event-filter */
     80        qApp->installEventFilter (this);
     81    }
     82
     83    void animateClick() { mButton->animateClick(); }
     84
     85    void setText (const QString &aName) { mLabel->setText (aName); }
     86
     87signals:
     88
     89    void clicked();
     90
     91protected slots:
     92
     93    virtual void buttonClicked()
     94    {
     95        emit clicked();
     96    }
     97
     98protected:
     99
     100    bool eventFilter (QObject *aObject, QEvent *aEvent)
     101    {
     102        /* Process only QIRichToolButton or children */
     103        if (!(aObject == this || children().contains (aObject)))
     104            return QWidget::eventFilter (aObject, aEvent);
     105
     106        /* Process keyboard events */
     107        if (aEvent->type() == QEvent::KeyPress)
     108        {
     109            QKeyEvent *kEvent = static_cast <QKeyEvent*> (aEvent);
     110            if (kEvent->key() == Qt::Key_Space)
     111                animateClick();
     112        }
     113
     114        /* Process mouse events */
     115        if ((aEvent->type() == QEvent::MouseButtonPress ||
     116             aEvent->type() == QEvent::MouseButtonDblClick)
     117            && aObject == mLabel)
     118        {
     119            /* Label click as toggle */
     120            animateClick();
     121        }
     122
     123        /* Default one handler */
    105124        return QWidget::eventFilter (aObject, aEvent);
    106 
    107     /* Process some keyboard events */
    108     if (aEvent->type() == QEvent::KeyPress)
    109     {
    110         QKeyEvent *kEvent = static_cast <QKeyEvent*> (aEvent);
    111         switch (kEvent->key())
     125    }
     126
     127    void paintEvent (QPaintEvent *aEvent)
     128    {
     129        /* Draw focus around mLabel if focused */
     130        if (hasFocus())
    112131        {
    113             /* "+" as expand */
    114             case Qt::Key_Plus:
     132            QStylePainter painter (this);
     133            QStyleOptionFocusRect option;
     134            option.initFrom (this);
     135            option.rect = mLabel->frameGeometry();
     136            painter.drawPrimitive (QStyle::PE_FrameFocusRect, option);
     137        }
     138        QWidget::paintEvent (aEvent);
     139    }
     140
     141    QToolButton *mButton;
     142    QLabel *mLabel;
     143};
     144
     145/** @class QIArrowButtonSwitch
     146 *
     147 *  The QIArrowButtonSwitch class is an arrow tool-botton with text-label,
     148 *  used as collaps/expand switch in QIMessageBox class.
     149 *  It is declared here until moved into separate file in case
     150 *  of it will be used somewhere except problem-reporter dialog.
     151 */
     152class QIArrowButtonSwitch : public QIRichToolButton
     153{
     154    Q_OBJECT;
     155
     156public:
     157
     158    QIArrowButtonSwitch (const QString &aName = QString::null, QWidget *aParent = 0)
     159        : QIRichToolButton (aName, aParent)
     160        , mIsExpanded (false)
     161    {
     162        updateIcon();
     163    }
     164
     165    bool isExpanded() const { return mIsExpanded; }
     166
     167private slots:
     168
     169    void buttonClicked()
     170    {
     171        mIsExpanded = !mIsExpanded;
     172        updateIcon();
     173        QIRichToolButton::buttonClicked();
     174    }
     175
     176private:
     177
     178    void updateIcon()
     179    {
     180        mButton->setIcon (VBoxGlobal::iconSet (mIsExpanded ?
     181                          ":/arrow_down_10px.png" : ":/arrow_right_10px.png"));
     182    }
     183
     184    bool eventFilter (QObject *aObject, QEvent *aEvent)
     185    {
     186        /* Process only QIArrowButtonSwitch or children */
     187        if (!(aObject == this || children().contains (aObject)))
     188            return QIRichToolButton::eventFilter (aObject, aEvent);
     189
     190        /* Process keyboard events */
     191        if (aEvent->type() == QEvent::KeyPress)
     192        {
     193            QKeyEvent *kEvent = static_cast <QKeyEvent*> (aEvent);
     194            if ((mIsExpanded && kEvent->key() == Qt::Key_Minus) ||
     195                (!mIsExpanded && kEvent->key() == Qt::Key_Plus))
     196                animateClick();
     197        }
     198
     199        /* Default one handler */
     200        return QIRichToolButton::eventFilter (aObject, aEvent);
     201    }
     202
     203    bool mIsExpanded;
     204};
     205
     206/** @class QIArrowButtonPress
     207 *
     208 *  The QIArrowButtonPress class is an arrow tool-botton with text-label,
     209 *  used as back/next buttons in QIMessageBox class.
     210 *  It is declared here until moved into separate file in case
     211 *  of it will be used somewhere except problem-reporter dialog.
     212 */
     213class QIArrowButtonPress : public QIRichToolButton
     214{
     215    Q_OBJECT;
     216
     217public:
     218
     219    QIArrowButtonPress (bool aNext, const QString &aName = QString::null, QWidget *aParent = 0)
     220        : QIRichToolButton (aName, aParent)
     221        , mNext (aNext)
     222    {
     223        updateIcon();
     224    }
     225
     226private:
     227
     228    void updateIcon()
     229    {
     230        mButton->setIcon (VBoxGlobal::iconSet (mNext ?
     231                          ":/arrow_right_10px.png" : ":/arrow_left_10px.png"));
     232    }
     233
     234    bool eventFilter (QObject *aObject, QEvent *aEvent)
     235    {
     236        /* Process only QIArrowButtonPress or children */
     237        if (!(aObject == this || children().contains (aObject)))
     238            return QIRichToolButton::eventFilter (aObject, aEvent);
     239
     240        /* Process keyboard events */
     241        if (aEvent->type() == QEvent::KeyPress)
     242        {
     243            QKeyEvent *kEvent = static_cast <QKeyEvent*> (aEvent);
     244            if ((mNext && kEvent->key() == Qt::Key_PageUp) ||
     245                (!mNext && kEvent->key() == Qt::Key_PageDown))
     246                animateClick();
     247        }
     248
     249        /* Default one handler */
     250        return QIRichToolButton::eventFilter (aObject, aEvent);
     251    }
     252
     253    bool mNext;
     254};
     255
     256/** @class QIArrowSplitter
     257 *
     258 *  The QIArrowSplitter class is a folding widget placeholder.
     259 *  It is declared here until moved into separate file in case
     260 *  of it will be used somewhere except problem-reporter dialog.
     261 */
     262class QIArrowSplitter : public QWidget
     263{
     264    Q_OBJECT;
     265
     266public:
     267
     268    QIArrowSplitter (QWidget *aChild, QWidget *aParent = 0)
     269        : QWidget (aParent)
     270        , mMainLayout (new QVBoxLayout (this))
     271        , mSwitchButton (new QIArrowButtonSwitch())
     272        , mBackButton (new QIArrowButtonPress (false, tr ("&Back")))
     273        , mNextButton (new QIArrowButtonPress (true,  tr ("&Next")))
     274        , mChild (aChild)
     275    {
     276        /* Setup main-layout */
     277        VBoxGlobal::setLayoutMargin (mMainLayout, 0);
     278
     279        /* Setup buttons */
     280        mBackButton->setVisible (false);
     281        mNextButton->setVisible (false);
     282
     283        /* Setup connections */
     284        connect (mSwitchButton, SIGNAL (clicked()), this, SLOT (toggleWidget()));
     285        connect (mBackButton, SIGNAL (clicked()), this, SIGNAL (showBackDetails()));
     286        connect (mNextButton, SIGNAL (clicked()), this, SIGNAL (showNextDetails()));
     287
     288        /* Setup button layout */
     289        QHBoxLayout *buttonLayout = new QHBoxLayout();
     290        VBoxGlobal::setLayoutMargin (buttonLayout, 0);
     291        buttonLayout->setSpacing (0);
     292        buttonLayout->addWidget (mSwitchButton);
     293        buttonLayout->addStretch();
     294        buttonLayout->addWidget (mBackButton);
     295        buttonLayout->addWidget (mNextButton);
     296
     297        /* Append layout with children */
     298        mMainLayout->addLayout (buttonLayout);
     299        mMainLayout->addWidget (mChild);
     300
     301        /* Install event-filter */
     302        qApp->installEventFilter (this);
     303    }
     304
     305    void setMultiPaging (bool aMultiPage)
     306    {
     307        mBackButton->setVisible (aMultiPage);
     308        mNextButton->setVisible (aMultiPage);
     309    }
     310
     311    void setButtonEnabled (bool aNext, bool aEnabled)
     312    {
     313        aNext ? mNextButton->setEnabled (aEnabled)
     314              : mBackButton->setEnabled (aEnabled);
     315    }
     316
     317    void setName (const QString &aName)
     318    {
     319        mSwitchButton->setText (aName);
     320        relayout();
     321    }
     322
     323public slots:
     324
     325    void toggleWidget()
     326    {
     327        mChild->setVisible (mSwitchButton->isExpanded());
     328        relayout();
     329    }
     330
     331signals:
     332
     333    void showBackDetails();
     334    void showNextDetails();
     335
     336private:
     337
     338    bool eventFilter (QObject *aObject, QEvent *aEvent)
     339    {
     340        /* Process only parent window children */
     341        if (!(aObject == window() || window()->children().contains (aObject)))
     342            return QWidget::eventFilter (aObject, aEvent);
     343
     344        /* Do not process QIArrowButtonSwitch & QIArrowButtonPress children */
     345        if (aObject == mSwitchButton ||
     346            aObject == mBackButton ||
     347            aObject == mNextButton ||
     348            mSwitchButton->children().contains (aObject) ||
     349            mBackButton->children().contains (aObject) ||
     350            mNextButton->children().contains (aObject))
     351            return QWidget::eventFilter (aObject, aEvent);
     352
     353        /* Process some keyboard events */
     354        if (aEvent->type() == QEvent::KeyPress)
     355        {
     356            QKeyEvent *kEvent = static_cast <QKeyEvent*> (aEvent);
     357            switch (kEvent->key())
    115358            {
    116                 if (!mIsExpanded)
    117                     mButton->animateClick();
    118                 break;
    119             }
    120             /* "-" as collapse */
    121             case Qt::Key_Minus:
    122             {
    123                 if (mIsExpanded)
    124                     mButton->animateClick();
    125                 break;
    126             }
    127             /* Space as toggle */
    128             case Qt::Key_Space:
    129             {
    130                 mButton->animateClick();
    131                 break;
     359                case Qt::Key_Plus:
     360                {
     361                    if (!mSwitchButton->isExpanded())
     362                        mSwitchButton->animateClick();
     363                    break;
     364                }
     365                case Qt::Key_Minus:
     366                {
     367                    if (mSwitchButton->isExpanded())
     368                        mSwitchButton->animateClick();
     369                    break;
     370                }
     371                case Qt::Key_PageUp:
     372                {
     373                    if (mNextButton->isEnabled())
     374                        mNextButton->animateClick();
     375                    break;
     376                }
     377                case Qt::Key_PageDown:
     378                {
     379                    if (mBackButton->isEnabled())
     380                        mBackButton->animateClick();
     381                    break;
     382                }
    132383            }
    133384        }
    134     }
    135 
    136     /* Process some mouse events */
    137     if ((aEvent->type() == QEvent::MouseButtonPress ||
    138          aEvent->type() == QEvent::MouseButtonDblClick)
    139         && aObject == mLabel)
    140     {
    141         /* Label click as toggle */
    142         mButton->animateClick();
    143     }
    144 
    145     /* Default one handler */
    146     return QWidget::eventFilter (aObject, aEvent);
    147 }
    148 
    149 void QIArrowButton::paintEvent (QPaintEvent *aEvent)
    150 {
    151     if (hasFocus())
    152     {
    153         QStylePainter painter (this);
    154         QStyleOptionFocusRect option;
    155         option.initFrom (this);
    156         option.rect = mLabel->frameGeometry();
    157         painter.drawPrimitive (QStyle::PE_FrameFocusRect, option);
    158     }
    159     QWidget::paintEvent (aEvent);
    160 }
    161 
    162 /** @class QIArrowSplitter
    163  *
    164  *  The QIArrowSplitter class is a folding widget placeholder.
    165  */
    166 QIArrowSplitter::QIArrowSplitter (QWidget *aParent)
    167     : QWidget (aParent)
    168     , mMainLayout (new QVBoxLayout (this))
    169 {
    170     /* Setup main-layout */
    171     VBoxGlobal::setLayoutMargin (mMainLayout, 0);
    172 
    173     /* Install event-filter */
    174     qApp->installEventFilter (this);
    175 }
    176 
    177 void QIArrowSplitter::addWidget (const QString &aName, QWidget *aWidget)
    178 {
    179     /* Creating arrow button */
    180     QIArrowButton *button = new QIArrowButton (aName);
    181     connect (button, SIGNAL (clicked()), this, SLOT (toggleWidget()));
    182 
    183     /* Append internal lists */
    184     mButtonsList.append (button);
    185     mWidgetsList.append (aWidget);
    186 
    187     /* Append layout with children */
    188     mMainLayout->addWidget (button);
    189     mMainLayout->addWidget (aWidget);
    190 }
    191 
    192 void QIArrowSplitter::toggleWidget()
    193 {
    194     QIArrowButton *clickedButton = qobject_cast <QIArrowButton*> (sender());
    195 
    196     foreach (QIArrowButton *button, mButtonsList)
    197     {
    198         if ((button == clickedButton) || !clickedButton)
     385
     386        /* Default one handler */
     387        return QWidget::eventFilter (aObject, aEvent);
     388    }
     389
     390    void relayout()
     391    {
     392        /* Update full layout system of message window */
     393        QList <QLayout*> layouts = findChildren <QLayout*> ();
     394        foreach (QLayout *item, layouts)
    199395        {
    200             QWidget *relatedWidget = mWidgetsList [mButtonsList.indexOf (button)];
    201             Assert (relatedWidget);
    202             relatedWidget->setVisible (button->isExpanded());
     396            item->update();
     397            item->activate();
    203398        }
    204     }
    205 
    206     /* Update full layout system of message window */
    207     QList <QLayout*> layouts = findChildren <QLayout*> ();
    208     foreach (QLayout *item, layouts)
    209     {
    210         item->update();
    211         item->activate();
    212     }
    213 
    214     /* Update main layout of message window at last */
    215     window()->layout()->update();
    216     window()->layout()->activate();
    217     qApp->processEvents();
    218 
    219     /* Now resize window to minimum possible size */
    220     window()->resize (window()->minimumSizeHint());
    221     qApp->processEvents();
    222 
    223     /* Check if we have to make dialog fixed in height */
    224     bool makeFixedHeight = true;
    225     foreach (QIArrowButton *button, mButtonsList)
    226     {
    227         if (button->isExpanded())
    228         {
    229             makeFixedHeight = false;
    230             break;
    231         }
    232     }
    233     if (makeFixedHeight)
    234         window()->setFixedHeight (window()->minimumSizeHint().height());
    235     else
    236         window()->setMaximumHeight (QWIDGETSIZE_MAX);
    237 }
    238 
    239 bool QIArrowSplitter::eventFilter (QObject *aObject, QEvent *aEvent)
    240 {
    241     /* Process only parent window children */
    242     if (!(aObject == window() || window()->children().contains (aObject)))
    243         return QWidget::eventFilter (aObject, aEvent);
    244 
    245     /* Do not process QIArrowButton children */
    246     foreach (QIArrowButton *button, mButtonsList)
    247         if (button->children().contains (aObject))
    248             return QWidget::eventFilter (aObject, aEvent);
    249 
    250     /* Process some keyboard events */
    251     if (aEvent->type() == QEvent::KeyPress)
    252     {
    253         QKeyEvent *kEvent = static_cast <QKeyEvent*> (aEvent);
    254         switch (kEvent->key())
    255         {
    256             case Qt::Key_Plus:
    257             {
    258                 foreach (QIArrowButton *button, mButtonsList)
    259                     if (!button->isExpanded())
    260                         button->animateClick();
    261                 break;
    262             }
    263             case Qt::Key_Minus:
    264             {
    265                 foreach (QIArrowButton *button, mButtonsList)
    266                     if (button->isExpanded())
    267                         button->animateClick();
    268                 break;
    269             }
    270         }
    271     }
    272 
    273     /* Default one handler */
    274     return QWidget::eventFilter (aObject, aEvent);
    275 }
     399
     400        /* Update main layout of message window at last */
     401        window()->layout()->update();
     402        window()->layout()->activate();
     403        qApp->processEvents();
     404
     405        /* Now resize window to minimum possible size */
     406        window()->resize (window()->minimumSizeHint());
     407        qApp->processEvents();
     408
     409        /* Check if we have to make dialog fixed in height */
     410        if (mSwitchButton->isExpanded())
     411            window()->setMaximumHeight (QWIDGETSIZE_MAX);
     412        else
     413            window()->setFixedHeight (window()->minimumSizeHint().height());
     414    }
     415
     416    QVBoxLayout *mMainLayout;
     417    QIArrowButtonSwitch *mSwitchButton;
     418    QIArrowButtonPress *mBackButton;
     419    QIArrowButtonPress *mNextButton;
     420    QWidget *mChild;
     421};
    276422
    277423/** @class QIMessageBox
     
    289435                            QWidget *aParent, const char *aName, bool aModal)
    290436    : QIDialog (aParent)
     437    , mText (aText)
     438    , mDetailsIndex (-1)
    291439    , mWasDone (false)
    292440    , mWasPolished (false)
     
    302450#endif /* Q_WS_MAC */
    303451
    304 
    305452    setWindowTitle (aCaption);
    306453    /* Necessary to later find some of the message boxes */
     
    358505    detailsVBoxLayout->setSpacing (10);
    359506
    360     mDetailsSplitter = new QIArrowSplitter();
    361     detailsVBoxLayout->addWidget (mDetailsSplitter);
    362 
    363507    mDetailsText = new QTextEdit();
    364508    {
     
    372516    mDetailsText->setSizePolicy (QSizePolicy::Expanding,
    373517                                 QSizePolicy::MinimumExpanding);
    374     mDetailsSplitter->addWidget (tr ("&Details"), mDetailsText);
     518    mDetailsSplitter = new QIArrowSplitter (mDetailsText);
     519    connect (mDetailsSplitter, SIGNAL (showBackDetails()), this, SLOT (detailsBack()));
     520    connect (mDetailsSplitter, SIGNAL (showNextDetails()), this, SLOT (detailsNext()));
     521    detailsVBoxLayout->addWidget (mDetailsSplitter);
    375522
    376523    mFlagCB_Details = new QCheckBox();
     
    532679void QIMessageBox::setDetailsText (const QString &aText)
    533680{
    534     QStringList parts (aText.split ("<!--EOM-->", QString::KeepEmptyParts));
    535     if (!parts [0].isEmpty()) mTextLabel->setText (mTextLabel->text() + parts [0]);
    536     if (parts.size() > 1 && !parts [1].isEmpty()) mDetailsText->setText (parts [1]);
    537 }
    538 
    539 /** @fn QIMessageBox::isDetailsShown() const
    540  *
    541  *  Returns true if the optional details box is shown and false otherwise.
    542  *  By default, the details box is not shown.
    543  *
    544  *  @see #setDetailsShown()
    545  *  @see #setDetailsText()
    546  */
    547 
    548 /**
    549  *  Sets the visibility state of the optional details box
    550  *  to a value of the argument.
    551  *
    552  *  @see #isDetailsShown()
    553  *  @see #setDetailsText()
    554  */
    555 void QIMessageBox::setDetailsShown (bool aShown)
    556 {
    557     if (aShown && mDetailsText->toPlainText().isEmpty())
    558         return;
    559 
    560     if (aShown)
    561     {
    562         mFlagCB_Details->setVisible (mFlagCB_Main->isVisible());
    563         mFlagCB_Details->setChecked (mFlagCB_Main->isChecked());
    564         mFlagCB_Details->setText (mFlagCB_Main->text());
    565         if (mFlagCB_Main->hasFocus())
    566             mFlagCB_Details->setFocus();
    567         mFlagCB_Main->setVisible (false);
    568         mFlagCB = mFlagCB_Details;
    569         mSpacer->changeSize (0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum);
    570     }
    571 
    572     mDetailsVBox->setVisible (aShown);
    573 
    574     if (!aShown)
    575     {
    576         mFlagCB_Main->setVisible (mFlagCB_Details->isVisible());
    577         mFlagCB_Main->setChecked (mFlagCB_Details->isChecked());
    578         mFlagCB_Main->setText (mFlagCB_Details->text());
    579         if (mFlagCB_Details->hasFocus())
    580             mFlagCB_Main->setFocus();
    581         mFlagCB = mFlagCB_Main;
    582         mSpacer->changeSize (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
    583     }
     681    AssertMsg (!aText.isEmpty(), ("Details text should NOT be empty."));
     682
     683    QStringList paragraphs (aText.split ("<!--EOP-->", QString::SkipEmptyParts));
     684    AssertMsg (paragraphs.size() != 0, ("There should be at least one paragraph."));
     685
     686    foreach (QString paragraph, paragraphs)
     687    {
     688        QStringList parts (paragraph.split ("<!--EOM-->", QString::KeepEmptyParts));
     689        AssertMsg (parts.size() == 2, ("Each paragraph should consist of 2 parts."));
     690        mDetailsList << QPair <QString, QString> (parts [0], parts [1]);
     691    }
     692
     693    mDetailsSplitter->setMultiPaging (mDetailsList.size() > 1);
     694    mDetailsIndex = 0;
     695    refreshDetails();
    584696}
    585697
     
    641753}
    642754
     755void QIMessageBox::refreshDetails()
     756{
     757    /* Update message text iteself */
     758    mTextLabel->setText (mText + mDetailsList [mDetailsIndex].first);
     759    /* Update details table */
     760    mDetailsText->setText (mDetailsList [mDetailsIndex].second);
     761    setDetailsShown (!mDetailsText->toPlainText().isEmpty());
     762
     763    /* Update multi-paging system */
     764    if (mDetailsList.size() > 1)
     765    {
     766        mDetailsSplitter->setButtonEnabled (true, mDetailsIndex < mDetailsList.size() - 1);
     767        mDetailsSplitter->setButtonEnabled (false, mDetailsIndex > 0);
     768    }
     769
     770    /* Update details label */
     771    mDetailsSplitter->setName (mDetailsList.size() == 1 ? tr ("&Details") :
     772        tr ("&Details (%1 of %2)").arg (mDetailsIndex + 1).arg (mDetailsList.size()));
     773}
     774
     775/**
     776 *  Sets the visibility state of the optional details box
     777 *  to a value of the argument.
     778 *
     779 *  @see #isDetailsShown()
     780 *  @see #setDetailsText()
     781 */
     782void QIMessageBox::setDetailsShown (bool aShown)
     783{
     784    if (aShown)
     785    {
     786        mFlagCB_Details->setVisible (mFlagCB_Main->isVisible());
     787        mFlagCB_Details->setChecked (mFlagCB_Main->isChecked());
     788        mFlagCB_Details->setText (mFlagCB_Main->text());
     789        if (mFlagCB_Main->hasFocus())
     790            mFlagCB_Details->setFocus();
     791        mFlagCB_Main->setVisible (false);
     792        mFlagCB = mFlagCB_Details;
     793        mSpacer->changeSize (0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum);
     794    }
     795
     796    mDetailsVBox->setVisible (aShown);
     797
     798    if (!aShown)
     799    {
     800        mFlagCB_Main->setVisible (mFlagCB_Details->isVisible());
     801        mFlagCB_Main->setChecked (mFlagCB_Details->isChecked());
     802        mFlagCB_Main->setText (mFlagCB_Details->text());
     803        if (mFlagCB_Details->hasFocus())
     804            mFlagCB_Main->setFocus();
     805        mFlagCB = mFlagCB_Main;
     806        mSpacer->changeSize (0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
     807    }
     808}
     809
     810void QIMessageBox::detailsBack()
     811{
     812    if (mDetailsIndex > 0)
     813    {
     814        -- mDetailsIndex;
     815        refreshDetails();
     816    }
     817}
     818
     819void QIMessageBox::detailsNext()
     820{
     821    if (mDetailsIndex < mDetailsList.size() - 1)
     822    {
     823        ++ mDetailsIndex;
     824        refreshDetails();
     825    }
     826}
     827
    643828void QIMessageBox::reject()
    644829{
     
    650835}
    651836
     837#include "QIMessageBox.moc"
     838
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxProblemReporter.cpp

    r18033 r18071  
    339339
    340340    if (!aDetails.isEmpty())
    341     {
    342341        box->setDetailsText (aDetails);
    343         box->setDetailsShown (true);
    344     }
    345342
    346343    if (aAutoConfirmId)
     
    23932390
    23942391    if (aInfo.next())
    2395         formatted = doFormatErrorInfo (*aInfo.next()) +  "<p></p>" +
    2396                     formatted;
     2392        formatted = formatted + "<!--EOP-->" + doFormatErrorInfo (*aInfo.next());
    23972393
    23982394    return formatted;
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