- Timestamp:
- May 21, 2013 2:59:54 PM (12 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 3 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r46058 r46195 509 509 src/globals/COMDefs.cpp \ 510 510 src/globals/UIActionPool.cpp \ 511 src/globals/UIAnimationFramework.cpp \ 511 512 src/globals/UIExtraDataEventHandler.cpp \ 512 513 src/globals/UIIconPool.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIAnimationFramework.cpp
r46193 r46195 3 3 * 4 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * UI PopupPaneclass implementation5 * UIAnimationFramework class implementation 6 6 */ 7 7 … … 19 19 20 20 /* Qt includes: */ 21 #include <QHBoxLayout> 22 #include <QVBoxLayout> 23 #include <QLabel> 24 #include <QCheckBox> 25 #include <QKeyEvent> 26 #include <QPainter> 21 #include <QWidget> 27 22 #include <QStateMachine> 28 23 #include <QPropertyAnimation> … … 30 25 31 26 /* GUI includes: */ 32 #include "QIWithRetranslateUI.h" 33 #include "UIPopupPane.h" 34 #include "UIIconPool.h" 35 #include "QIToolButton.h" 36 37 /* Other VBox includes: */ 38 #include <VBox/sup.h> 39 27 #include "UIAnimationFramework.h" 40 28 41 29 QStateMachine* UIAnimationFramework::installPropertyAnimation(QWidget *pTarget, const char *pszPropertyName, … … 78 66 } 79 67 80 81 /* Popup-pane text-pane prototype class: */82 class UIPopupPaneTextPane : public QIWithRetranslateUI<QWidget>83 {84 Q_OBJECT;85 Q_PROPERTY(QSize collapsedSizeHint READ collapsedSizeHint);86 Q_PROPERTY(QSize expandedSizeHint READ expandedSizeHint);87 Q_PROPERTY(QSize minimumSizeHint READ minimumSizeHint WRITE setMinimumSizeHint);88 89 signals:90 91 /* Notifiers: Parent propagation stuff: */92 void sigFocusEnter();93 void sigFocusLeave();94 95 /* Notifier: Layout stuff: */96 void sigSizeHintChanged();97 98 public:99 100 /* Constructor: */101 UIPopupPaneTextPane(QWidget *pParent = 0);102 103 /* API: Text stuff: */104 void setText(const QString &strText);105 106 /* API: Desired-width stuff: */107 void setDesiredWidth(int iDesiredWidth);108 109 /* API: Auto-confirmation stuff: */110 void setProposeAutoConfirmation(bool fPropose);111 bool autoConfirmationProposed() const;112 bool isAutoConfirmed() const;113 114 /* API: Layout stuff: */115 QSize minimumSizeHint() const;116 void setMinimumSizeHint(const QSize &minimumSizeHint);117 void layoutContent();118 119 private slots:120 121 /* Handlers: Focus stuff: */122 void sltFocusEnter();123 void sltFocusLeave();124 125 private:126 127 /* Helpers: Prepare stuff: */128 void prepare();129 void prepareContent();130 131 /* Helper: Translate stuff: */132 void retranslateUi();133 134 /* Helper: Layout stuff: */135 void updateSizeHint();136 137 /* Property: Focus stuff: */138 QSize collapsedSizeHint() const { return m_collapsedSizeHint; }139 QSize expandedSizeHint() const { return m_expandedSizeHint; }140 141 /* Variables: Layout stuff: */142 const int m_iLayoutMargin;143 const int m_iLayoutSpacing;144 QSize m_labelSizeHint;145 QSize m_checkBoxSizeHint;146 QSize m_collapsedSizeHint;147 QSize m_expandedSizeHint;148 QSize m_minimumSizeHint;149 150 /* Variables: Widget stuff: */151 QLabel *m_pLabel;152 int m_iDesiredLabelWidth;153 QCheckBox *m_pAutoConfirmCheckBox;154 bool m_fProposeAutoConfirmation;155 156 /* Variables: Focus stuff: */157 bool m_fFocused;158 QObject *m_pAnimation;159 };160 161 162 /* Popup-pane button-pane prototype class: */163 class UIPopupPaneButtonPane : public QWidget164 {165 Q_OBJECT;166 167 signals:168 169 /* Notifier: Button stuff: */170 void sigButtonClicked(int iButtonID);171 172 public:173 174 /* Constructor: */175 UIPopupPaneButtonPane(QWidget *pParent = 0);176 177 /* API: Button stuff: */178 void setButtons(const QMap<int, QString> &buttonDescriptions);179 180 private slots:181 182 /* Handler: Button stuff: */183 void sltButtonClicked();184 185 private:186 187 /* Helpers: Prepare/cleanup stuff: */188 void prepare();189 void prepareLayouts();190 void prepareButtons();191 void cleanupButtons();192 193 /* Handler: Event stuff: */194 void keyPressEvent(QKeyEvent *pEvent);195 196 /* Static helpers: Button stuff: */197 static QIToolButton* addButton(int iButtonID, const QString &strToolTip);198 static QString defaultToolTip(int iButtonID);199 static QIcon defaultIcon(int iButtonID);200 201 /* Variables: Widget stuff: */202 QHBoxLayout *m_pButtonLayout;203 QMap<int, QString> m_buttonDescriptions;204 QMap<int, QIToolButton*> m_buttons;205 int m_iDefaultButton;206 int m_iEscapeButton;207 };208 209 210 UIPopupPane::UIPopupPane(QWidget *pParent,211 const QString &strMessage, const QString &strDetails,212 const QMap<int, QString> &buttonDescriptions,213 bool fProposeAutoConfirmation)214 : QWidget(pParent)215 , m_iLayoutMargin(10), m_iLayoutSpacing(5)216 , m_strMessage(strMessage), m_strDetails(strDetails)217 , m_fProposeAutoConfirmation(fProposeAutoConfirmation)218 , m_buttonDescriptions(buttonDescriptions)219 , m_fHovered(false)220 , m_iDefaultOpacity(128)221 , m_iHoveredOpacity(230)222 , m_iOpacity(m_iDefaultOpacity)223 , m_fFocused(false)224 , m_pTextPane(0), m_pButtonPane(0)225 {226 /* Prepare: */227 prepare();228 }229 230 void UIPopupPane::setMessage(const QString &strMessage)231 {232 /* Make sure somthing changed: */233 if (m_strMessage == strMessage)234 return;235 236 /* Fetch new message: */237 m_strMessage = strMessage;238 m_pTextPane->setText(m_strMessage);239 }240 241 void UIPopupPane::setDetails(const QString &strDetails)242 {243 /* Make sure somthing changed: */244 if (m_strDetails == strDetails)245 return;246 247 /* Fetch new details: */248 m_strDetails = strDetails;249 }250 251 void UIPopupPane::setProposeAutoConfirmation(bool fPropose)252 {253 /* Make sure something changed: */254 if (m_fProposeAutoConfirmation == fPropose)255 return;256 257 /* Fetch new auto-confirmation proposal: */258 m_fProposeAutoConfirmation = fPropose;259 m_pTextPane->setProposeAutoConfirmation(m_fProposeAutoConfirmation);260 }261 262 void UIPopupPane::setDesiredWidth(int iWidth)263 {264 /* Make sure text-pane exists: */265 if (!m_pTextPane)266 return;267 268 /* Propagate desired width to the text-pane we have: */269 m_pTextPane->setDesiredWidth(iWidth - 2 * m_iLayoutMargin270 - m_pButtonPane->minimumSizeHint().width());271 }272 273 int UIPopupPane::minimumWidthHint() const274 {275 /* Prepare width hint: */276 int iWidthHint = 0;277 278 /* Take into account layout: */279 iWidthHint += 2 * m_iLayoutMargin;280 {281 /* Take into account widgets: */282 iWidthHint += m_pTextPane->minimumSizeHint().width();283 iWidthHint += m_iLayoutSpacing;284 iWidthHint += m_pButtonPane->minimumSizeHint().width();285 }286 287 /* Return width hint: */288 return iWidthHint;289 }290 291 int UIPopupPane::minimumHeightHint() const292 {293 /* Prepare height hint: */294 int iHeightHint = 0;295 296 /* Take into account layout: */297 iHeightHint += 2 * m_iLayoutMargin;298 {299 /* Take into account widgets: */300 const int iTextPaneHeight = m_pTextPane->minimumSizeHint().height();301 const int iButtonBoxHeight = m_pButtonPane->minimumSizeHint().height();302 iHeightHint += qMax(iTextPaneHeight, iButtonBoxHeight);303 }304 305 /* Return height hint: */306 return iHeightHint;307 }308 309 QSize UIPopupPane::minimumSizeHint() const310 {311 /* Wrap reimplemented getters: */312 return QSize(minimumWidthHint(), minimumHeightHint());313 }314 315 void UIPopupPane::layoutContent()316 {317 /* Variables: */318 const int iWidth = width();319 const int iHeight = height();320 const QSize buttonPaneMinimumSizeHint = m_pButtonPane->minimumSizeHint();321 const int iButtonPaneMinimumWidth = buttonPaneMinimumSizeHint.width();322 const int iButtonPaneMinimumHeight = buttonPaneMinimumSizeHint.height();323 const int iTextPaneWidth = iWidth - 2 * m_iLayoutMargin - m_iLayoutSpacing - iButtonPaneMinimumWidth;324 const int iTextPaneHeight = m_pTextPane->minimumSizeHint().height();325 const int iMaximumHeight = qMax(iTextPaneHeight, iButtonPaneMinimumHeight);326 const int iMinimumHeight = qMin(iTextPaneHeight, iButtonPaneMinimumHeight);327 const int iHeightShift = (iMaximumHeight - iMinimumHeight) / 2;328 const bool fTextPaneShifted = iTextPaneHeight < iButtonPaneMinimumHeight;329 330 /* Text-pane: */331 m_pTextPane->move(m_iLayoutMargin,332 fTextPaneShifted ? m_iLayoutMargin + iHeightShift : m_iLayoutMargin);333 m_pTextPane->resize(iTextPaneWidth,334 iTextPaneHeight);335 m_pTextPane->layoutContent();336 /* Button-box: */337 m_pButtonPane->move(m_iLayoutMargin + iTextPaneWidth + m_iLayoutSpacing,338 m_iLayoutMargin);339 m_pButtonPane->resize(iButtonPaneMinimumWidth,340 iHeight - 2 * m_iLayoutMargin);341 }342 343 void UIPopupPane::sltButtonClicked(int iButtonID)344 {345 done(iButtonID & AlertButtonMask);346 }347 348 void UIPopupPane::prepare()349 {350 /* Install 'hover' animation for 'opacity' property: */351 UIAnimationFramework::installPropertyAnimation(this, "opacity", "defaultOpacity", "hoveredOpacity",352 SIGNAL(sigHoverEnter()), SIGNAL(sigHoverLeave()));353 /* Prepare content: */354 prepareContent();355 }356 357 void UIPopupPane::prepareContent()358 {359 /* Prepare this: */360 installEventFilter(this);361 /* Create message-label: */362 m_pTextPane = new UIPopupPaneTextPane(this);363 {364 /* Prepare label: */365 connect(m_pTextPane, SIGNAL(sigSizeHintChanged()),366 this, SIGNAL(sigSizeHintChanged()));367 m_pTextPane->installEventFilter(this);368 m_pTextPane->setText(m_strMessage);369 m_pTextPane->setProposeAutoConfirmation(m_fProposeAutoConfirmation);370 }371 /* Create button-box: */372 m_pButtonPane = new UIPopupPaneButtonPane(this);373 {374 /* Prepare button-box: */375 connect(m_pButtonPane, SIGNAL(sigButtonClicked(int)),376 this, SLOT(sltButtonClicked(int)));377 m_pButtonPane->installEventFilter(this);378 m_pButtonPane->setButtons(m_buttonDescriptions);379 }380 381 /* Prepare focus rules: */382 setFocusPolicy(Qt::StrongFocus);383 m_pTextPane->setFocusPolicy(Qt::StrongFocus);384 m_pButtonPane->setFocusPolicy(Qt::StrongFocus);385 setFocusProxy(m_pButtonPane);386 m_pTextPane->setFocusProxy(m_pButtonPane);387 }388 389 bool UIPopupPane::eventFilter(QObject *pWatched, QEvent *pEvent)390 {391 /* Depending on event-type: */392 switch (pEvent->type())393 {394 /* Something is hovered: */395 case QEvent::HoverEnter:396 case QEvent::Enter:397 {398 if (!m_fHovered)399 {400 m_fHovered = true;401 emit sigHoverEnter();402 }403 break;404 }405 /* Nothing is hovered: */406 case QEvent::Leave:407 {408 if (pWatched == this && m_fHovered)409 {410 m_fHovered = false;411 emit sigHoverLeave();412 }413 break;414 }415 case QEvent::FocusIn:416 {417 if (!m_fFocused)418 {419 m_fFocused = true;420 emit sigFocusEnter();421 }422 break;423 }424 case QEvent::FocusOut:425 {426 if (m_fFocused)427 {428 m_fFocused = false;429 emit sigFocusLeave();430 }431 break;432 }433 /* Default case: */434 default: break;435 }436 /* Do not filter anything: */437 return false;438 }439 440 void UIPopupPane::paintEvent(QPaintEvent*)441 {442 /* Compose painting rectangle: */443 const QRect rect(0, 0, width(), height());444 445 /* Create painter: */446 QPainter painter(this);447 painter.setRenderHint(QPainter::Antialiasing);448 449 /* Configure painter clipping: */450 QPainterPath path;451 int iDiameter = 6;452 QSizeF arcSize(2 * iDiameter, 2 * iDiameter);453 path.moveTo(iDiameter, 0);454 path.arcTo(QRectF(path.currentPosition(), arcSize).translated(-iDiameter, 0), 90, 90);455 path.lineTo(path.currentPosition().x(), rect.height() - iDiameter);456 path.arcTo(QRectF(path.currentPosition(), arcSize).translated(0, -iDiameter), 180, 90);457 path.lineTo(rect.width() - iDiameter, path.currentPosition().y());458 path.arcTo(QRectF(path.currentPosition(), arcSize).translated(-iDiameter, -2 * iDiameter), 270, 90);459 path.lineTo(path.currentPosition().x(), iDiameter);460 path.arcTo(QRectF(path.currentPosition(), arcSize).translated(-2 * iDiameter, -iDiameter), 0, 90);461 path.closeSubpath();462 painter.setClipPath(path);463 464 /* Fill with background: */465 QColor currentColor(palette().color(QPalette::Window));466 QColor newColor1(currentColor.red(), currentColor.green(), currentColor.blue(), opacity());467 QColor newColor2 = newColor1.darker(115);468 QLinearGradient headerGradient(rect.topLeft(), rect.topRight());469 headerGradient.setColorAt(0, newColor1);470 headerGradient.setColorAt(1, newColor2);471 painter.fillRect(rect, headerGradient);472 }473 474 void UIPopupPane::done(int iResultCode)475 {476 /* Close the window: */477 close();478 479 /* Was the popup auto-confirmed? */480 if (m_pTextPane->isAutoConfirmed())481 iResultCode |= AlertOption_AutoConfirmed;482 483 /* Notify listeners: */484 emit sigDone(iResultCode);485 }486 487 488 UIPopupPaneTextPane::UIPopupPaneTextPane(QWidget *pParent /*= 0*/)489 : QIWithRetranslateUI<QWidget>(pParent)490 , m_iLayoutMargin(0)491 , m_iLayoutSpacing(10)492 , m_pLabel(0)493 , m_iDesiredLabelWidth(-1)494 , m_pAutoConfirmCheckBox(0)495 , m_fProposeAutoConfirmation(false)496 , m_fFocused(false)497 , m_pAnimation(0)498 {499 /* Prepare: */500 prepare();501 }502 503 void UIPopupPaneTextPane::setText(const QString &strText)504 {505 /* Make sure the text is changed: */506 if (m_pLabel->text() == strText)507 return;508 /* Update the pane for the new text: */509 m_pLabel->setText(strText);510 updateSizeHint();511 }512 513 void UIPopupPaneTextPane::setDesiredWidth(int iDesiredWidth)514 {515 /* Make sure the desired-width is changed: */516 if (m_iDesiredLabelWidth == iDesiredWidth)517 return;518 /* Update the pane for the new desired-width: */519 m_iDesiredLabelWidth = iDesiredWidth;520 updateSizeHint();521 }522 523 void UIPopupPaneTextPane::setProposeAutoConfirmation(bool fPropose)524 {525 /* Make sure the auto-confirmation-proposal is changed: */526 if (m_fProposeAutoConfirmation == fPropose)527 return;528 /* Update the pane for the new auto-confirmation-proposal: */529 m_fProposeAutoConfirmation = fPropose;530 updateSizeHint();531 }532 533 bool UIPopupPaneTextPane::autoConfirmationProposed() const534 {535 return m_fProposeAutoConfirmation;536 }537 538 bool UIPopupPaneTextPane::isAutoConfirmed() const539 {540 return autoConfirmationProposed() &&541 m_pAutoConfirmCheckBox &&542 m_pAutoConfirmCheckBox->isChecked();543 }544 545 QSize UIPopupPaneTextPane::minimumSizeHint() const546 {547 /* Check if desired-width set: */548 if (m_iDesiredLabelWidth >= 0)549 /* Dependent size-hint: */550 return m_minimumSizeHint;551 /* Golden-rule size-hint by default: */552 return QWidget::minimumSizeHint();553 }554 555 void UIPopupPaneTextPane::setMinimumSizeHint(const QSize &minimumSizeHint)556 {557 /* Make sure the size-hint is changed: */558 if (m_minimumSizeHint == minimumSizeHint)559 return;560 /* Assign new size-hint: */561 m_minimumSizeHint = minimumSizeHint;562 /* Notify parent popup-pane: */563 emit sigSizeHintChanged();564 }565 566 void UIPopupPaneTextPane::layoutContent()567 {568 /* Variables: */569 const int iWidth = width();570 const int iHeight = height();571 const int iLabelWidth = m_labelSizeHint.width();572 const int iLabelHeight = m_labelSizeHint.height();573 /* Label: */574 m_pLabel->move(m_iLayoutMargin, m_iLayoutMargin);575 m_pLabel->resize(qMin(iWidth, iLabelWidth), qMin(iHeight, iLabelHeight));576 577 /* Check-box: */578 if (m_fProposeAutoConfirmation)579 {580 /* Variables: */581 const int iCheckBoxWidth = m_checkBoxSizeHint.width();582 const int iCheckBoxHeight = m_checkBoxSizeHint.height();583 const int iCheckBoxY = m_iLayoutMargin + iLabelHeight + m_iLayoutSpacing;584 /* Layout check-box: */585 if (iHeight - m_iLayoutMargin - iCheckBoxHeight - iCheckBoxY >= 0)586 {587 m_pAutoConfirmCheckBox->move(m_iLayoutMargin, iCheckBoxY);588 m_pAutoConfirmCheckBox->resize(iCheckBoxWidth, iCheckBoxHeight);589 if (m_pAutoConfirmCheckBox->isHidden())590 m_pAutoConfirmCheckBox->show();591 }592 else if (!m_pAutoConfirmCheckBox->isHidden())593 m_pAutoConfirmCheckBox->hide();594 }595 else if (!m_pAutoConfirmCheckBox->isHidden())596 m_pAutoConfirmCheckBox->hide();597 }598 599 void UIPopupPaneTextPane::sltFocusEnter()600 {601 /* Ignore if already focused: */602 if (m_fFocused)603 return;604 605 /* Update focus state: */606 m_fFocused = true;607 608 /* Notify listeners: */609 emit sigFocusEnter();610 }611 612 void UIPopupPaneTextPane::sltFocusLeave()613 {614 /* Ignore if already unfocused: */615 if (!m_fFocused)616 return;617 618 /* Update focus state: */619 m_fFocused = false;620 621 /* Notify listeners: */622 emit sigFocusLeave();623 }624 625 void UIPopupPaneTextPane::prepare()626 {627 /* Propagate parent signals: */628 connect(parent(), SIGNAL(sigFocusEnter()), this, SLOT(sltFocusEnter()));629 connect(parent(), SIGNAL(sigFocusLeave()), this, SLOT(sltFocusLeave()));630 /* Prepare content: */631 prepareContent();632 }633 634 void UIPopupPaneTextPane::prepareContent()635 {636 /* Create label: */637 m_pLabel = new QLabel(this);638 {639 /* Prepare label: */640 QFont currentFont = m_pLabel->font();641 #ifdef Q_WS_MAC642 currentFont.setPointSize(currentFont.pointSize() - 2);643 #else /* Q_WS_MAC */644 currentFont.setPointSize(currentFont.pointSize() - 1);645 #endif /* !Q_WS_MAC */646 m_pLabel->setFont(currentFont);647 m_pLabel->setWordWrap(true);648 m_pLabel->setFocusPolicy(Qt::NoFocus);649 }650 /* Create check-box: */651 m_pAutoConfirmCheckBox = new QCheckBox(this);652 {653 /* Prepare check-box: */654 QFont currentFont = m_pAutoConfirmCheckBox->font();655 #ifdef Q_WS_MAC656 currentFont.setPointSize(currentFont.pointSize() - 2);657 #else /* Q_WS_MAC */658 currentFont.setPointSize(currentFont.pointSize() - 1);659 #endif /* !Q_WS_MAC */660 m_pAutoConfirmCheckBox->setFont(currentFont);661 m_pAutoConfirmCheckBox->setFocusPolicy(Qt::NoFocus);662 }663 /* Translate UI finally: */664 retranslateUi();665 }666 667 void UIPopupPaneTextPane::retranslateUi()668 {669 /* Translate auto-confirm check-box: */670 m_pAutoConfirmCheckBox->setText(QApplication::translate("UIMessageCenter", "Do not show this message again"));671 }672 673 void UIPopupPaneTextPane::updateSizeHint()674 {675 /* Recalculate collapsed size-hint: */676 {677 /* Collapsed size-hint contains only one-text-line label: */678 QFontMetrics fm(m_pLabel->font(), m_pLabel);679 m_collapsedSizeHint = QSize(m_iDesiredLabelWidth, fm.height());680 }681 682 /* Recalculate expanded size-hint: */683 {684 /* Recalculate label size-hint: */685 m_labelSizeHint = QSize(m_iDesiredLabelWidth, m_pLabel->heightForWidth(m_iDesiredLabelWidth));686 /* Recalculate check-box size-hint: */687 m_checkBoxSizeHint = m_fProposeAutoConfirmation ? m_pAutoConfirmCheckBox->sizeHint() : QSize();688 /* Expanded size-hint contains full-size label: */689 m_expandedSizeHint = m_labelSizeHint;690 /* Expanded size-hint can contain check-box: */691 if (m_checkBoxSizeHint.isValid())692 {693 m_expandedSizeHint.setWidth(qMax(m_expandedSizeHint.width(), m_checkBoxSizeHint.width()));694 m_expandedSizeHint.setHeight(m_expandedSizeHint.height() + m_iLayoutSpacing + m_checkBoxSizeHint.height());695 }696 }697 698 /* Update current size-hint: */699 m_minimumSizeHint = m_fFocused ? m_expandedSizeHint : m_collapsedSizeHint;700 701 /* And reinstall size-hint animation: */702 delete m_pAnimation;703 m_pAnimation = UIAnimationFramework::installPropertyAnimation(this, "minimumSizeHint", "collapsedSizeHint", "expandedSizeHint",704 SIGNAL(sigFocusEnter()), SIGNAL(sigFocusLeave()),705 m_fFocused);706 }707 708 709 UIPopupPaneButtonPane::UIPopupPaneButtonPane(QWidget *pParent /*= 0*/)710 : QWidget(pParent)711 , m_iDefaultButton(0)712 , m_iEscapeButton(0)713 {714 /* Prepare: */715 prepare();716 }717 718 void UIPopupPaneButtonPane::setButtons(const QMap<int, QString> &buttonDescriptions)719 {720 /* Make sure something changed: */721 if (m_buttonDescriptions == buttonDescriptions)722 return;723 724 /* Assign new button-descriptions: */725 m_buttonDescriptions = buttonDescriptions;726 /* Recreate buttons: */727 cleanupButtons();728 prepareButtons();729 }730 731 void UIPopupPaneButtonPane::sltButtonClicked()732 {733 /* Make sure the slot is called by the button: */734 QIToolButton *pButton = qobject_cast<QIToolButton*>(sender());735 if (!pButton)736 return;737 738 /* Make sure we still have that button: */739 int iButtonID = m_buttons.key(pButton, 0);740 if (!iButtonID)741 return;742 743 /* Notify listeners button was clicked: */744 emit sigButtonClicked(iButtonID);745 }746 747 void UIPopupPaneButtonPane::prepare()748 {749 /* Prepare layouts: */750 prepareLayouts();751 }752 753 void UIPopupPaneButtonPane::prepareLayouts()754 {755 /* Create layouts: */756 m_pButtonLayout = new QHBoxLayout;757 m_pButtonLayout->setContentsMargins(0, 0, 0, 0);758 m_pButtonLayout->setSpacing(0);759 QVBoxLayout *pMainLayout = new QVBoxLayout(this);760 pMainLayout->setContentsMargins(0, 0, 0, 0);761 pMainLayout->setSpacing(0);762 pMainLayout->addLayout(m_pButtonLayout);763 pMainLayout->addStretch();764 }765 766 void UIPopupPaneButtonPane::prepareButtons()767 {768 /* Add all the buttons: */769 const QList<int> &buttonsIDs = m_buttonDescriptions.keys();770 foreach (int iButtonID, buttonsIDs)771 if (QIToolButton *pButton = addButton(iButtonID, m_buttonDescriptions[iButtonID]))772 {773 m_pButtonLayout->addWidget(pButton);774 m_buttons[iButtonID] = pButton;775 connect(pButton, SIGNAL(clicked(bool)), this, SLOT(sltButtonClicked()));776 if (pButton->property("default").toBool())777 m_iDefaultButton = iButtonID;778 if (pButton->property("escape").toBool())779 m_iEscapeButton = iButtonID;780 }781 }782 783 void UIPopupPaneButtonPane::cleanupButtons()784 {785 /* Remove all the buttons: */786 const QList<int> &buttonsIDs = m_buttons.keys();787 foreach (int iButtonID, buttonsIDs)788 {789 delete m_buttons[iButtonID];790 m_buttons.remove(iButtonID);791 }792 }793 794 void UIPopupPaneButtonPane::keyPressEvent(QKeyEvent *pEvent)795 {796 /* Depending on pressed key: */797 switch (pEvent->key())798 {799 case Qt::Key_Enter:800 case Qt::Key_Return:801 {802 if (m_iDefaultButton)803 {804 pEvent->accept();805 emit sigButtonClicked(m_iDefaultButton);806 return;807 }808 break;809 }810 case Qt::Key_Escape:811 {812 if (m_iEscapeButton)813 {814 pEvent->accept();815 emit sigButtonClicked(m_iEscapeButton);816 return;817 }818 break;819 }820 default:821 break;822 }823 /* Call to base-class: */824 QWidget::keyPressEvent(pEvent);825 }826 827 /* static */828 QIToolButton* UIPopupPaneButtonPane::addButton(int iButtonID, const QString &strToolTip)829 {830 /* Create button: */831 QIToolButton *pButton = new QIToolButton;832 pButton->removeBorder();833 pButton->setToolTip(strToolTip.isEmpty() ? defaultToolTip(iButtonID) : strToolTip);834 pButton->setIcon(defaultIcon(iButtonID));835 836 /* Sign the 'default' button: */837 if (iButtonID & AlertButtonOption_Default)838 pButton->setProperty("default", true);839 /* Sign the 'escape' button: */840 if (iButtonID & AlertButtonOption_Escape)841 pButton->setProperty("escape", true);842 843 /* Return button: */844 return pButton;845 }846 847 /* static */848 QString UIPopupPaneButtonPane::defaultToolTip(int iButtonID)849 {850 QString strToolTip;851 switch (iButtonID & AlertButtonMask)852 {853 case AlertButton_Ok: strToolTip = QIMessageBox::tr("OK"); break;854 case AlertButton_Cancel: strToolTip = QIMessageBox::tr("Cancel"); break;855 case AlertButton_Choice1: strToolTip = QIMessageBox::tr("Yes"); break;856 case AlertButton_Choice2: strToolTip = QIMessageBox::tr("No"); break;857 default: strToolTip = QString(); break;858 }859 return strToolTip;860 }861 862 /* static */863 QIcon UIPopupPaneButtonPane::defaultIcon(int iButtonID)864 {865 QIcon icon;866 switch (iButtonID & AlertButtonMask)867 {868 case AlertButton_Ok: icon = UIIconPool::iconSet(":/ok_16px.png"); break;869 case AlertButton_Cancel: icon = UIIconPool::iconSet(":/cancel_16px.png"); break;870 case AlertButton_Choice1: break;871 case AlertButton_Choice2: break;872 default: break;873 }874 return icon;875 }876 877 #include "UIPopupPane.moc"878 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIAnimationFramework.h
r46193 r46195 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * UI PopupPaneclass declaration4 * UIAnimationFramework class declaration 5 5 */ 6 6 … … 17 17 */ 18 18 19 #ifndef __UIPopupPane_h__ 20 #define __UIPopupPane_h__ 21 22 /* Qt includes: */ 23 #include <QWidget> 24 #include <QMap> 25 26 /* GUI includes: */ 27 #include "QIMessageBox.h" 19 #ifndef __UIAnimationFramework_h__ 20 #define __UIAnimationFramework_h__ 28 21 29 22 /* Forward declaration: */ 30 23 class QStateMachine; 31 class UIPopupPaneTextPane;32 class UIPopupPaneButtonPane;33 24 34 25 /* UIAnimationFramework namespace: */ … … 42 33 } 43 34 44 /* Popup-pane prototype class: */ 45 class UIPopupPane : public QWidget 46 { 47 Q_OBJECT; 48 Q_PROPERTY(int defaultOpacity READ defaultOpacity); 49 Q_PROPERTY(int hoveredOpacity READ hoveredOpacity); 50 Q_PROPERTY(int opacity READ opacity WRITE setOpacity); 51 52 signals: 53 54 /* Notifiers: Hover stuff: */ 55 void sigHoverEnter(); 56 void sigHoverLeave(); 57 58 /* Notifiers: Focus stuff: */ 59 void sigFocusEnter(); 60 void sigFocusLeave(); 61 62 /* Notifier: Layout stuff: */ 63 void sigSizeHintChanged(); 64 65 /* Notifier: Complete stuff: */ 66 void sigDone(int iResultCode) const; 67 68 public: 69 70 /* Constructor: */ 71 UIPopupPane(QWidget *pParent, 72 const QString &strMessage, const QString &strDetails, 73 const QMap<int, QString> &buttonDescriptions, 74 bool fProposeAutoConfirmation); 75 76 /* API: Text stuff: */ 77 void setMessage(const QString &strMessage); 78 void setDetails(const QString &strDetails); 79 80 /* API: Auto-confirmation stuff: */ 81 void setProposeAutoConfirmation(bool fPropose); 82 83 /* API: Layout stuff: */ 84 void setDesiredWidth(int iWidth); 85 int minimumWidthHint() const; 86 int minimumHeightHint() const; 87 QSize minimumSizeHint() const; 88 void layoutContent(); 89 90 private slots: 91 92 /* Handler: Button stuff: */ 93 void sltButtonClicked(int iButtonID); 94 95 private: 96 97 /* Helpers: Prepare stuff: */ 98 void prepare(); 99 void prepareContent(); 100 101 /* Handler: Event-filter stuff: */ 102 bool eventFilter(QObject *pWatched, QEvent *pEvent); 103 104 /* Handler: Event stuff: */ 105 void paintEvent(QPaintEvent *pEvent); 106 107 /* Helper: Complete stuff: */ 108 void done(int iResultCode); 109 110 /* Property: Hover stuff: */ 111 int defaultOpacity() const { return m_iDefaultOpacity; } 112 int hoveredOpacity() const { return m_iHoveredOpacity; } 113 int opacity() const { return m_iOpacity; } 114 void setOpacity(int iOpacity) { m_iOpacity = iOpacity; update(); } 115 116 /* Variables: General stuff: */ 117 const QString m_strId; 118 const int m_iLayoutMargin; 119 const int m_iLayoutSpacing; 120 121 /* Variables: Text stuff: */ 122 QString m_strMessage, m_strDetails; 123 124 /* Variables: Auto-confirmation stuff: */ 125 bool m_fProposeAutoConfirmation; 126 127 /* Variables: Button stuff: */ 128 QMap<int, QString> m_buttonDescriptions; 129 130 /* Variables: Hover stuff: */ 131 bool m_fHovered; 132 const int m_iDefaultOpacity; 133 const int m_iHoveredOpacity; 134 int m_iOpacity; 135 136 /* Variables: Focus stuff: */ 137 bool m_fFocused; 138 139 /* Widgets: */ 140 UIPopupPaneTextPane *m_pTextPane; 141 UIPopupPaneButtonPane *m_pButtonPane; 142 }; 143 144 #endif /* __UIPopupPane_h__ */ 35 #endif /* __UIAnimationFramework_h__ */ -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.cpp
r45696 r46195 26 26 #include <QPainter> 27 27 #include <QStateMachine> 28 #include <QPropertyAnimation>29 #include <QSignalTransition>30 28 31 29 /* GUI includes: */ … … 34 32 #include "UIIconPool.h" 35 33 #include "QIToolButton.h" 34 #include "UIAnimationFramework.h" 36 35 37 36 /* Other VBox includes: */ 38 37 #include <VBox/sup.h> 39 40 41 QStateMachine* UIAnimationFramework::installPropertyAnimation(QWidget *pTarget, const char *pszPropertyName,42 const char *pszValuePropertyNameStart, const char *pszValuePropertyNameFinal,43 const char *pSignalForward, const char *pSignalBackward,44 bool fReversive /*= false*/, int iAnimationDuration /*= 300*/)45 {46 /* State-machine: */47 QStateMachine *pStateMachine = new QStateMachine(pTarget);48 /* State-machine 'start' state: */49 QState *pStateStart = new QState(pStateMachine);50 /* State-machine 'final' state: */51 QState *pStateFinal = new QState(pStateMachine);52 53 /* State-machine 'forward' animation: */54 QPropertyAnimation *pForwardAnimation = new QPropertyAnimation(pTarget, pszPropertyName, pStateMachine);55 pForwardAnimation->setEasingCurve(QEasingCurve(QEasingCurve::InOutCubic));56 pForwardAnimation->setDuration(iAnimationDuration);57 pForwardAnimation->setStartValue(pTarget->property(pszValuePropertyNameStart));58 pForwardAnimation->setEndValue(pTarget->property(pszValuePropertyNameFinal));59 /* State-machine 'backward' animation: */60 QPropertyAnimation *pBackwardAnimation = new QPropertyAnimation(pTarget, pszPropertyName, pStateMachine);61 pBackwardAnimation->setEasingCurve(QEasingCurve(QEasingCurve::InOutCubic));62 pBackwardAnimation->setDuration(iAnimationDuration);63 pBackwardAnimation->setStartValue(pTarget->property(pszValuePropertyNameFinal));64 pBackwardAnimation->setEndValue(pTarget->property(pszValuePropertyNameStart));65 66 /* State-machine state transitions: */67 QSignalTransition *pDefaultToHovered = pStateStart->addTransition(pTarget, pSignalForward, pStateFinal);68 pDefaultToHovered->addAnimation(pForwardAnimation);69 QSignalTransition *pHoveredToDefault = pStateFinal->addTransition(pTarget, pSignalBackward, pStateStart);70 pHoveredToDefault->addAnimation(pBackwardAnimation);71 72 /* Initial state is 'start': */73 pStateMachine->setInitialState(!fReversive ? pStateStart : pStateFinal);74 /* Start hover-machine: */75 pStateMachine->start();76 /* Return machine: */77 return pStateMachine;78 }79 38 80 39 -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupPane.h
r45696 r46195 28 28 29 29 /* Forward declaration: */ 30 class QStateMachine;31 30 class UIPopupPaneTextPane; 32 31 class UIPopupPaneButtonPane; 33 34 /* UIAnimationFramework namespace: */35 namespace UIAnimationFramework36 {37 /* API: Animation stuff: */38 QStateMachine* installPropertyAnimation(QWidget *pTarget, const char *pszPropertyName,39 const char *pszValuePropertyNameStart, const char *pszValuePropertyNameFinal,40 const char *pSignalForward, const char *pSignalBackward,41 bool fReversive = false, int iAnimationDuration = 300);42 }43 32 44 33 /* Popup-pane prototype class: */
Note:
See TracChangeset
for help on using the changeset viewer.