Changeset 52053 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Jul 16, 2014 2:41:46 PM (10 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r51992 r52053 482 482 src/runtime/UIMachine.cpp \ 483 483 src/runtime/UIMachineMenuBar.cpp \ 484 src/runtime/normal/UIMachineWindowNormal.cpp \ 484 485 src/selector/UIActionPoolSelector.cpp \ 485 486 src/selector/UIVMDesktop.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
r52014 r52053 24 24 #include <QContextMenuEvent> 25 25 #include <QResizeEvent> 26 27 #include <QStylePainter> 28 #include <QStyleOption> 29 #include <QPaintEvent> 30 #include <QPainter> 31 #include <QDrag> 26 32 27 33 /* GUI includes: */ … … 43 49 #endif /* Q_WS_MAC */ 44 50 51 #include "QIWithRetranslateUI.h" 52 #include "QIToolButton.h" 53 #include "UIIconPool.h" 54 #include "UIConverter.h" 55 #include "UIAnimationFramework.h" 56 45 57 /* COM includes: */ 46 58 #include "CConsole.h" … … 48 60 #include "CUSBController.h" 49 61 #include "CUSBDeviceFilters.h" 62 63 64 /** QWidget extension 65 * used as status-bar editor button. */ 66 class UIStatusBarEditorButton : public QIWithRetranslateUI<QWidget> 67 { 68 Q_OBJECT; 69 70 signals: 71 72 /** Notifies about click. */ 73 void sigClick(); 74 75 /** Notifies about drag-object destruction. */ 76 void sigDragObjectDestroy(); 77 78 public: 79 80 /** Holds the mime-type for the D&D system. */ 81 static const QString MimeType; 82 83 /** Constructor for the button of passed @a type. */ 84 UIStatusBarEditorButton(IndicatorType type); 85 86 /** Returns button type. */ 87 IndicatorType type() const { return m_type; } 88 89 /** Returns button size-hint. */ 90 QSize sizeHint() const { return m_size; } 91 92 /** Defines whether button is @a fChecked. */ 93 void setChecked(bool fChecked); 94 95 private: 96 97 /** Retranslation routine. */ 98 virtual void retranslateUi(); 99 100 /** Paint-event handler. */ 101 virtual void paintEvent(QPaintEvent *pEvent); 102 103 /** Mouse-press event handler. */ 104 virtual void mousePressEvent(QMouseEvent *pEvent); 105 /** Mouse-release event handler. */ 106 virtual void mouseReleaseEvent(QMouseEvent *pEvent); 107 /** Mouse-enter event handler. */ 108 virtual void enterEvent(QEvent *pEvent); 109 /** Mouse-leave event handler. */ 110 virtual void leaveEvent(QEvent *pEvent); 111 /** Mouse-move event handler. */ 112 virtual void mouseMoveEvent(QMouseEvent *pEvent); 113 114 /** Holds the button type. */ 115 IndicatorType m_type; 116 /** Holds the button size. */ 117 QSize m_size; 118 /** Holds the button pixmap. */ 119 QPixmap m_pixmap; 120 /** Holds whether button is checked. */ 121 bool m_fChecked; 122 /** Holds whether button is hovered. */ 123 bool m_fHovered; 124 /** Holds the last mouse-press position. */ 125 QPoint m_mousePressPosition; 126 }; 127 128 /* static */ 129 const QString UIStatusBarEditorButton::MimeType = QString("application/virtualbox;value=IndicatorType"); 130 131 UIStatusBarEditorButton::UIStatusBarEditorButton(IndicatorType type) 132 : m_type(type) 133 , m_fChecked(false) 134 , m_fHovered(false) 135 { 136 /* Track mouse events: */ 137 setMouseTracking(true); 138 139 /* Prepare icon for assigned type: */ 140 const QIcon icon = gpConverter->toIcon(m_type); 141 /* Cache button size-hint: */ 142 m_size = icon.availableSizes().first(); 143 /* Cache pixmap of same size: */ 144 m_pixmap = icon.pixmap(m_size); 145 146 /* Translate finally: */ 147 retranslateUi(); 148 } 149 150 void UIStatusBarEditorButton::setChecked(bool fChecked) 151 { 152 /* Update 'checked' state: */ 153 m_fChecked = fChecked; 154 /* Update: */ 155 update(); 156 } 157 158 void UIStatusBarEditorButton::retranslateUi() 159 { 160 /* Translate tool-tip: */ 161 setToolTip(tr("<nobr><b>Click</b> to toggle indicator presence.</nobr><br>" 162 "<nobr><b>Drag&Drop</b> to change indicator position.</nobr>")); 163 } 164 165 void UIStatusBarEditorButton::paintEvent(QPaintEvent*) 166 { 167 /* Create style-painter: */ 168 QStylePainter painter(this); 169 QStyleOption option; 170 option.initFrom(this); 171 option.rect = QRect(0, 0, width(), height()); 172 /* Remember checked-state: */ 173 if (m_fChecked) 174 option.state |= QStyle::State_On; 175 /* Draw check-box for hovered-state: */ 176 if (m_fHovered) 177 painter.drawPrimitive(QStyle::PE_IndicatorCheckBox, option); 178 /* Draw pixmap for unhovered-state: */ 179 else 180 painter.drawItemPixmap(option.rect, Qt::AlignCenter, m_pixmap); 181 } 182 183 void UIStatusBarEditorButton::mousePressEvent(QMouseEvent *pEvent) 184 { 185 /* We are interested in left button only: */ 186 if (pEvent->button() != Qt::LeftButton) 187 return; 188 189 /* Remember mouse-press position: */ 190 m_mousePressPosition = pEvent->globalPos(); 191 } 192 193 void UIStatusBarEditorButton::mouseReleaseEvent(QMouseEvent *pEvent) 194 { 195 /* We are interested in left button only: */ 196 if (pEvent->button() != Qt::LeftButton) 197 return; 198 199 /* Forget mouse-press position: */ 200 m_mousePressPosition = QPoint(); 201 202 /* Notify about click: */ 203 emit sigClick(); 204 } 205 206 void UIStatusBarEditorButton::enterEvent(QEvent*) 207 { 208 /* Make sure button isn't hovered: */ 209 if (m_fHovered) 210 return; 211 212 /* Invert hovered state: */ 213 m_fHovered = true; 214 /* Update: */ 215 update(); 216 } 217 218 void UIStatusBarEditorButton::leaveEvent(QEvent*) 219 { 220 /* Make sure button is hovered: */ 221 if (!m_fHovered) 222 return; 223 224 /* Invert hovered state: */ 225 m_fHovered = false; 226 /* Update: */ 227 update(); 228 } 229 230 void UIStatusBarEditorButton::mouseMoveEvent(QMouseEvent *pEvent) 231 { 232 /* Make sure item isn't already dragged: */ 233 if (m_mousePressPosition.isNull()) 234 return QWidget::mouseMoveEvent(pEvent); 235 236 /* Make sure item is really dragged: */ 237 if (QLineF(pEvent->globalPos(), m_mousePressPosition).length() < 238 QApplication::startDragDistance()) 239 return QWidget::mouseMoveEvent(pEvent); 240 241 /* Initialize dragging: */ 242 m_mousePressPosition = QPoint(); 243 QDrag *pDrag = new QDrag(this); 244 connect(pDrag, SIGNAL(destroyed(QObject*)), this, SIGNAL(sigDragObjectDestroy())); 245 QMimeData *pMimeData = new QMimeData; 246 pMimeData->setData(MimeType, gpConverter->toInternalString(m_type).toLatin1()); 247 pDrag->setMimeData(pMimeData); 248 pDrag->setPixmap(m_pixmap); 249 pDrag->exec(); 250 } 251 252 253 /** QWidget reimplementation 254 * providing user with possibility to edit status-bar layout. */ 255 class UIStatusBarEditorWindow : public QIWithRetranslateUI2<QWidget> 256 { 257 Q_OBJECT; 258 Q_PROPERTY(QRect startGeometry READ startGeometry); 259 Q_PROPERTY(QRect finalGeometry READ finalGeometry); 260 261 signals: 262 263 /** Notifies about window shown. */ 264 void sigShown(); 265 /** Commands window to expand. */ 266 void sigExpand(); 267 /** Commands window to collapse. */ 268 void sigCollapse(); 269 270 public: 271 272 /** Constructor, passes @a pParent to the QIRichToolButton constructor. 273 * @param rect is used to define initial cached parent geometry. 274 * @param statusBarRect is used to define initial cached status-bar geometry. */ 275 UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect); 276 277 private slots: 278 279 /** Mark window as expanded. */ 280 void sltMarkAsExpanded() { m_fExpanded = true; } 281 /** Mark window as collapsed. */ 282 void sltMarkAsCollapsed() { close(); m_fExpanded = false; } 283 284 /** Handles parent geometry change. */ 285 void sltParentGeometryChanged(const QRect &rect); 286 287 /** Handles configuration change. */ 288 void sltHandleConfigurationChange(); 289 290 /** Handles button click. */ 291 void sltHandleButtonClick(); 292 293 /** Handles drag object destroy. */ 294 void sltHandleDragObjectDestroy(); 295 296 private: 297 298 /** Prepare routine. */ 299 void prepare(); 300 /** Prepare status buttons routine. */ 301 void prepareStatusButtons(); 302 /** Prepare status button routine. */ 303 void prepareStatusButton(IndicatorType type); 304 /** Prepare animation routine. */ 305 void prepareAnimation(); 306 307 /** Updates status buttons. */ 308 void updateStatusButtons(); 309 /** Updates animation. */ 310 void updateAnimation(); 311 /** Update geometry. */ 312 void adjustGeometry(); 313 314 /** Retranslation routine. */ 315 virtual void retranslateUi(); 316 317 /** Show event handler. */ 318 virtual void showEvent(QShowEvent *pEvent); 319 /** Close event handler. */ 320 virtual void closeEvent(QCloseEvent *pEvent); 321 322 /** Paint event handler. */ 323 virtual void paintEvent(QPaintEvent *pEvent); 324 325 /** Drag-enter event handler. */ 326 virtual void dragEnterEvent(QDragEnterEvent *pEvent); 327 /** Drag-move event handler. */ 328 virtual void dragMoveEvent(QDragMoveEvent *pEvent); 329 /** Drag-leave event handler. */ 330 virtual void dragLeaveEvent(QDragLeaveEvent *pEvent); 331 /** Drop event handler. */ 332 virtual void dropEvent(QDropEvent *pEvent); 333 334 /** Returns position for passed @a type. */ 335 int position(IndicatorType type) const; 336 337 /** Returns cached start-geometry. */ 338 QRect startGeometry() const { return m_startGeometry; } 339 /** Returns cached final-geometry. */ 340 QRect finalGeometry() const { return m_finalGeometry; } 341 342 /** @name Geometry 343 * @{ */ 344 /** Holds the cached parent geometry. */ 345 QRect m_rect; 346 /** Holds the cached status-bar geometry. */ 347 QRect m_statusBarRect; 348 /** @} */ 349 350 /** @name Geometry: Animation 351 * @{ */ 352 /** Holds the expand/collapse animation instance. */ 353 UIAnimation *m_pAnimation; 354 /** Holds whether window is expanded. */ 355 bool m_fExpanded; 356 /** Holds the cached start-geometry. */ 357 QRect m_startGeometry; 358 /** Holds the cached final-geometry. */ 359 QRect m_finalGeometry; 360 /** @} */ 361 362 /** @name Contents 363 * @{ */ 364 /** Holds the main-layout instance. */ 365 QHBoxLayout *m_pMainLayout; 366 /** Holds the button-layout instance. */ 367 QHBoxLayout *m_pButtonLayout; 368 /** Holds the close-button instance. */ 369 QIToolButton *m_pButtonClose; 370 /** Holds status-bar buttons. */ 371 QMap<IndicatorType, UIStatusBarEditorButton*> m_buttons; 372 /** @} */ 373 374 /** @name Contents: Restrictions 375 * @{ */ 376 /** Holds the cached status-bar button restrictions. */ 377 QList<IndicatorType> m_restrictions; 378 /** @} */ 379 380 /** @name Contents: Order 381 * @{ */ 382 /** Holds the cached status-bar button order. */ 383 QList<IndicatorType> m_order; 384 /** Holds the token-button to drop dragged-button nearby. */ 385 UIStatusBarEditorButton *m_pButtonDropToken; 386 /** Holds whether dragged-button should be dropped <b>after</b> the token-button. */ 387 bool m_fDropAfterTokenButton; 388 /** @} */ 389 }; 390 391 UIStatusBarEditorWindow::UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect) 392 : QIWithRetranslateUI2<QWidget>(pParent, Qt::Tool | Qt::FramelessWindowHint) 393 , m_rect(rect), m_statusBarRect(statusBarRect) 394 , m_pAnimation(0), m_fExpanded(false) 395 , m_pMainLayout(0), m_pButtonLayout(0) 396 , m_pButtonClose(0) 397 , m_pButtonDropToken(0) 398 , m_fDropAfterTokenButton(true) 399 { 400 /* Prepare: */ 401 prepare(); 402 } 403 404 void UIStatusBarEditorWindow::sltParentGeometryChanged(const QRect &rect) 405 { 406 /* Update rectangle: */ 407 m_rect = rect; 408 /* Update animation: */ 409 updateAnimation(); 410 /* Adjust geometry: */ 411 adjustGeometry(); 412 } 413 414 void UIStatusBarEditorWindow::sltHandleConfigurationChange() 415 { 416 /* Update status buttons: */ 417 updateStatusButtons(); 418 } 419 420 void UIStatusBarEditorWindow::sltHandleButtonClick() 421 { 422 /* Make sure sender is valid: */ 423 UIStatusBarEditorButton *pButton = qobject_cast<UIStatusBarEditorButton*>(sender()); 424 AssertPtrReturnVoid(pButton); 425 426 /* Get sender type: */ 427 const IndicatorType type = pButton->type(); 428 429 /* Load current status-bar indicator restrictions: */ 430 QList<IndicatorType> restrictions = 431 gEDataManager->restrictedStatusBarIndicators(vboxGlobal().managedVMUuid()); 432 433 /* Invert restriction for sender type: */ 434 if (restrictions.contains(type)) 435 restrictions.removeAll(type); 436 else 437 restrictions.append(type); 438 439 /* Save updated status-bar indicator restrictions: */ 440 gEDataManager->setRestrictedStatusBarIndicators(restrictions, vboxGlobal().managedVMUuid()); 441 } 442 443 void UIStatusBarEditorWindow::sltHandleDragObjectDestroy() 444 { 445 /* Reset token: */ 446 m_pButtonDropToken = 0; 447 m_fDropAfterTokenButton = true; 448 /* Update: */ 449 update(); 450 } 451 452 void UIStatusBarEditorWindow::prepare() 453 { 454 /* Do not count that window as important for application, 455 * it will NOT be taken into account when other top-level windows will be closed: */ 456 setAttribute(Qt::WA_QuitOnClose, false); 457 /* Delete window when closed: */ 458 setAttribute(Qt::WA_DeleteOnClose); 459 /* Make window background translucent: */ 460 setAttribute(Qt::WA_TranslucentBackground); 461 /* Track D&D events: */ 462 setAcceptDrops(true); 463 464 /* Create main-layout: */ 465 m_pMainLayout = new QHBoxLayout(this); 466 AssertPtrReturnVoid(m_pMainLayout); 467 { 468 /* Configure main-layout: */ 469 int iLeft, iTop, iRight, iBottom; 470 m_pMainLayout->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom); 471 if (iBottom >= 5) 472 iBottom -= 5; 473 m_pMainLayout->setContentsMargins(iLeft, iTop, iRight, iBottom); 474 m_pMainLayout->setSpacing(0); 475 /* Create close-button: */ 476 m_pButtonClose = new QIToolButton; 477 AssertPtrReturnVoid(m_pButtonClose); 478 { 479 /* Configure close-button: */ 480 m_pButtonClose->setMinimumSize(QSize(1, 1)); 481 m_pButtonClose->setShortcut(Qt::Key_Escape); 482 m_pButtonClose->setIcon(UIIconPool::iconSet(":/ok_16px.png")); 483 connect(m_pButtonClose, SIGNAL(clicked(bool)), this, SLOT(close())); 484 /* Add close-button into main-layout: */ 485 m_pMainLayout->addWidget(m_pButtonClose); 486 } 487 /* Insert stretch: */ 488 m_pMainLayout->addStretch(); 489 /* Create button-layout: */ 490 m_pButtonLayout = new QHBoxLayout; 491 AssertPtrReturnVoid(m_pButtonLayout); 492 { 493 /* Configure button-layout: */ 494 m_pButtonLayout->setContentsMargins(0, 0, 0, 0); 495 m_pButtonLayout->setSpacing(5); 496 /* Add button-layout into main-layout: */ 497 m_pMainLayout->addLayout(m_pButtonLayout); 498 } 499 /* Prepare status buttons: */ 500 prepareStatusButtons(); 501 } 502 503 /* Translate contents: */ 504 retranslateUi(); 505 506 /* Prepare animation: */ 507 prepareAnimation(); 508 509 /* Activate window: */ 510 activateWindow(); 511 } 512 513 void UIStatusBarEditorWindow::prepareStatusButtons() 514 { 515 /* Create status buttons: */ 516 for (int i = IndicatorType_Invalid; i < IndicatorType_Max; ++i) 517 { 518 /* Get current type: */ 519 const IndicatorType type = (IndicatorType)i; 520 /* Skip inappropriate types: */ 521 if (type == IndicatorType_Invalid || type == IndicatorType_KeyboardExtension) 522 continue; 523 /* Create status button: */ 524 prepareStatusButton(type); 525 } 526 527 /* Listen for the status-bar configuration changes: */ 528 connect(gEDataManager, SIGNAL(sigStatusBarConfigurationChange()), 529 this, SLOT(sltHandleConfigurationChange())); 530 /* Update status buttons: */ 531 updateStatusButtons(); 532 } 533 534 void UIStatusBarEditorWindow::prepareStatusButton(IndicatorType type) 535 { 536 /* Create status button: */ 537 UIStatusBarEditorButton *pButton = new UIStatusBarEditorButton(type); 538 AssertPtrReturnVoid(pButton); 539 { 540 /* Configure status button: */ 541 connect(pButton, SIGNAL(sigClick()), this, SLOT(sltHandleButtonClick())); 542 connect(pButton, SIGNAL(sigDragObjectDestroy()), this, SLOT(sltHandleDragObjectDestroy())); 543 /* Add status button into button-layout: */ 544 m_pButtonLayout->addWidget(pButton); 545 /* Insert status button into map: */ 546 m_buttons.insert(type, pButton); 547 } 548 } 549 550 void UIStatusBarEditorWindow::prepareAnimation() 551 { 552 /* Prepare geometry animation itself: */ 553 connect(this, SIGNAL(sigShown()), this, SIGNAL(sigExpand()), Qt::QueuedConnection); 554 m_pAnimation = UIAnimation::installPropertyAnimation(this, "geometry", "startGeometry", "finalGeometry", 555 SIGNAL(sigExpand()), SIGNAL(sigCollapse())); 556 connect(m_pAnimation, SIGNAL(sigStateEnteredStart()), this, SLOT(sltMarkAsCollapsed())); 557 connect(m_pAnimation, SIGNAL(sigStateEnteredFinal()), this, SLOT(sltMarkAsExpanded())); 558 /* Update animation: */ 559 updateAnimation(); 560 } 561 562 void UIStatusBarEditorWindow::updateStatusButtons() 563 { 564 /* Recache status-bar configuration: */ 565 m_restrictions = gEDataManager->restrictedStatusBarIndicators(vboxGlobal().managedVMUuid()); 566 m_order = gEDataManager->statusBarIndicatorOrder(vboxGlobal().managedVMUuid()); 567 for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType) 568 if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension && 569 !m_order.contains((IndicatorType)iType)) 570 m_order << (IndicatorType)iType; 571 572 /* Update configuration for all the status buttons: */ 573 foreach (const IndicatorType &type, m_order) 574 { 575 /* Get button: */ 576 UIStatusBarEditorButton *pButton = m_buttons.value(type); 577 /* Update button 'checked' state: */ 578 pButton->setChecked(!m_restrictions.contains(type)); 579 /* Make sure it have valid position: */ 580 const int iWantedIndex = position(type); 581 const int iActualIndex = m_pButtonLayout->indexOf(pButton); 582 if (iActualIndex != iWantedIndex) 583 { 584 /* Re-inject button into main-layout at proper position: */ 585 m_pButtonLayout->removeWidget(pButton); 586 m_pButtonLayout->insertWidget(iWantedIndex, pButton); 587 } 588 } 589 } 590 591 void UIStatusBarEditorWindow::updateAnimation() 592 { 593 /* Calculate geometry animation boundaries 594 * based on size-hint and minimum size-hint: */ 595 const QSize sh = sizeHint(); 596 const QSize msh = minimumSizeHint(); 597 m_startGeometry = QRect(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - msh.height(), 598 qMax(m_rect.width(), msh.width()), msh.height()); 599 m_finalGeometry = QRect(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - sh.height(), 600 qMax(m_rect.width(), sh.width()), sh.height()); 601 m_pAnimation->update(); 602 } 603 604 void UIStatusBarEditorWindow::adjustGeometry() 605 { 606 /* Adjust geometry based on size-hint: */ 607 const QSize sh = sizeHint(); 608 setGeometry(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - sh.height(), 609 qMax(m_rect.width(), sh.width()), sh.height()); 610 raise(); 611 } 612 613 void UIStatusBarEditorWindow::retranslateUi() 614 { 615 /* Translate close-button: */ 616 m_pButtonClose->setToolTip(tr("Close")); 617 } 618 619 void UIStatusBarEditorWindow::showEvent(QShowEvent*) 620 { 621 /* If window isn't expanded: */ 622 if (!m_fExpanded) 623 { 624 /* Start expand animation: */ 625 emit sigShown(); 626 } 627 } 628 629 void UIStatusBarEditorWindow::closeEvent(QCloseEvent *pEvent) 630 { 631 /* If window isn't expanded: */ 632 if (!m_fExpanded) 633 { 634 /* Ignore close-event: */ 635 pEvent->ignore(); 636 return; 637 } 638 639 /* If animation state is Final: */ 640 const QString strAnimationState = property("AnimationState").toString(); 641 bool fAnimationComplete = strAnimationState == "Final"; 642 if (fAnimationComplete) 643 { 644 /* Ignore close-event: */ 645 pEvent->ignore(); 646 /* And start collapse animation: */ 647 emit sigCollapse(); 648 } 649 } 650 651 void UIStatusBarEditorWindow::paintEvent(QPaintEvent*) 652 { 653 /* Prepare painter: */ 654 QPainter painter(this); 655 656 /* Prepare palette colors: */ 657 const QPalette pal = palette(); 658 QColor color0 = pal.color(QPalette::Window); 659 QColor color1 = pal.color(QPalette::Window).lighter(110); 660 color1.setAlpha(0); 661 QColor color2 = pal.color(QPalette::Window).darker(200); 662 QColor color3 = pal.color(QPalette::Window).darker(120); 663 664 /* Left corner: */ 665 QRadialGradient grad1(QPointF(5, 5), 5); 666 { 667 grad1.setColorAt(0, color2); 668 grad1.setColorAt(1, color1); 669 } 670 /* Right corner: */ 671 QRadialGradient grad2(QPointF(width() - 5, 5), 5); 672 { 673 grad2.setColorAt(0, color2); 674 grad2.setColorAt(1, color1); 675 } 676 /* Top line: */ 677 QLinearGradient grad3(QPointF(5, 0), QPointF(5, 5)); 678 { 679 grad3.setColorAt(0, color1); 680 grad3.setColorAt(1, color2); 681 } 682 /* Left line: */ 683 QLinearGradient grad4(QPointF(0, 5), QPointF(5, 5)); 684 { 685 grad4.setColorAt(0, color1); 686 grad4.setColorAt(1, color2); 687 } 688 /* Right line: */ 689 QLinearGradient grad5(QPointF(width(), 5), QPointF(width() - 5, 5)); 690 { 691 grad5.setColorAt(0, color1); 692 grad5.setColorAt(1, color2); 693 } 694 695 /* Paint frames: */ 696 painter.fillRect(QRect(5, 5, width() - 5 * 2, height() - 5), color0); 697 painter.fillRect(QRect(0, 0, 5, 5), grad1); 698 painter.fillRect(QRect(width() - 5, 0, 5, 5), grad2); 699 painter.fillRect(QRect(5, 0, width() - 5 * 2, 5), grad3); 700 painter.fillRect(QRect(0, 5, 5, height() - 5), grad4); 701 painter.fillRect(QRect(width() - 5, 5, 5, height() - 5), grad5); 702 painter.save(); 703 painter.setPen(color3); 704 painter.drawLine(QLine(QPoint(5 + 1, 5 + 1), QPoint(width() - 1 - 5 - 1, 5 + 1))); 705 painter.drawLine(QLine(QPoint(width() - 1 - 5 - 1, 5 + 1), QPoint(width() - 1 - 5 - 1, height() - 1))); 706 painter.drawLine(QLine(QPoint(width() - 1 - 5 - 1, height() - 1), QPoint(5 + 1, height() - 1))); 707 painter.drawLine(QLine(QPoint(5 + 1, height() - 1), QPoint(5 + 1, 5 + 1))); 708 painter.restore(); 709 710 /* Paint drop token: */ 711 if (m_pButtonDropToken) 712 { 713 QStyleOption option; 714 option.state |= QStyle::State_Horizontal; 715 const QRect geo = m_pButtonDropToken->geometry(); 716 option.rect = !m_fDropAfterTokenButton ? 717 QRect(geo.topLeft() - QPoint(5, 5), 718 geo.bottomLeft() + QPoint(0, 5)) : 719 QRect(geo.topRight() - QPoint(0, 5), 720 geo.bottomRight() + QPoint(5, 5)); 721 QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, 722 &option, &painter); 723 } 724 } 725 726 void UIStatusBarEditorWindow::dragEnterEvent(QDragEnterEvent *pEvent) 727 { 728 /* Make sure event is valid: */ 729 AssertPtrReturnVoid(pEvent); 730 /* And mime-data is set: */ 731 const QMimeData *pMimeData = pEvent->mimeData(); 732 AssertPtrReturnVoid(pMimeData); 733 /* Make sure mime-data format is valid: */ 734 if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType)) 735 return; 736 737 /* Accept drag-enter event: */ 738 pEvent->acceptProposedAction(); 739 } 740 741 void UIStatusBarEditorWindow::dragMoveEvent(QDragMoveEvent *pEvent) 742 { 743 /* Make sure event is valid: */ 744 AssertPtrReturnVoid(pEvent); 745 /* And mime-data is set: */ 746 const QMimeData *pMimeData = pEvent->mimeData(); 747 AssertPtrReturnVoid(pMimeData); 748 /* Make sure mime-data format is valid: */ 749 if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType)) 750 return; 751 752 /* Reset token: */ 753 m_pButtonDropToken = 0; 754 m_fDropAfterTokenButton = true; 755 756 /* Get event position: */ 757 const QPoint pos = pEvent->pos(); 758 /* Search for most suitable button: */ 759 foreach (const IndicatorType &type, m_order) 760 { 761 m_pButtonDropToken = m_buttons.value(type); 762 const QRect geo = m_pButtonDropToken->geometry(); 763 if (pos.x() < geo.center().x()) 764 { 765 m_fDropAfterTokenButton = false; 766 break; 767 } 768 } 769 /* Update: */ 770 update(); 771 } 772 773 void UIStatusBarEditorWindow::dragLeaveEvent(QDragLeaveEvent*) 774 { 775 /* Reset token: */ 776 m_pButtonDropToken = 0; 777 m_fDropAfterTokenButton = true; 778 /* Update: */ 779 update(); 780 } 781 782 void UIStatusBarEditorWindow::dropEvent(QDropEvent *pEvent) 783 { 784 /* Make sure event is valid: */ 785 AssertPtrReturnVoid(pEvent); 786 /* And mime-data is set: */ 787 const QMimeData *pMimeData = pEvent->mimeData(); 788 AssertPtrReturnVoid(pMimeData); 789 /* Make sure mime-data format is valid: */ 790 if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType)) 791 return; 792 793 /* Make sure token-button set: */ 794 if (!m_pButtonDropToken) 795 return; 796 797 /* Determine type of token-button: */ 798 const IndicatorType tokenType = m_pButtonDropToken->type(); 799 /* Determine type of dropped-button: */ 800 const QString strDroppedType = 801 QString::fromLatin1(pMimeData->data(UIStatusBarEditorButton::MimeType)); 802 const IndicatorType droppedType = 803 gpConverter->fromInternalString<IndicatorType>(strDroppedType); 804 805 /* Make sure these types are different: */ 806 if (droppedType == tokenType) 807 return; 808 809 /* Load current status-bar indicator order and make sure it's complete: */ 810 QList<IndicatorType> order = 811 gEDataManager->statusBarIndicatorOrder(vboxGlobal().managedVMUuid()); 812 for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType) 813 if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension && 814 !order.contains((IndicatorType)iType)) 815 order << (IndicatorType)iType; 816 817 /* Remove type of dropped-button: */ 818 order.removeAll(droppedType); 819 /* Insert type of dropped-button into position of token-button: */ 820 int iPosition = order.indexOf(tokenType); 821 if (m_fDropAfterTokenButton) 822 ++iPosition; 823 order.insert(iPosition, droppedType); 824 825 /* Save updated status-bar indicator order: */ 826 gEDataManager->setStatusBarIndicatorOrder(order, vboxGlobal().managedVMUuid()); 827 } 828 829 int UIStatusBarEditorWindow::position(IndicatorType type) const 830 { 831 int iPosition = 0; 832 foreach (const IndicatorType &iteratedType, m_order) 833 if (iteratedType == type) 834 return iPosition; 835 else 836 ++iPosition; 837 return iPosition; 838 } 839 50 840 51 841 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId) … … 110 900 /* Update virtualization stuff: */ 111 901 updateAppearanceOf(UIVisualElement_FeaturesStuff); 902 } 903 904 void UIMachineWindowNormal::sltShowStatusBarContextMenu(const QPoint &position) 905 { 906 /* Prepare context-menu: */ 907 QMenu menu; 908 /* Having just one action to configure status-bar: */ 909 QAction *pAction = menu.addAction(UIIconPool::iconSet(":/vm_settings_16px.png"), 910 tr("Configure status-bar..."), 911 this, SLOT(sltOpenStatusBarEditorWindow())); 912 pAction->setEnabled(!uisession()->property("StatusBarEditorOpened").toBool()); 913 /* Execute context-menu: */ 914 menu.exec(statusBar()->mapToGlobal(position)); 915 } 916 917 void UIMachineWindowNormal::sltOpenStatusBarEditorWindow() 918 { 919 /* Prevent user from opening another one editor: */ 920 uisession()->setProperty("StatusBarEditorOpened", true); 921 /* Create status-bar editor: */ 922 UIStatusBarEditorWindow *pStatusBarEditor = 923 new UIStatusBarEditorWindow(this, m_normalGeometry, statusBar()->geometry()); 924 AssertPtrReturnVoid(pStatusBarEditor); 925 { 926 /* Configure status-bar editor: */ 927 connect(this, SIGNAL(sigGeometryChange(const QRect&)), 928 pStatusBarEditor, SLOT(sltParentGeometryChanged(const QRect&))); 929 connect(pStatusBarEditor, SIGNAL(destroyed(QObject*)), 930 this, SLOT(sltStatusBarEditorWindowClosed())); 931 /* Show window: */ 932 pStatusBarEditor->show(); 933 } 934 } 935 936 void UIMachineWindowNormal::sltStatusBarEditorWindowClosed() 937 { 938 /* Allow user to open editor again: */ 939 uisession()->setProperty("StatusBarEditorOpened", QVariant()); 112 940 } 113 941 … … 190 1018 AssertPtrReturnVoid(statusBar()); 191 1019 { 1020 #ifdef Q_WS_WIN 1021 /* Configure status-bar: */ 1022 statusBar()->setContextMenuPolicy(Qt::CustomContextMenu); 1023 connect(statusBar(), SIGNAL(customContextMenuRequested(const QPoint&)), 1024 this, SLOT(sltShowStatusBarContextMenu(const QPoint&))); 1025 #endif /* Q_WS_WIN */ 192 1026 /* Create indicator-pool: */ 193 1027 m_pIndicatorsPool = new UIIndicatorsPool(machineLogic()->uisession()); … … 329 1163 { 330 1164 m_normalGeometry.setSize(pResizeEvent->size()); 1165 emit sigGeometryChange(m_normalGeometry); 331 1166 #ifdef VBOX_WITH_DEBUGGER_GUI 332 1167 /* Update debugger window position: */ … … 341 1176 { 342 1177 m_normalGeometry.moveTo(geometry().x(), geometry().y()); 1178 emit sigGeometryChange(m_normalGeometry); 343 1179 #ifdef VBOX_WITH_DEBUGGER_GUI 344 1180 /* Update debugger window position: */ … … 348 1184 break; 349 1185 } 1186 case QEvent::WindowActivate: 1187 emit sigGeometryChange(m_normalGeometry); 1188 break; 350 1189 default: 351 1190 break; … … 465 1304 } 466 1305 467 1306 #include "UIMachineWindowNormal.moc" 1307 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.h
r52014 r52053 32 32 Q_OBJECT; 33 33 34 signals: 35 36 /** Notifies about geometry change. */ 37 void sigGeometryChange(const QRect &rect); 38 34 39 protected: 35 40 … … 53 58 void sltVideoCaptureChange(); 54 59 void sltCPUExecutionCapChange(); 60 61 /** Handles status-bar context-menu-request: */ 62 void sltShowStatusBarContextMenu(const QPoint &position); 63 /** Handles status-bar editor opening. */ 64 void sltOpenStatusBarEditorWindow(); 65 /** Handles status-bar editor closing. */ 66 void sltStatusBarEditorWindowClosed(); 55 67 56 68 /** Handles indicator context-menu-request: */
Note:
See TracChangeset
for help on using the changeset viewer.