VirtualBox

Changeset 45658 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Apr 22, 2013 7:31:01 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
85176
Message:

FE/Qt: Popup-center, popup-pane: Implementing main framework stuff (part 8).

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp

    r45605 r45658  
    2020/* GUI includes: */
    2121#include "UIPopupCenter.h"
    22 #include "UIModalWindowManager.h"
    2322#include "UIPopupPane.h"
    2423
     
    6968                            const QString &strButtonText1 /* = QString() */,
    7069                            const QString &strButtonText2 /* = QString() */,
    71                             const QString &strButtonText3 /* = QString() */) const
     70                            const QString &strButtonText3 /* = QString() */)
    7271{
    7372    showPopupPane(pParent, strId,
     
    7877
    7978void UIPopupCenter::error(QWidget *pParent, const QString &strId,
    80                           const QString &strMessage, const QString &strDetails) const
     79                          const QString &strMessage, const QString &strDetails)
    8180{
    8281    message(pParent, strId,
     
    8685
    8786void UIPopupCenter::alert(QWidget *pParent, const QString &strId,
    88                           const QString &strMessage) const
     87                          const QString &strMessage)
    8988{
    9089    error(pParent, strId,
     
    9796                             const QString &strButtonText1 /*= QString()*/,
    9897                             const QString &strButtonText2 /*= QString()*/,
    99                              const QString &strButtonText3 /*= QString()*/) const
     98                             const QString &strButtonText3 /*= QString()*/)
    10099{
    101100    message(pParent, strId,
     
    108107                                   const QString &strMessage,
    109108                                   const QString &strOkButtonText /*= QString()*/,
    110                                    const QString &strCancelButtonText /*= QString()*/) const
     109                                   const QString &strCancelButtonText /*= QString()*/)
    111110{
    112111    question(pParent, strId,
     
    124123                                    const QString &strChoice1ButtonText /*= QString()*/,
    125124                                    const QString &strChoice2ButtonText /*= QString()*/,
    126                                     const QString &strCancelButtonText /*= QString()*/) const
     125                                    const QString &strCancelButtonText /*= QString()*/)
    127126{
    128127    question(pParent, strId,
     
    136135}
    137136
    138 void UIPopupCenter::showPopupPane(QWidget *pParent, const QString &strId,
     137void UIPopupCenter::showPopupPane(QWidget *pParent, const QString &strPopupPaneID,
    139138                                 const QString &strMessage, const QString &strDetails,
    140139                                 int iButton1, int iButton2, int iButton3,
    141                                  const QString &strButtonText1, const QString &strButtonText2, const QString &strButtonText3) const
    142 {
    143     /* Prepare popup-pane: */
    144     UIPopupPane *pPopupPane = 0;
    145     /* Is there already popup-pane with the same ID? */
    146     if (m_popups.contains(strId))
     140                                 const QString &strButtonText1, const QString &strButtonText2, const QString &strButtonText3)
     141{
     142    /* Looking for the corresponding popup-stack: */
     143    QString strPopupStackID = pParent->metaObject()->className();
     144    UIPopupStack *pPopupStack = 0;
     145    /* Is there already popup-stack with the same ID? */
     146    if (m_stacks.contains(strPopupStackID))
    147147    {
    148148        /* Get existing one: */
    149         pPopupPane = m_popups[strId];
    150         /* And update message and details: */
    151         pPopupPane->setMessage(strMessage);
    152         pPopupPane->setDetails(strDetails);
    153     }
    154     /* There is no popup-pane with the same ID? */
     149        pPopupStack = m_stacks[strPopupStackID];
     150    }
     151    /* There is no popup-stack with the same ID? */
    155152    else
    156153    {
    157         /* Choose at least one button to be the 'default' and 'escape': */
    158         if (iButton1 == 0 && iButton2 == 0 && iButton3 == 0)
    159             iButton1 = AlertButton_Ok | AlertButtonOption_Default | AlertButtonOption_Escape;
    160         /* Compose button description map: */
    161         QMap<int, QString> buttonDescriptions;
    162         if (iButton1 != 0 && !buttonDescriptions.contains(iButton1))
    163             buttonDescriptions[iButton1] = strButtonText1;
    164         if (iButton2 != 0 && !buttonDescriptions.contains(iButton2))
    165             buttonDescriptions[iButton2] = strButtonText2;
    166         if (iButton3 != 0 && !buttonDescriptions.contains(iButton3))
    167             buttonDescriptions[iButton3] = strButtonText3;
    168         /* Create popup-pane and insert it into our map: */
    169         QWidget *pPopupBoxParent = windowManager().realParentWindow(pParent ? pParent : windowManager().mainWindowShown());
    170         pPopupPane = new UIPopupPane(pPopupBoxParent, strId, strMessage, strDetails, buttonDescriptions);
    171         m_popups.insert(strId, pPopupPane);
    172         /* Attach popup-pane connections: */
    173         connect(pPopupPane, SIGNAL(sigDone(int)), this, SLOT(sltPopupDone(int)));
    174     }
    175     /* Show popup-pane: */
    176     pPopupPane->show();
    177 }
    178 
    179 void UIPopupCenter::sltPopupDone(int iButtonCode) const
    180 {
    181     /* Make sure the sender is popup: */
    182     const UIPopupPane *pPopup = qobject_cast<UIPopupPane*>(sender());
    183     if (!pPopup)
    184         return;
    185 
    186     /* Make sure the popup is still exists: */
    187     const QString strPopupID(pPopup->id());
    188     const bool fIsPopupStillHere = m_popups.contains(strPopupID);
    189     AssertMsg(fIsPopupStillHere, ("Popup already destroyed!"));
    190     if (!fIsPopupStillHere)
    191         return;
    192 
    193     /* Notify listeners: */
    194     emit sigPopupDone(strPopupID, iButtonCode);
    195 
    196     /* Cleanup the popup: */
    197     m_popups.remove(strPopupID);
    198     delete pPopup;
    199 }
    200 
    201 void UIPopupCenter::remindAboutMouseIntegration(bool fSupportsAbsolute) const
     154        /* Create new one: */
     155        pPopupStack = m_stacks[strPopupStackID] = new UIPopupStack(pParent);
     156        /* Attach popup-stack connections: */
     157        connect(pPopupStack, SIGNAL(sigPopupPaneDone(QString, int)), this, SIGNAL(sigPopupPaneDone(QString, int)));
     158        connect(pPopupStack, SIGNAL(sigRemove()), this, SLOT(sltRemovePopupStack()));
     159    }
     160    /* Show popup-stack: */
     161    pPopupStack->show();
     162
     163    /* Choose at least one button to be the 'default' and 'escape': */
     164    if (iButton1 == 0 && iButton2 == 0 && iButton3 == 0)
     165        iButton1 = AlertButton_Ok | AlertButtonOption_Default | AlertButtonOption_Escape;
     166    /* Compose button description map: */
     167    QMap<int, QString> buttonDescriptions;
     168    if (iButton1 != 0 && !buttonDescriptions.contains(iButton1))
     169        buttonDescriptions[iButton1] = strButtonText1;
     170    if (iButton2 != 0 && !buttonDescriptions.contains(iButton2))
     171        buttonDescriptions[iButton2] = strButtonText2;
     172    if (iButton3 != 0 && !buttonDescriptions.contains(iButton3))
     173        buttonDescriptions[iButton3] = strButtonText3;
     174    /* Update corresponding popup-pane: */
     175    pPopupStack->updatePopupPane(strPopupPaneID, strMessage, strDetails, buttonDescriptions);
     176}
     177
     178void UIPopupCenter::sltRemovePopupStack()
     179{
     180    /* Make sure the sender is the popup-stack: */
     181    UIPopupStack *pPopupStack = qobject_cast<UIPopupStack*>(sender());
     182    if (!pPopupStack)
     183    {
     184        AssertMsgFailed(("Should be called by popup-stack only!"));
     185        return;
     186    }
     187
     188    /* Make sure the popup-stack still exists: */
     189    const QString strPopupStackID(m_stacks.key(pPopupStack, QString()));
     190    if (strPopupStackID.isNull())
     191    {
     192        AssertMsgFailed(("Popup-stack already destroyed!"));
     193        return;
     194    }
     195
     196    /* Cleanup the popup-stack: */
     197    m_stacks.remove(strPopupStackID);
     198    delete pPopupStack;
     199}
     200
     201void UIPopupCenter::remindAboutMouseIntegration(bool fSupportsAbsolute, QWidget *pParent)
    202202{
    203203    if (fSupportsAbsolute)
    204204    {
    205         alert(0, QString("remindAboutMouseIntegration"),
     205        alert(pParent, QString("remindAboutMouseIntegration"),
    206206              tr("<p>The Virtual Machine reports that the guest OS supports <b>mouse pointer integration</b>. "
    207207                 "This means that you do not need to <i>capture</i> the mouse pointer to be able to use it in your guest OS -- "
     
    216216    else
    217217    {
    218         alert(0, QString("remindAboutMouseIntegration"),
     218        alert(pParent, QString("remindAboutMouseIntegration"),
    219219              tr("<p>The Virtual Machine reports that the guest OS does not support <b>mouse pointer integration</b> "
    220220                 "in the current video mode. You need to capture the mouse (by clicking over the VM display "
     
    223223}
    224224
     225
     226/* Qt includes: */
     227#include <QVBoxLayout>
     228#include <QEvent>
     229#include <QMainWindow>
     230#include <QStatusBar>
     231
     232UIPopupStack::UIPopupStack(QWidget *pParent)
     233    : QWidget(pParent)
     234    , m_fPolished(false)
     235    , m_iStackLayoutMargin(0)
     236    , m_iStackLayoutSpacing(0)
     237    , m_iParentStatusBarHeight(parentStatusBarHeight(pParent))
     238{
     239    /* Prepare: */
     240    prepare();
     241}
     242
     243void UIPopupStack::updatePopupPane(const QString &strPopupPaneID,
     244                                   const QString &strMessage, const QString &strDetails,
     245                                   const QMap<int, QString> &buttonDescriptions)
     246{
     247    /* Looking for the corresponding popup-pane: */
     248    UIPopupPane *pPopupPane = 0;
     249    /* Is there already popup-pane with the same ID? */
     250    if (m_panes.contains(strPopupPaneID))
     251    {
     252        /* Get existing one: */
     253        pPopupPane = m_panes[strPopupPaneID];
     254        /* And update message and details: */
     255        pPopupPane->setMessage(strMessage);
     256        pPopupPane->setDetails(strDetails);
     257    }
     258    /* There is no popup-pane with the same ID? */
     259    else
     260    {
     261        /* Create new one: */
     262        pPopupPane = m_panes[strPopupPaneID] = new UIPopupPane(this,
     263                                                               strMessage, strDetails,
     264                                                               buttonDescriptions);
     265        pPopupPane->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
     266        /* Attach popup-pane connection: */
     267        connect(pPopupPane, SIGNAL(sigSizeHintChanged()), this, SLOT(sltAdjustGeometry()));
     268        connect(pPopupPane, SIGNAL(sigDone(int)), this, SLOT(sltPopupPaneDone(int)));
     269        /* Show popup-pane: */
     270        pPopupPane->show();
     271    }
     272
     273    /* Propagate desired width: */
     274    setDesiredWidth(parentWidget()->width());
     275    /* Adjust geometry: */
     276    sltAdjustGeometry();
     277}
     278
     279void UIPopupStack::sltAdjustGeometry()
     280{
     281    /* Get this attributes: */
     282    const int iWidth = parentWidget()->width();
     283    const int iHeight = minimumHeightHint();
     284
     285    /* Move according parent: */
     286    move(0, parentWidget()->height() - iHeight - m_iParentStatusBarHeight);
     287    /* Resize according parent: */
     288    resize(iWidth, iHeight);
     289
     290    /* Layout content: */
     291    layoutContent();
     292}
     293
     294void UIPopupStack::sltPopupPaneDone(int iButtonCode)
     295{
     296    /* Make sure the sender is the popup-pane: */
     297    UIPopupPane *pPopupPane = qobject_cast<UIPopupPane*>(sender());
     298    if (!pPopupPane)
     299    {
     300        AssertMsgFailed(("Should be called by popup-pane only!"));
     301        return;
     302    }
     303
     304    /* Make sure the popup-pane still exists: */
     305    const QString strPopupPaneID(m_panes.key(pPopupPane, QString()));
     306    if (strPopupPaneID.isNull())
     307    {
     308        AssertMsgFailed(("Popup-pane already destroyed!"));
     309        return;
     310    }
     311
     312    /* Notify listeners about popup-pane: */
     313    emit sigPopupPaneDone(strPopupPaneID, iButtonCode);
     314
     315    /* Cleanup the popup-pane: */
     316    m_panes.remove(strPopupPaneID);
     317    delete pPopupPane;
     318
     319    /* Make sure this stack still contains popup-panes: */
     320    if (!m_panes.isEmpty())
     321        return;
     322
     323    /* Notify listeners about popup-stack: */
     324    emit sigRemove();
     325}
     326
     327void UIPopupStack::prepare()
     328{
     329    /* Install event-filter to parent: */
     330    parent()->installEventFilter(this);
     331}
     332
     333int UIPopupStack::minimumWidthHint()
     334{
     335    /* Prepare width hint: */
     336    int iWidthHint = 0;
     337
     338    /* Take into account all the panes: */
     339    foreach (UIPopupPane *pPane, m_panes)
     340        iWidthHint = qMax(iWidthHint, pPane->minimumWidthHint());
     341
     342    /* And two margins finally: */
     343    iWidthHint += 2 * m_iStackLayoutMargin;
     344
     345    /* Return width hint: */
     346    return iWidthHint;
     347}
     348
     349int UIPopupStack::minimumHeightHint()
     350{
     351    /* Prepare height hint: */
     352    int iHeightHint = 0;
     353
     354    /* Take into account all the panes: */
     355    foreach (UIPopupPane *pPane, m_panes)
     356        iHeightHint += pPane->minimumHeightHint();
     357
     358    /* Take into account all the spacings, if any: */
     359    if (!m_panes.isEmpty())
     360        iHeightHint += (m_panes.size() - 1) * m_iStackLayoutSpacing;
     361
     362    /* And two margins finally: */
     363    iHeightHint += 2 * m_iStackLayoutMargin;
     364
     365    /* Return height hint: */
     366    return iHeightHint;
     367}
     368
     369QSize UIPopupStack::minimumSizeHint()
     370{
     371    /* Wrap reimplemented getters: */
     372    return QSize(minimumWidthHint(), minimumHeightHint());
     373}
     374
     375void UIPopupStack::setDesiredWidth(int iWidth)
     376{
     377    /* Propagate desired width to all the popup-panes we have: */
     378    foreach (UIPopupPane *pPane, m_panes)
     379        pPane->setDesiredWidth(iWidth - 2 * m_iStackLayoutMargin);
     380}
     381
     382void UIPopupStack::layoutContent()
     383{
     384    /* Get attributes: */
     385    const int iWidth = width();
     386    const int iHeight = height();
     387    int iX = m_iStackLayoutMargin;
     388    int iY = iHeight - m_iStackLayoutMargin;
     389
     390    /* Layout every pane we have: */
     391    foreach (UIPopupPane *pPane, m_panes)
     392    {
     393        /* Get pane attributes: */
     394        const int iPaneWidth = iWidth - 2 * m_iStackLayoutMargin;
     395        const int iPaneHeight = pPane->minimumHeightHint();
     396        /* Adjust geometry for the pane: */
     397        pPane->move(iX, iY - iPaneHeight);
     398        pPane->resize(iPaneWidth, iPaneHeight);
     399        pPane->layoutContent();
     400        /* Increment placeholder: */
     401        iY -= (iPaneHeight + m_iStackLayoutSpacing);
     402    }
     403}
     404
     405bool UIPopupStack::eventFilter(QObject *pWatched, QEvent *pEvent)
     406{
     407    /* Make sure its parent event came: */
     408    if (pWatched != parent())
     409        return false;
     410
     411    /* Make sure its resize event came: */
     412    if (pEvent->type() != QEvent::Resize)
     413        return false;
     414
     415    /* Propagate desired width: */
     416    setDesiredWidth(parentWidget()->width());
     417    /* Adjust geometry: */
     418    sltAdjustGeometry();
     419
     420    /* Do not filter anything: */
     421    return false;
     422}
     423
     424void UIPopupStack::showEvent(QShowEvent *pEvent)
     425{
     426    /* Make sure we should polish dialog: */
     427    if (m_fPolished)
     428        return;
     429
     430    /* Call to polish-event: */
     431    polishEvent(pEvent);
     432
     433    /* Mark dialog as polished: */
     434    m_fPolished = true;
     435}
     436
     437void UIPopupStack::polishEvent(QShowEvent*)
     438{
     439    /* Propagate desired width: */
     440    setDesiredWidth(parentWidget()->width());
     441    /* Adjust geometry: */
     442    sltAdjustGeometry();
     443}
     444
     445/* static */
     446int UIPopupStack::parentStatusBarHeight(QWidget *pParent)
     447{
     448    /* Check if passed parent is QMainWindow and contains status-bar: */
     449    if (QMainWindow *pParentWindow = qobject_cast<QMainWindow*>(pParent))
     450        if (pParentWindow->statusBar())
     451            return pParentWindow->statusBar()->height();
     452    /* Zero by default: */
     453    return 0;
     454}
     455
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.h

    r45523 r45658  
    2727/* Forward declaration: */
    2828class QWidget;
     29class UIPopupStack;
    2930class UIPopupPane;
    3031
     
    3637signals:
    3738
    38     /* Notifier: Popup done stuff: */
    39     void sigPopupDone(QString strId, int iButtonCode) const;
     39    /* Notifier: Popup-pane done stuff: */
     40    void sigPopupPaneDone(QString strID, int iButtonCode);
    4041
    4142public:
     
    5152                 const QString &strButtonText1 = QString(),
    5253                 const QString &strButtonText2 = QString(),
    53                  const QString &strButtonText3 = QString()) const;
     54                 const QString &strButtonText3 = QString());
    5455
    5556    /* API: Wrapper to 'message' function.
    5657     * Provides single OK button: */
    5758    void error(QWidget *pParent, const QString &strId,
    58                const QString &strMessage, const QString &strDetails) const;
     59               const QString &strMessage, const QString &strDetails);
    5960
    6061    /* API: Wrapper to 'error' function.
    6162     * Omits details: */
    6263    void alert(QWidget *pParent, const QString &strId,
    63                const QString &strMessage) const;
     64               const QString &strMessage);
    6465
    6566    /* API: Wrapper to 'message' function.
     
    7071                  const QString &strButtonText1 = QString(),
    7172                  const QString &strButtonText2 = QString(),
    72                   const QString &strButtonText3 = QString()) const;
     73                  const QString &strButtonText3 = QString());
    7374
    7475    /* API: Wrapper to 'question' function,
     
    7778                        const QString &strMessage,
    7879                        const QString &strOkButtonText = QString(),
    79                         const QString &strCancelButtonText = QString()) const;
     80                        const QString &strCancelButtonText = QString());
    8081
    8182    /* API: Wrapper to 'question' function,
     
    8586                         const QString &strChoice1ButtonText = QString(),
    8687                         const QString &strChoice2ButtonText = QString(),
    87                          const QString &strCancelButtonText = QString()) const;
     88                         const QString &strCancelButtonText = QString());
    8889
    8990    /* API: Runtime UI stuff: */
    90     void remindAboutMouseIntegration(bool fSupportsAbsolute) const;
     91    void remindAboutMouseIntegration(bool fSupportsAbsolute, QWidget *pParent);
    9192
    9293private slots:
    9394
    94     /* Handler: Popup done stuff: */
    95     void sltPopupDone(int iButtonCode) const;
     95    /* Handler: Popup-stack stuff: */
     96    void sltRemovePopupStack();
    9697
    9798private:
     
    102103
    103104    /* Helper: Popup-pane stuff: */
    104     void showPopupPane(QWidget *pParent, const QString &strId,
     105    void showPopupPane(QWidget *pParent, const QString &strPopupPaneID,
    105106                       const QString &strMessage, const QString &strDetails,
    106107                       int iButton1, int iButton2, int iButton3,
    107                        const QString &strButtonText1, const QString &strButtonText2, const QString &strButtonText3) const;
     108                       const QString &strButtonText1, const QString &strButtonText2, const QString &strButtonText3);
    108109
    109     /* Variables: Popup-pane stuff: */
    110     mutable QMap<QString, QPointer<UIPopupPane> > m_popups;
     110    /* Variables: Popup-stack stuff: */
     111    QMap<QString, QPointer<UIPopupStack> > m_stacks;
    111112
    112113    /* Instance stuff: */
     
    119120inline UIPopupCenter& popupCenter() { return *UIPopupCenter::instance(); }
    120121
     122
     123/* Qt includes: */
     124#include <QWidget>
     125
     126/* Popup-stack prototype class: */
     127class UIPopupStack : public QWidget
     128{
     129    Q_OBJECT;
     130
     131signals:
     132
     133    /* Notifier: Popup-pane stuff: */
     134    void sigPopupPaneDone(QString strID, int iButtonCode);
     135
     136    /* Notifier: Popup-stack stuff: */
     137    void sigRemove();
     138
     139public:
     140
     141    /* Constructor: */
     142    UIPopupStack(QWidget *pParent);
     143
     144    /* API: Popup-pane stuff: */
     145    void updatePopupPane(const QString &strPopupPaneID,
     146                         const QString &strMessage, const QString &strDetails,
     147                         const QMap<int, QString> &buttonDescriptions);
     148
     149private slots:
     150
     151    /* Handler: Layout stuff: */
     152    void sltAdjustGeometry();
     153
     154    /* Handler: Popup-pane stuff: */
     155    void sltPopupPaneDone(int iButtonCode);
     156
     157private:
     158
     159    /* Prepare stuff: */
     160    void prepare();
     161
     162    /* Helpers: Layout stuff: */
     163    int minimumWidthHint();
     164    int minimumHeightHint();
     165    QSize minimumSizeHint();
     166    void setDesiredWidth(int iWidth);
     167    void layoutContent();
     168
     169    /* Handler: Event-filter stuff: */
     170    bool eventFilter(QObject *pWatched, QEvent *pEvent);
     171
     172    /* Handlers: Event stuff: */
     173    virtual void showEvent(QShowEvent *pEvent);
     174    virtual void polishEvent(QShowEvent *pEvent);
     175
     176    /* Static helpers: Prepare stuff: */
     177    static int parentStatusBarHeight(QWidget *pParent);
     178
     179    /* Variables: */
     180    bool m_fPolished;
     181    const int m_iStackLayoutMargin;
     182    const int m_iStackLayoutSpacing;
     183    QMap<QString, UIPopupPane*> m_panes;
     184    const int m_iParentStatusBarHeight;
     185};
     186
    121187#endif /* __UIPopupCenter_h__ */
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.cpp

    r45608 r45658  
    2222#include <QVBoxLayout>
    2323#include <QLabel>
    24 #include <QPushButton>
    25 #include <QEvent>
    2624#include <QKeyEvent>
    27 #include <QMainWindow>
    28 #include <QStatusBar>
    2925#include <QPainter>
    3026#include <QStateMachine>
     
    159155{
    160156    Q_OBJECT;
     157    Q_PROPERTY(QSize collapsedSizeHint READ collapsedSizeHint);
     158    Q_PROPERTY(QSize expandedSizeHint READ expandedSizeHint);
     159    Q_PROPERTY(QSize minimumSizeHint READ minimumSizeHint WRITE setMinimumSizeHint);
    161160
    162161signals:
     
    167166
    168167    /* Notifier: Animation stuff: */
    169     void sigSizeChanged();
     168    void sigSizeHintChanged();
    170169
    171170public:
     
    182181    /* API: Size-hint stuff: */
    183182    QSize minimumSizeHint() const;
    184     QSize sizeHint() const;
     183    void setMinimumSizeHint(const QSize &minimumSizeHint);
    185184
    186185private slots:
     
    197196
    198197    /* Helper: Size-hint stuff: */
    199     void updateGeometry();
    200 
    201     /* Handler: Animation stuff: */
    202     void resizeEvent(QResizeEvent *pEvent);
     198    QSize collapsedSizeHint() const { return m_collapsedSizeHint; }
     199    QSize expandedSizeHint() const { return m_expandedSizeHint; }
     200    void updateSizeHint();
    203201
    204202    /* Variables: Label stuff: */
     
    207205
    208206    /* Variables: Size-hint stuff: */
     207    QSize m_collapsedSizeHint;
     208    QSize m_expandedSizeHint;
    209209    QSize m_minimumSizeHint;
    210     QSize m_sizeHint;
    211210
    212211    /* Variables: Animation stuff: */
     
    264263
    265264
    266 UIPopupPane::UIPopupPane(QWidget *pParent, const QString &strId,
     265UIPopupPane::UIPopupPane(QWidget *pParent,
    267266                         const QString &strMessage, const QString &strDetails,
    268267                         const QMap<int, QString> &buttonDescriptions)
    269268    : QWidget(pParent)
    270     , m_fPolished(false)
    271     , m_strId(strId)
    272269    , m_iMainLayoutMargin(2), m_iMainFrameLayoutMargin(10), m_iMainFrameLayoutSpacing(5)
    273     , m_iParentStatusBarHeight(parentStatusBarHeight(pParent))
    274270    , m_strMessage(strMessage), m_strDetails(strDetails), m_buttonDescriptions(buttonDescriptions)
    275271    , m_fHovered(false) , m_fFocused(false)
     
    301297}
    302298
     299void UIPopupPane::setDesiredWidth(int iWidth)
     300{
     301    /* Make sure text-pane exists: */
     302    if (!m_pTextPane)
     303        return;
     304
     305    /* Propagate desired width to the text-pane we have: */
     306    m_pTextPane->setDesiredWidth(iWidth - 2 * m_iMainLayoutMargin
     307                                        - 2 * m_iMainFrameLayoutMargin
     308                                        - m_pButtonPane->minimumSizeHint().width());
     309}
     310
     311int UIPopupPane::minimumWidthHint() const
     312{
     313    /* Prepare width hint: */
     314    int iWidthHint = 0;
     315
     316    /* Take into account main layout: */
     317    iWidthHint += 2 * m_iMainLayoutMargin;
     318    {
     319        /* Take into account main-frame layout: */
     320        iWidthHint += 2 * m_iMainFrameLayoutMargin;
     321        {
     322            /* Take into account widgets: */
     323            iWidthHint += m_pTextPane->minimumSizeHint().width();
     324            iWidthHint += m_iMainFrameLayoutSpacing;
     325            iWidthHint += m_pButtonPane->minimumSizeHint().width();
     326        }
     327    }
     328
     329    /* Return width hint: */
     330    return iWidthHint;
     331}
     332
     333int UIPopupPane::minimumHeightHint() const
     334{
     335    /* Prepare height hint: */
     336    int iHeightHint = 0;
     337
     338    /* Take into account main layout: */
     339    iHeightHint += 2 * m_iMainLayoutMargin;
     340    {
     341        /* Take into account main-frame layout: */
     342        iHeightHint += 2 * m_iMainFrameLayoutMargin;
     343        {
     344            /* Take into account widgets: */
     345            const int iTextPaneHeight = m_pTextPane->minimumSizeHint().height();
     346            const int iButtonBoxHeight = m_pButtonPane->minimumSizeHint().height();
     347            iHeightHint += qMax(iTextPaneHeight, iButtonBoxHeight);
     348        }
     349    }
     350
     351    /* Return height hint: */
     352    return iHeightHint;
     353}
     354
     355QSize UIPopupPane::minimumSizeHint() const
     356{
     357    /* Wrap reimplemented getters: */
     358    return QSize(minimumWidthHint(), minimumHeightHint());
     359}
     360
     361void UIPopupPane::layoutContent()
     362{
     363    /* This attributes: */
     364    const int iWidth = width();
     365    const int iHeight = height();
     366    /* Main layout: */
     367    {
     368        /* Main-frame: */
     369        const int iMainFrameWidth = iWidth - 2 * m_iMainLayoutMargin;
     370        const int iMainFrameHeight = iHeight - 2 * m_iMainLayoutMargin;
     371        m_pMainFrame->move(m_iMainLayoutMargin, m_iMainLayoutMargin);
     372        m_pMainFrame->resize(iMainFrameWidth, iMainFrameHeight);
     373        /* Main-frame layout: */
     374        {
     375            /* Variables: */
     376            const QSize buttonPaneMinimumSizeHint = m_pButtonPane->minimumSizeHint();
     377            const int iButtonPaneMinimumWidth = buttonPaneMinimumSizeHint.width();
     378            const int iButtonPaneMinimumHeight = buttonPaneMinimumSizeHint.height();
     379            const int iTextPaneWidth = iMainFrameWidth - 2 * m_iMainFrameLayoutMargin - m_iMainFrameLayoutSpacing - iButtonPaneMinimumWidth;
     380            const int iTextPaneHeight = m_pTextPane->minimumSizeHint().height();
     381            const int iMaximumHeight = qMax(iTextPaneHeight, iButtonPaneMinimumHeight);
     382            const int iMinimumHeight = qMin(iTextPaneHeight, iButtonPaneMinimumHeight);
     383            const int iHeightShift = (iMaximumHeight - iMinimumHeight) / 2;
     384            const bool fTextPaneShifted = iTextPaneHeight < iButtonPaneMinimumHeight;
     385            /* Text-pane: */
     386            m_pTextPane->move(m_iMainFrameLayoutMargin,
     387                              fTextPaneShifted ? m_iMainFrameLayoutMargin + iHeightShift : m_iMainFrameLayoutMargin);
     388            m_pTextPane->resize(iTextPaneWidth,
     389                                iTextPaneHeight);
     390            /* Button-box: */
     391            m_pButtonPane->move(m_iMainFrameLayoutMargin + iTextPaneWidth + m_iMainFrameLayoutSpacing,
     392                                m_iMainFrameLayoutMargin);
     393            m_pButtonPane->resize(iButtonPaneMinimumWidth,
     394                                  iMainFrameHeight - 2 * m_iMainFrameLayoutMargin);
     395        }
     396    }
     397}
     398
    303399void UIPopupPane::sltButtonClicked(int iButtonID)
    304400{
     
    306402}
    307403
    308 void UIPopupPane::sltAdjustGeomerty()
    309 {
    310     /* Get parent attributes: */
    311     const int iWidth = parentWidget()->width();
    312     const int iHeight = parentWidget()->height();
    313 
    314     /* Resize popup according parent width: */
    315     resize(iWidth, minimumSizeHint().height());
    316 
    317     /* Move popup according parent: */
    318     move(0, iHeight - height() - m_iParentStatusBarHeight);
    319 
    320     /* Raise popup according parent: */
    321     raise();
    322 
    323     /* Update layout: */
    324     updateLayout();
    325 }
    326 
    327404void UIPopupPane::prepare()
    328405{
    329     /* Install event-filter to parent: */
    330     parent()->installEventFilter(this);
    331406    /* Prepare content: */
    332407    prepareContent();
     
    347422        {
    348423            /* Prepare label: */
    349             connect(m_pTextPane, SIGNAL(sigSizeChanged()),
    350                     this, SLOT(sltAdjustGeomerty()));
     424            connect(m_pTextPane, SIGNAL(sigSizeHintChanged()),
     425                    this, SIGNAL(sigSizeHintChanged()));
    351426            m_pTextPane->installEventFilter(this);
    352427            m_pTextPane->setFocusPolicy(Qt::StrongFocus);
     
    370445bool UIPopupPane::eventFilter(QObject *pWatched, QEvent *pEvent)
    371446{
    372     /* If its parent event came: */
    373     if (pWatched == parent())
    374     {
    375         /* Make sure its resize event came: */
    376         if (pEvent->type() != QEvent::Resize)
    377             return false;
    378 
    379         /* Adjust geometry: */
    380         adjustGeometry();
    381     }
    382     /* Other objects subscribed for hovering: */
    383     else
    384     {
    385         /* Depending on event-type: */
    386         switch (pEvent->type())
    387         {
    388             /* Something is hovered: */
    389             case QEvent::HoverEnter:
    390             case QEvent::Enter:
     447    /* Depending on event-type: */
     448    switch (pEvent->type())
     449    {
     450        /* Something is hovered: */
     451        case QEvent::HoverEnter:
     452        case QEvent::Enter:
     453        {
     454            if (!m_fHovered)
    391455            {
    392                 if (!m_fHovered)
    393                 {
    394                     m_fHovered = true;
    395                     emit sigHoverEnter();
    396                 }
    397                 break;
     456                m_fHovered = true;
     457                emit sigHoverEnter();
    398458            }
    399             /* Nothing is hovered: */
    400             case QEvent::Leave:
     459            break;
     460        }
     461        /* Nothing is hovered: */
     462        case QEvent::Leave:
     463        {
     464            if (pWatched == this && m_fHovered)
    401465            {
    402                 if (pWatched == this && m_fHovered)
    403                 {
    404                     m_fHovered = false;
    405                     emit sigHoverLeave();
    406                 }
    407                 break;
     466                m_fHovered = false;
     467                emit sigHoverLeave();
    408468            }
    409             case QEvent::FocusIn:
     469            break;
     470        }
     471        case QEvent::FocusIn:
     472        {
     473            if (!m_fFocused)
    410474            {
    411                 if (!m_fFocused)
    412                 {
    413                     m_fFocused = true;
    414                     emit sigFocusEnter();
    415                 }
    416                 break;
     475                m_fFocused = true;
     476                emit sigFocusEnter();
    417477            }
    418             case QEvent::FocusOut:
     478            break;
     479        }
     480        case QEvent::FocusOut:
     481        {
     482            if (m_fFocused)
    419483            {
    420                 if (m_fFocused)
    421                 {
    422                     m_fFocused = false;
    423                     emit sigFocusLeave();
    424                 }
    425                 break;
     484                m_fFocused = false;
     485                emit sigFocusLeave();
    426486            }
    427             /* Default case: */
    428             default: break;
    429         }
     487            break;
     488        }
     489        /* Default case: */
     490        default: break;
    430491    }
    431492    /* Do not filter anything: */
     
    433494}
    434495
    435 void UIPopupPane::showEvent(QShowEvent *pEvent)
    436 {
    437     /* Make sure we should polish dialog: */
    438     if (m_fPolished)
    439         return;
    440 
    441     /* Call to polish-event: */
    442     polishEvent(pEvent);
    443 
    444     /* Mark dialog as polished: */
    445     m_fPolished = true;
    446 }
    447 
    448 void UIPopupPane::polishEvent(QShowEvent*)
    449 {
    450     /* Adjust geometry: */
    451     adjustGeometry();
    452 }
    453 
    454 int UIPopupPane::minimumWidthHint() const
    455 {
    456     /* Prepare minimum width hint: */
    457     int iMinimumWidthHint = 0;
    458 
    459     /* Take into account main layout: */
    460     iMinimumWidthHint += 2 * m_iMainLayoutMargin;
    461     {
    462         /* Take into account main-frame layout: */
    463         iMinimumWidthHint += 2 * m_iMainFrameLayoutMargin;
    464         {
    465             /* Take into account widgets: */
    466             iMinimumWidthHint += m_pTextPane->width();
    467             iMinimumWidthHint += m_iMainFrameLayoutSpacing;
    468             iMinimumWidthHint += m_pButtonPane->minimumSizeHint().width();
    469         }
    470     }
    471 
    472     /* Return minimum width hint: */
    473     return iMinimumWidthHint;
    474 }
    475 
    476 int UIPopupPane::minimumHeightHint() const
    477 {
    478     /* Prepare minimum height hint: */
    479     int iMinimumHeightHint = 0;
    480 
    481     /* Take into account main layout: */
    482     iMinimumHeightHint += 2 * m_iMainLayoutMargin;
    483     {
    484         /* Take into account main-frame layout: */
    485         iMinimumHeightHint += 2 * m_iMainFrameLayoutMargin;
    486         {
    487             /* Take into account widgets: */
    488             const int iTextPaneHeight = m_pTextPane->height();
    489             const int iButtonBoxHeight = m_pButtonPane->minimumSizeHint().height();
    490             iMinimumHeightHint += qMax(iTextPaneHeight, iButtonBoxHeight);
    491         }
    492     }
    493 
    494     /* Return minimum height hint: */
    495     return iMinimumHeightHint;
    496 }
    497 
    498 QSize UIPopupPane::minimumSizeHint() const
    499 {
    500     return QSize(minimumWidthHint(), minimumHeightHint());
    501 }
    502 
    503 void UIPopupPane::adjustGeometry()
    504 {
    505     /* Get parent width: */
    506     const int iWidth = parentWidget()->width();
    507 
    508     /* Adjust text-pane according parent width: */
    509     if (m_pTextPane)
    510     {
    511         m_pTextPane->setDesiredWidth(iWidth - 2 * m_iMainLayoutMargin
    512                                             - 2 * m_iMainFrameLayoutMargin
    513                                             - m_pButtonPane->minimumSizeHint().width());
    514     }
    515 
    516     /* Adjust other widgets: */
    517     sltAdjustGeomerty();
    518 }
    519 
    520 void UIPopupPane::updateLayout()
    521 {
    522     /* This attributes: */
    523     const int iWidth = width();
    524     const int iHeight = height();
    525     /* Main layout: */
    526     {
    527         /* Main-frame: */
    528         m_pMainFrame->move(m_iMainLayoutMargin,
    529                            m_iMainLayoutMargin);
    530         m_pMainFrame->resize(iWidth - 2 * m_iMainLayoutMargin,
    531                              iHeight - 2 * m_iMainLayoutMargin);
    532         const int iMainFrameHeight = m_pMainFrame->height();
    533         /* Main-frame layout: */
    534         {
    535             /* Variables: */
    536             const int iTextPaneWidth = m_pTextPane->width();
    537             const int iTextPaneHeight = m_pTextPane->height();
    538             const QSize buttonBoxMinimumSizeHint = m_pButtonPane->minimumSizeHint();
    539             const int iButtonBoxWidth = buttonBoxMinimumSizeHint.width();
    540             const int iButtonBoxHeight = buttonBoxMinimumSizeHint.height();
    541             const int iMaximumHeight = qMax(iTextPaneHeight, iButtonBoxHeight);
    542             const int iMinimumHeight = qMin(iTextPaneHeight, iButtonBoxHeight);
    543             const int iHeightShift = (iMaximumHeight - iMinimumHeight) / 2;
    544             const bool fTextPaneShifted = iTextPaneHeight < iButtonBoxHeight;
    545             /* Text-pane: */
    546             m_pTextPane->move(m_iMainFrameLayoutMargin,
    547                               fTextPaneShifted ? m_iMainFrameLayoutMargin + iHeightShift : m_iMainFrameLayoutMargin);
    548             m_pTextPane->resize(iTextPaneWidth, iTextPaneHeight);
    549             /* Button-box: */
    550             m_pButtonPane->move(m_iMainFrameLayoutMargin + iTextPaneWidth + m_iMainFrameLayoutSpacing,
    551                                 m_iMainFrameLayoutMargin);
    552             m_pButtonPane->resize(iButtonBoxWidth,
    553                                   iMainFrameHeight - 2 * m_iMainFrameLayoutMargin);
    554         }
    555     }
    556 }
    557 
    558496void UIPopupPane::done(int iButtonCode)
    559497{
     
    563501    /* Notify listeners: */
    564502    emit sigDone(iButtonCode);
    565 }
    566 
    567 /* static */
    568 int UIPopupPane::parentStatusBarHeight(QWidget *pParent)
    569 {
    570     /* Check if passed parent is QMainWindow and contains status-bar: */
    571     if (QMainWindow *pParentWindow = qobject_cast<QMainWindow*>(pParent))
    572         if (pParentWindow->statusBar())
    573             return pParentWindow->statusBar()->height();
    574     /* Zero by default: */
    575     return 0;
    576503}
    577504
     
    654581    /* Update the pane for new text: */
    655582    m_pLabel->setText(strText);
    656     updateGeometry();
     583    updateSizeHint();
    657584}
    658585
     
    664591    /* Update the pane for new desired-width: */
    665592    m_iDesiredWidth = iDesiredWidth;
    666     updateGeometry();
     593    updateSizeHint();
    667594}
    668595
     
    677604}
    678605
    679 QSize UIPopupPaneTextPane::sizeHint() const
    680 {
    681     /* Check if desired-width set: */
    682     if (m_iDesiredWidth >= 0)
    683         /* Return dependent size-hint: */
    684         return m_sizeHint;
    685     /* Return golden-rule size-hint by default: */
    686     return m_pLabel->sizeHint();
     606void UIPopupPaneTextPane::setMinimumSizeHint(const QSize &minimumSizeHint)
     607{
     608    /* Make sure the size-hint is changed: */
     609    if (m_minimumSizeHint == minimumSizeHint)
     610        return;
     611    /* Assign new size-hint: */
     612    m_minimumSizeHint = minimumSizeHint;
     613    /* Notify parent popup-pane: */
     614    emit sigSizeHintChanged();
    687615}
    688616
     
    741669}
    742670
    743 void UIPopupPaneTextPane::updateGeometry()
     671void UIPopupPaneTextPane::updateSizeHint()
    744672{
    745673    /* Recalculate size-hints: */
    746674    QFontMetrics fm(m_pLabel->font(), m_pLabel);
    747     m_sizeHint = QSize(m_iDesiredWidth, m_pLabel->heightForWidth(m_iDesiredWidth));
    748     m_minimumSizeHint = QSize(m_iDesiredWidth, fm.height());
    749     /* Update geometry: */
    750     QWidget::updateGeometry();
    751     /* Resize to required size: */
    752     resize(m_fFocused ? sizeHint() : minimumSizeHint());
     675    m_collapsedSizeHint = QSize(m_iDesiredWidth, fm.height());
     676    m_expandedSizeHint = QSize(m_iDesiredWidth, m_pLabel->heightForWidth(m_iDesiredWidth));
     677    m_minimumSizeHint = m_fFocused ? m_expandedSizeHint : m_collapsedSizeHint;
    753678    /* Reinstall animation: */
    754679    delete m_pAnimation;
    755     m_pAnimation = UIAnimationFramework::installPropertyAnimation(this, "size", "minimumSizeHint", "sizeHint",
     680    m_pAnimation = UIAnimationFramework::installPropertyAnimation(this, "minimumSizeHint", "collapsedSizeHint", "expandedSizeHint",
    756681                                                                  SIGNAL(sigFocusEnter()), SIGNAL(sigFocusLeave()),
    757682                                                                  m_fFocused);
    758 }
    759 
    760 void UIPopupPaneTextPane::resizeEvent(QResizeEvent*)
    761 {
    762     emit sigSizeChanged();
    763683}
    764684
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.h

    r45605 r45658  
    6363    void sigFocusEnter();
    6464    void sigFocusLeave();
     65    void sigSizeHintChanged();
    6566
    6667    /* Notifier: Complete stuff: */
     
    7071
    7172    /* Constructor: */
    72     UIPopupPane(QWidget *pParent, const QString &strId,
     73    UIPopupPane(QWidget *pParent,
    7374                const QString &strMessage, const QString &strDetails,
    7475                const QMap<int, QString> &buttonDescriptions);
    75 
    76     /* API: Id stuff: */
    77     const QString& id() const { return m_strId; }
    7876
    7977    /* API: Text stuff: */
     
    8179    void setDetails(const QString &strDetails);
    8280
     81    /* API: Layout stuff: */
     82    void setDesiredWidth(int iWidth);
     83    int minimumWidthHint() const;
     84    int minimumHeightHint() const;
     85    QSize minimumSizeHint() const;
     86    void layoutContent();
     87
    8388private slots:
    8489
    8590    /* Handler: Button stuff: */
    8691    void sltButtonClicked(int iButtonID);
    87 
    88     /* Handler: Layout stuff: */
    89     void sltAdjustGeomerty();
    9092
    9193private:
     
    98100    bool eventFilter(QObject *pWatched, QEvent *pEvent);
    99101
    100     /* Handlers: Event stuff: */
    101     virtual void showEvent(QShowEvent *pEvent);
    102     virtual void polishEvent(QShowEvent *pEvent);
    103 
    104     /* Helper: Layout stuff: */
    105     int minimumWidthHint() const;
    106     int minimumHeightHint() const;
    107     QSize minimumSizeHint() const;
    108     void adjustGeometry();
    109     void updateLayout();
    110 
    111102    /* Helper: Complete stuff: */
    112103    void done(int iButtonCode);
    113104
    114     /* Static helpers: Prepare stuff: */
    115     static int parentStatusBarHeight(QWidget *pParent);
    116 
    117105    /* Variables: */
    118     bool m_fPolished;
    119106    const QString m_strId;
    120107
     
    123110    const int m_iMainFrameLayoutMargin;
    124111    const int m_iMainFrameLayoutSpacing;
    125     const int m_iParentStatusBarHeight;
    126112
    127113    /* Variables: Text stuff: */
Note: See TracChangeset for help on using the changeset viewer.

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