VirtualBox

Changeset 52070 in vbox for trunk/src


Ignore:
Timestamp:
Jul 17, 2014 9:09:10 AM (11 years ago)
Author:
vboxsync
Message:

FE/Qt: 3646: Status-bar Editor: Move code to separate files.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
2 edited
2 copied

Legend:

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

    r52053 r52070  
    303303        src/runtime/UIMultiScreenLayout.h \
    304304        src/runtime/UISession.h \
     305        src/runtime/UIStatusBarEditorWindow.h \
    305306        src/runtime/UIVMCloseDialog.h \
    306307        src/runtime/fullscreen/UIKeyboardHandlerFullscreen.h \
     
    482483        src/runtime/UIMachine.cpp \
    483484        src/runtime/UIMachineMenuBar.cpp \
    484         src/runtime/normal/UIMachineWindowNormal.cpp \
     485        src/runtime/UIStatusBarEditorWindow.cpp \
    485486        src/selector/UIActionPoolSelector.cpp \
    486487        src/selector/UIVMDesktop.cpp \
     
    579580        src/runtime/UIMultiScreenLayout.cpp \
    580581        src/runtime/UISession.cpp \
     582        src/runtime/UIStatusBarEditorWindow.cpp \
    581583        src/runtime/UIVMCloseDialog.cpp \
    582584        src/runtime/fullscreen/UIKeyboardHandlerFullscreen.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIStatusBarEditorWindow.cpp

    r52064 r52070  
    11/* $Id$ */
    22/** @file
    3  *
    4  * VBox frontends: Qt GUI ("VirtualBox"):
    5  * UIMachineWindowNormal class implementation
     3 * VBox Qt GUI - UIStatusBarEditorWindow class implementation.
    64 */
    75
    86/*
    9  * Copyright (C) 2010-2012 Oracle Corporation
     7 * Copyright (C) 2010-2014 Oracle Corporation
    108 *
    119 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1917
    2018/* Qt includes: */
    21 #include <QDesktopWidget>
    22 #include <QMenuBar>
    23 #include <QTimer>
    24 #include <QContextMenuEvent>
    25 #include <QResizeEvent>
    26 
    2719#include <QStylePainter>
    2820#include <QStyleOption>
     21#include <QHBoxLayout>
    2922#include <QPaintEvent>
     23#include <QMouseEvent>
    3024#include <QPainter>
     25#include <QPixmap>
    3126#include <QDrag>
    3227
    3328/* GUI includes: */
     29#include "UIStatusBarEditorWindow.h"
     30#include "UIAnimationFramework.h"
     31#include "UIExtraDataManager.h"
     32#include "UIConverter.h"
     33#include "UIIconPool.h"
     34#include "QIToolButton.h"
    3435#include "VBoxGlobal.h"
    35 #include "UIExtraDataManager.h"
    36 #include "UISession.h"
    37 #include "UIActionPoolRuntime.h"
    38 #include "UIIndicatorsPool.h"
    39 #include "UIKeyboardHandler.h"
    40 #include "UIMouseHandler.h"
    41 #include "UIMachineLogic.h"
    42 #include "UIMachineWindowNormal.h"
    43 #include "UIMachineView.h"
    44 #include "QIStatusBar.h"
    45 #include "QIStatusBarIndicator.h"
    46 #ifdef Q_WS_MAC
    47 # include "VBoxUtils.h"
    48 # include "UIImageTools.h"
    49 #endif /* Q_WS_MAC */
    50 
    51 #include "QIWithRetranslateUI.h"
    52 #include "QIToolButton.h"
    53 #include "UIIconPool.h"
    54 #include "UIConverter.h"
    55 #include "UIAnimationFramework.h"
    56 
    57 /* COM includes: */
    58 #include "CConsole.h"
    59 #include "CMediumAttachment.h"
    60 #include "CUSBController.h"
    61 #include "CUSBDeviceFilters.h"
    6236
    6337
     
    12599    QPoint m_mousePressPosition;
    126100};
     101
    127102
    128103/* static */
     
    255230}
    256231
    257 
    258 /** QWidget reimplementation
    259   * providing user with possibility to edit status-bar layout. */
    260 class UIStatusBarEditorWindow : public QIWithRetranslateUI2<QWidget>
    261 {
    262     Q_OBJECT;
    263     Q_PROPERTY(QRect startGeometry READ startGeometry);
    264     Q_PROPERTY(QRect finalGeometry READ finalGeometry);
    265 
    266 signals:
    267 
    268     /** Notifies about window shown. */
    269     void sigShown();
    270     /** Commands window to expand. */
    271     void sigExpand();
    272     /** Commands window to collapse. */
    273     void sigCollapse();
    274 
    275 public:
    276 
    277     /** Constructor, passes @a pParent to the QIRichToolButton constructor.
    278       * @param rect is used to define initial cached parent geometry.
    279       * @param statusBarRect is used to define initial cached status-bar geometry. */
    280     UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect);
    281 
    282 private slots:
    283 
    284     /** Mark window as expanded. */
    285     void sltMarkAsExpanded() { m_fExpanded = true; }
    286     /** Mark window as collapsed. */
    287     void sltMarkAsCollapsed() { close(); m_fExpanded = false; }
    288 
    289     /** Handles parent geometry change. */
    290     void sltParentGeometryChanged(const QRect &rect);
    291 
    292     /** Handles configuration change. */
    293     void sltHandleConfigurationChange();
    294 
    295     /** Handles button click. */
    296     void sltHandleButtonClick();
    297 
    298     /** Handles drag object destroy. */
    299     void sltHandleDragObjectDestroy();
    300 
    301     /** Performs window activation. */
    302     void sltActivateWindow() { activateWindow(); }
    303 
    304 private:
    305 
    306     /** Prepare routine. */
    307     void prepare();
    308     /** Prepare status buttons routine. */
    309     void prepareStatusButtons();
    310     /** Prepare status button routine. */
    311     void prepareStatusButton(IndicatorType type);
    312     /** Prepare animation routine. */
    313     void prepareAnimation();
    314     /** Prepare geometry. */
    315     void prepareGeometry();
    316 
    317     /** Updates status buttons. */
    318     void updateStatusButtons();
    319     /** Updates animation. */
    320     void updateAnimation();
    321     /** Update geometry. */
    322     void adjustGeometry();
    323 
    324     /** Retranslation routine. */
    325     virtual void retranslateUi();
    326 
    327     /** Show event handler. */
    328     virtual void showEvent(QShowEvent *pEvent);
    329     /** Close event handler. */
    330     virtual void closeEvent(QCloseEvent *pEvent);
    331 
    332     /** Paint event handler. */
    333     virtual void paintEvent(QPaintEvent *pEvent);
    334 
    335     /** Drag-enter event handler. */
    336     virtual void dragEnterEvent(QDragEnterEvent *pEvent);
    337     /** Drag-move event handler. */
    338     virtual void dragMoveEvent(QDragMoveEvent *pEvent);
    339     /** Drag-leave event handler. */
    340     virtual void dragLeaveEvent(QDragLeaveEvent *pEvent);
    341     /** Drop event handler. */
    342     virtual void dropEvent(QDropEvent *pEvent);
    343 
    344     /** Returns position for passed @a type. */
    345     int position(IndicatorType type) const;
    346 
    347     /** Returns cached start-geometry. */
    348     QRect startGeometry() const { return m_startGeometry; }
    349     /** Returns cached final-geometry. */
    350     QRect finalGeometry() const { return m_finalGeometry; }
    351 
    352     /** @name Geometry
    353       * @{ */
    354         /** Holds the cached parent geometry. */
    355         QRect m_rect;
    356         /** Holds the cached status-bar geometry. */
    357         QRect m_statusBarRect;
    358     /** @} */
    359 
    360     /** @name Geometry: Animation
    361       * @{ */
    362         /** Holds the expand/collapse animation instance. */
    363         UIAnimation *m_pAnimation;
    364         /** Holds whether window is expanded. */
    365         bool m_fExpanded;
    366         /** Holds the cached start-geometry. */
    367         QRect m_startGeometry;
    368         /** Holds the cached final-geometry. */
    369         QRect m_finalGeometry;
    370     /** @} */
    371 
    372     /** @name Contents
    373       * @{ */
    374         /** Holds the main-layout instance. */
    375         QHBoxLayout *m_pMainLayout;
    376         /** Holds the button-layout instance. */
    377         QHBoxLayout *m_pButtonLayout;
    378         /** Holds the close-button instance. */
    379         QIToolButton *m_pButtonClose;
    380         /** Holds status-bar buttons. */
    381         QMap<IndicatorType, UIStatusBarEditorButton*> m_buttons;
    382     /** @} */
    383 
    384     /** @name Contents: Restrictions
    385       * @{ */
    386         /** Holds the cached status-bar button restrictions. */
    387         QList<IndicatorType> m_restrictions;
    388     /** @} */
    389 
    390     /** @name Contents: Order
    391       * @{ */
    392         /** Holds the cached status-bar button order. */
    393         QList<IndicatorType> m_order;
    394         /** Holds the token-button to drop dragged-button nearby. */
    395         UIStatusBarEditorButton *m_pButtonDropToken;
    396         /** Holds whether dragged-button should be dropped <b>after</b> the token-button. */
    397         bool m_fDropAfterTokenButton;
    398     /** @} */
    399 };
    400232
    401233UIStatusBarEditorWindow::UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect)
     
    889721}
    890722
    891 
    892 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId)
    893     : UIMachineWindow(pMachineLogic, uScreenId)
    894     , m_pIndicatorsPool(0)
    895 {
    896 }
    897 
    898 void UIMachineWindowNormal::sltMachineStateChanged()
    899 {
    900     /* Call to base-class: */
    901     UIMachineWindow::sltMachineStateChanged();
    902 
    903     /* Update pause and virtualization stuff: */
    904     updateAppearanceOf(UIVisualElement_PauseStuff | UIVisualElement_FeaturesStuff);
    905 }
    906 
    907 void UIMachineWindowNormal::sltMediumChange(const CMediumAttachment &attachment)
    908 {
    909     /* Update corresponding medium stuff: */
    910     KDeviceType type = attachment.GetType();
    911     if (type == KDeviceType_HardDisk)
    912         updateAppearanceOf(UIVisualElement_HDStuff);
    913     if (type == KDeviceType_DVD)
    914         updateAppearanceOf(UIVisualElement_CDStuff);
    915     if (type == KDeviceType_Floppy)
    916         updateAppearanceOf(UIVisualElement_FDStuff);
    917 }
    918 
    919 void UIMachineWindowNormal::sltUSBControllerChange()
    920 {
    921     /* Update USB stuff: */
    922     updateAppearanceOf(UIVisualElement_USBStuff);
    923 }
    924 
    925 void UIMachineWindowNormal::sltUSBDeviceStateChange()
    926 {
    927     /* Update USB stuff: */
    928     updateAppearanceOf(UIVisualElement_USBStuff);
    929 }
    930 
    931 void UIMachineWindowNormal::sltNetworkAdapterChange()
    932 {
    933     /* Update network stuff: */
    934     updateAppearanceOf(UIVisualElement_NetworkStuff);
    935 }
    936 
    937 void UIMachineWindowNormal::sltSharedFolderChange()
    938 {
    939     /* Update shared-folders stuff: */
    940     updateAppearanceOf(UIVisualElement_SharedFolderStuff);
    941 }
    942 
    943 void UIMachineWindowNormal::sltVideoCaptureChange()
    944 {
    945     /* Update video-capture stuff: */
    946     updateAppearanceOf(UIVisualElement_VideoCapture);
    947 }
    948 
    949 void UIMachineWindowNormal::sltCPUExecutionCapChange()
    950 {
    951     /* Update virtualization stuff: */
    952     updateAppearanceOf(UIVisualElement_FeaturesStuff);
    953 }
    954 
    955 void UIMachineWindowNormal::sltShowStatusBarContextMenu(const QPoint &position)
    956 {
    957     /* Prepare context-menu: */
    958     QMenu menu;
    959     /* Having just one action to configure status-bar: */
    960     QAction *pAction = menu.addAction(UIIconPool::iconSet(":/vm_settings_16px.png"),
    961                                       tr("Configure status-bar..."),
    962                                       this, SLOT(sltOpenStatusBarEditorWindow()));
    963     pAction->setEnabled(!uisession()->property("StatusBarEditorOpened").toBool());
    964     /* Execute context-menu: */
    965     menu.exec(statusBar()->mapToGlobal(position));
    966 }
    967 
    968 void UIMachineWindowNormal::sltOpenStatusBarEditorWindow()
    969 {
    970     /* Prevent user from opening another one editor: */
    971     uisession()->setProperty("StatusBarEditorOpened", true);
    972     /* Create status-bar editor: */
    973     UIStatusBarEditorWindow *pStatusBarEditor =
    974         new UIStatusBarEditorWindow(this, m_normalGeometry, statusBar()->geometry());
    975     AssertPtrReturnVoid(pStatusBarEditor);
    976     {
    977         /* Configure status-bar editor: */
    978         connect(this, SIGNAL(sigGeometryChange(const QRect&)),
    979                 pStatusBarEditor, SLOT(sltParentGeometryChanged(const QRect&)));
    980         connect(pStatusBarEditor, SIGNAL(destroyed(QObject*)),
    981                 this, SLOT(sltStatusBarEditorWindowClosed()));
    982 #ifdef Q_WS_MAC
    983         connect(machineLogic(), SIGNAL(sigNotifyAbout3DOverlayVisibilityChange(bool)),
    984                 pStatusBarEditor, SLOT(sltActivateWindow()));
    985 #endif /* Q_WS_MAC */
    986         /* Show window: */
    987         pStatusBarEditor->show();
    988     }
    989 }
    990 
    991 void UIMachineWindowNormal::sltStatusBarEditorWindowClosed()
    992 {
    993     /* Allow user to open editor again: */
    994     uisession()->setProperty("StatusBarEditorOpened", QVariant());
    995 }
    996 
    997 void UIMachineWindowNormal::sltHandleIndicatorContextMenuRequest(IndicatorType indicatorType, const QPoint &position)
    998 {
    999     /* Determine action depending on indicator-type: */
    1000     UIAction *pAction = 0;
    1001     switch (indicatorType)
    1002     {
    1003         case IndicatorType_HardDisks:     pAction = gActionPool->action(UIActionIndexRuntime_Menu_HardDisks);        break;
    1004         case IndicatorType_OpticalDisks:  pAction = gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices);   break;
    1005         case IndicatorType_FloppyDisks:   pAction = gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices);    break;
    1006         case IndicatorType_USB:           pAction = gActionPool->action(UIActionIndexRuntime_Menu_USBDevices);       break;
    1007         case IndicatorType_Network:       pAction = gActionPool->action(UIActionIndexRuntime_Menu_Network);          break;
    1008         case IndicatorType_SharedFolders: pAction = gActionPool->action(UIActionIndexRuntime_Menu_SharedFolders);    break;
    1009         case IndicatorType_VideoCapture:  pAction = gActionPool->action(UIActionIndexRuntime_Menu_VideoCapture);     break;
    1010         case IndicatorType_Mouse:         pAction = gActionPool->action(UIActionIndexRuntime_Menu_MouseIntegration); break;
    1011         case IndicatorType_Keyboard:      pAction = gActionPool->action(UIActionIndexRuntime_Menu_Keyboard);         break;
    1012         default: break;
    1013     }
    1014     /* Raise action's context-menu: */
    1015     if (pAction && pAction->isEnabled())
    1016         pAction->menu()->exec(position);
    1017 }
    1018 
    1019 void UIMachineWindowNormal::prepareSessionConnections()
    1020 {
    1021     /* Call to base-class: */
    1022     UIMachineWindow::prepareSessionConnections();
    1023 
    1024     /* Medium change updater: */
    1025     connect(machineLogic()->uisession(), SIGNAL(sigMediumChange(const CMediumAttachment &)),
    1026             this, SLOT(sltMediumChange(const CMediumAttachment &)));
    1027 
    1028     /* USB controller change updater: */
    1029     connect(machineLogic()->uisession(), SIGNAL(sigUSBControllerChange()),
    1030             this, SLOT(sltUSBControllerChange()));
    1031 
    1032     /* USB device state-change updater: */
    1033     connect(machineLogic()->uisession(), SIGNAL(sigUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &)),
    1034             this, SLOT(sltUSBDeviceStateChange()));
    1035 
    1036     /* Network adapter change updater: */
    1037     connect(machineLogic()->uisession(), SIGNAL(sigNetworkAdapterChange(const CNetworkAdapter &)),
    1038             this, SLOT(sltNetworkAdapterChange()));
    1039 
    1040     /* Shared folder change updater: */
    1041     connect(machineLogic()->uisession(), SIGNAL(sigSharedFolderChange()),
    1042             this, SLOT(sltSharedFolderChange()));
    1043 
    1044     /* Video capture change updater: */
    1045     connect(machineLogic()->uisession(), SIGNAL(sigVideoCaptureChange()),
    1046             this, SLOT(sltVideoCaptureChange()));
    1047 
    1048     /* CPU execution cap change updater: */
    1049     connect(machineLogic()->uisession(), SIGNAL(sigCPUExecutionCapChange()),
    1050             this, SLOT(sltCPUExecutionCapChange()));
    1051 }
    1052 
    1053 void UIMachineWindowNormal::prepareMenu()
    1054 {
    1055     /* Call to base-class: */
    1056     UIMachineWindow::prepareMenu();
    1057 
    1058 #ifndef Q_WS_MAC
    1059     /* Prepare application menu-bar: */
    1060     RuntimeMenuType restrictedMenus = gEDataManager->restrictedRuntimeMenuTypes(vboxGlobal().managedVMUuid());
    1061     RuntimeMenuType allowedMenus = static_cast<RuntimeMenuType>(RuntimeMenuType_All ^ restrictedMenus);
    1062     setMenuBar(uisession()->newMenuBar(allowedMenus));
    1063 #endif /* !Q_WS_MAC */
    1064 }
    1065 
    1066 void UIMachineWindowNormal::prepareStatusBar()
    1067 {
    1068     /* Call to base-class: */
    1069     UIMachineWindow::prepareStatusBar();
    1070 
    1071     /* Create status-bar: */
    1072     setStatusBar(new QIStatusBar);
    1073     AssertPtrReturnVoid(statusBar());
    1074     {
    1075         /* Configure status-bar: */
    1076         statusBar()->setContextMenuPolicy(Qt::CustomContextMenu);
    1077         connect(statusBar(), SIGNAL(customContextMenuRequested(const QPoint&)),
    1078                 this, SLOT(sltShowStatusBarContextMenu(const QPoint&)));
    1079         /* Create indicator-pool: */
    1080         m_pIndicatorsPool = new UIIndicatorsPool(machineLogic()->uisession());
    1081         AssertPtrReturnVoid(m_pIndicatorsPool);
    1082         {
    1083             /* Configure indicator-pool: */
    1084             connect(m_pIndicatorsPool, SIGNAL(sigContextMenuRequest(IndicatorType, const QPoint&)),
    1085                     this, SLOT(sltHandleIndicatorContextMenuRequest(IndicatorType, const QPoint&)));
    1086             /* Add indicator-pool into status-bar: */
    1087             statusBar()->addPermanentWidget(m_pIndicatorsPool, 0);
    1088         }
    1089     }
    1090 
    1091 #ifdef Q_WS_MAC
    1092     /* For the status-bar on Cocoa: */
    1093     setUnifiedTitleAndToolBarOnMac(true);
    1094 #endif /* Q_WS_MAC */
    1095 }
    1096 
    1097 void UIMachineWindowNormal::prepareVisualState()
    1098 {
    1099     /* Call to base-class: */
    1100     UIMachineWindow::prepareVisualState();
    1101 
    1102 #ifdef VBOX_GUI_WITH_CUSTOMIZATIONS1
    1103     /* The background has to go black: */
    1104     QPalette palette(centralWidget()->palette());
    1105     palette.setColor(centralWidget()->backgroundRole(), Qt::black);
    1106     centralWidget()->setPalette(palette);
    1107     centralWidget()->setAutoFillBackground(true);
    1108     setAutoFillBackground(true);
    1109 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */
    1110 
    1111 #ifdef Q_WS_MAC
    1112     /* Beta label? */
    1113     if (vboxGlobal().isBeta())
    1114     {
    1115         QPixmap betaLabel = ::betaLabel(QSize(100, 16));
    1116         ::darwinLabelWindow(this, &betaLabel, true);
    1117     }
    1118 #endif /* Q_WS_MAC */
    1119 }
    1120 
    1121 void UIMachineWindowNormal::loadSettings()
    1122 {
    1123     /* Call to base-class: */
    1124     UIMachineWindow::loadSettings();
    1125 
    1126     /* Get machine: */
    1127     CMachine m = machine();
    1128 
    1129     /* Load GUI customizations: */
    1130     {
    1131         VBoxGlobalSettings settings = vboxGlobal().settings();
    1132 #ifndef Q_WS_MAC
    1133         menuBar()->setHidden(settings.isFeatureActive("noMenuBar"));
    1134 #endif /* !Q_WS_MAC */
    1135         statusBar()->setHidden(settings.isFeatureActive("noStatusBar"));
    1136         if (statusBar()->isHidden())
    1137             m_pIndicatorsPool->setAutoUpdateIndicatorStates(false);
    1138     }
    1139 
    1140     /* Load window geometry: */
    1141     {
    1142         /* Load extra-data: */
    1143         QRect geo = gEDataManager->machineWindowGeometry(machineLogic()->visualStateType(),
    1144                                                          m_uScreenId, vboxGlobal().managedVMUuid());
    1145 
    1146         /* If we do have proper geometry: */
    1147         if (!geo.isNull())
    1148         {
    1149             /* If previous machine-state was SAVED: */
    1150             if (m.GetState() == KMachineState_Saved)
    1151             {
    1152                 /* Restore window geometry: */
    1153                 m_normalGeometry = geo;
    1154                 setGeometry(m_normalGeometry);
    1155             }
    1156             /* If previous machine-state was NOT SAVED: */
    1157             else
    1158             {
    1159                 /* Restore only window position: */
    1160                 m_normalGeometry = QRect(geo.x(), geo.y(), width(), height());
    1161                 setGeometry(m_normalGeometry);
    1162                 /* And normalize to the optimal-size: */
    1163                 normalizeGeometry(false);
    1164             }
    1165 
    1166             /* Maximize (if necessary): */
    1167             if (gEDataManager->machineWindowShouldBeMaximized(machineLogic()->visualStateType(),
    1168                                                               m_uScreenId, vboxGlobal().managedVMUuid()))
    1169                 setWindowState(windowState() | Qt::WindowMaximized);
    1170         }
    1171         /* If we do NOT have proper geometry: */
    1172         else
    1173         {
    1174             /* Get available geometry, for screen with (x,y) coords if possible: */
    1175             QRect availableGeo = !geo.isNull() ? QApplication::desktop()->availableGeometry(QPoint(geo.x(), geo.y())) :
    1176                                                  QApplication::desktop()->availableGeometry(this);
    1177 
    1178             /* Normalize to the optimal size: */
    1179             normalizeGeometry(true);
    1180             /* Move newly created window to the screen-center: */
    1181             m_normalGeometry = geometry();
    1182             m_normalGeometry.moveCenter(availableGeo.center());
    1183             setGeometry(m_normalGeometry);
    1184         }
    1185 
    1186         /* Normalize to the optimal size: */
    1187 #ifdef Q_WS_X11
    1188         QTimer::singleShot(0, this, SLOT(sltNormalizeGeometry()));
    1189 #else /* !Q_WS_X11 */
    1190         normalizeGeometry(true);
    1191 #endif /* !Q_WS_X11 */
    1192     }
    1193 }
    1194 
    1195 void UIMachineWindowNormal::saveSettings()
    1196 {
    1197     /* Save window geometry: */
    1198     {
    1199         gEDataManager->setMachineWindowGeometry(machineLogic()->visualStateType(),
    1200                                                 m_uScreenId, m_normalGeometry,
    1201                                                 isMaximizedChecked(), vboxGlobal().managedVMUuid());
    1202     }
    1203 
    1204     /* Call to base-class: */
    1205     UIMachineWindow::saveSettings();
    1206 }
    1207 
    1208 bool UIMachineWindowNormal::event(QEvent *pEvent)
    1209 {
    1210     switch (pEvent->type())
    1211     {
    1212         case QEvent::Resize:
    1213         {
    1214             QResizeEvent *pResizeEvent = static_cast<QResizeEvent*>(pEvent);
    1215             if (!isMaximizedChecked())
    1216             {
    1217                 m_normalGeometry.setSize(pResizeEvent->size());
    1218                 emit sigGeometryChange(m_normalGeometry);
    1219 #ifdef VBOX_WITH_DEBUGGER_GUI
    1220                 /* Update debugger window position: */
    1221                 updateDbgWindows();
    1222 #endif /* VBOX_WITH_DEBUGGER_GUI */
    1223             }
    1224             break;
    1225         }
    1226         case QEvent::Move:
    1227         {
    1228             if (!isMaximizedChecked())
    1229             {
    1230                 m_normalGeometry.moveTo(geometry().x(), geometry().y());
    1231                 emit sigGeometryChange(m_normalGeometry);
    1232 #ifdef VBOX_WITH_DEBUGGER_GUI
    1233                 /* Update debugger window position: */
    1234                 updateDbgWindows();
    1235 #endif /* VBOX_WITH_DEBUGGER_GUI */
    1236             }
    1237             break;
    1238         }
    1239         case QEvent::WindowActivate:
    1240             emit sigGeometryChange(m_normalGeometry);
    1241             break;
    1242         default:
    1243             break;
    1244     }
    1245     return UIMachineWindow::event(pEvent);
    1246 }
    1247 
    1248 void UIMachineWindowNormal::showInNecessaryMode()
    1249 {
    1250     /* Make sure this window should be shown at all: */
    1251     if (!uisession()->isScreenVisible(m_uScreenId))
    1252         return hide();
    1253 
    1254     /* Make sure this window is not minimized: */
    1255     if (isMinimized())
    1256         return;
    1257 
    1258     /* Show in normal mode: */
    1259     show();
    1260 }
    1261 
    1262 /**
    1263  * Adjusts machine-window size to correspond current guest screen size.
    1264  * @param fAdjustPosition determines whether is it necessary to adjust position too.
    1265  */
    1266 void UIMachineWindowNormal::normalizeGeometry(bool fAdjustPosition)
    1267 {
    1268 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS1
    1269     /* Skip if maximized: */
    1270     if (isMaximized())
    1271         return;
    1272 
    1273     /* Calculate client window offsets: */
    1274     QRect frameGeo = frameGeometry();
    1275     QRect geo = geometry();
    1276     int dl = geo.left() - frameGeo.left();
    1277     int dt = geo.top() - frameGeo.top();
    1278     int dr = frameGeo.right() - geo.right();
    1279     int db = frameGeo.bottom() - geo.bottom();
    1280 
    1281     /* Get the best size w/o scroll-bars: */
    1282     QSize s = sizeHint();
    1283 
    1284     /* Resize the frame to fit the contents: */
    1285     s -= size();
    1286     frameGeo.setRight(frameGeo.right() + s.width());
    1287     frameGeo.setBottom(frameGeo.bottom() + s.height());
    1288 
    1289     /* Adjust position if necessary: */
    1290     if (fAdjustPosition)
    1291     {
    1292         QRegion availableGeo;
    1293         QDesktopWidget *dwt = QApplication::desktop();
    1294         if (dwt->isVirtualDesktop())
    1295             /* Compose complex available region: */
    1296             for (int i = 0; i < dwt->numScreens(); ++i)
    1297                 availableGeo += dwt->availableGeometry(i);
    1298         else
    1299             /* Get just a simple available rectangle */
    1300             availableGeo = dwt->availableGeometry(pos());
    1301 
    1302         frameGeo = VBoxGlobal::normalizeGeometry(frameGeo, availableGeo);
    1303     }
    1304 
    1305     /* Finally, set the frame geometry: */
    1306     setGeometry(frameGeo.left() + dl, frameGeo.top() + dt,
    1307                 frameGeo.width() - dl - dr, frameGeo.height() - dt - db);
    1308 
    1309 #else /* !VBOX_GUI_WITH_CUSTOMIZATIONS1 */
    1310     Q_UNUSED(fAdjustPosition);
    1311 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */
    1312 }
    1313 
    1314 void UIMachineWindowNormal::updateAppearanceOf(int iElement)
    1315 {
    1316     /* Call to base-class: */
    1317     UIMachineWindow::updateAppearanceOf(iElement);
    1318 
    1319     /* Update machine window content: */
    1320     if (iElement & UIVisualElement_PauseStuff)
    1321     {
    1322         if (!statusBar()->isHidden())
    1323         {
    1324             if (uisession()->isPaused())
    1325                 m_pIndicatorsPool->setAutoUpdateIndicatorStates(false);
    1326             else if (uisession()->isRunning())
    1327                 m_pIndicatorsPool->setAutoUpdateIndicatorStates(true);
    1328         }
    1329     }
    1330     if (iElement & UIVisualElement_HDStuff)
    1331         m_pIndicatorsPool->updateAppearance(IndicatorType_HardDisks);
    1332     if (iElement & UIVisualElement_CDStuff)
    1333         m_pIndicatorsPool->updateAppearance(IndicatorType_OpticalDisks);
    1334     if (iElement & UIVisualElement_FDStuff)
    1335         m_pIndicatorsPool->updateAppearance(IndicatorType_FloppyDisks);
    1336     if (iElement & UIVisualElement_NetworkStuff)
    1337         m_pIndicatorsPool->updateAppearance(IndicatorType_Network);
    1338     if (iElement & UIVisualElement_USBStuff)
    1339         m_pIndicatorsPool->updateAppearance(IndicatorType_USB);
    1340     if (iElement & UIVisualElement_SharedFolderStuff)
    1341         m_pIndicatorsPool->updateAppearance(IndicatorType_SharedFolders);
    1342     if (iElement & UIVisualElement_VideoCapture)
    1343         m_pIndicatorsPool->updateAppearance(IndicatorType_VideoCapture);
    1344     if (iElement & UIVisualElement_FeaturesStuff)
    1345         m_pIndicatorsPool->updateAppearance(IndicatorType_Features);
    1346 }
    1347 
    1348 bool UIMachineWindowNormal::isMaximizedChecked()
    1349 {
    1350 #ifdef Q_WS_MAC
    1351     /* On the Mac the WindowStateChange signal doesn't seems to be delivered
    1352      * when the user get out of the maximized state. So check this ourself. */
    1353     return ::darwinIsWindowMaximized(this);
    1354 #else /* Q_WS_MAC */
    1355     return isMaximized();
    1356 #endif /* !Q_WS_MAC */
    1357 }
    1358 
    1359 #include "UIMachineWindowNormal.moc"
    1360 
     723#include "UIStatusBarEditorWindow.moc"
     724
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIStatusBarEditorWindow.h

    r52064 r52070  
    1 /* $Id$ */
    21/** @file
    3  *
    4  * VBox frontends: Qt GUI ("VirtualBox"):
    5  * UIMachineWindowNormal class implementation
     2 * VBox Qt GUI - UIStatusBarEditorWindow class declaration.
    63 */
    74
    85/*
    9  * Copyright (C) 2010-2012 Oracle Corporation
     6 * Copyright (C) 2010-2014 Oracle Corporation
    107 *
    118 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1815 */
    1916
     17#ifndef ___UIStatusBarEditorWindow_h___
     18#define ___UIStatusBarEditorWindow_h___
     19
    2020/* Qt includes: */
    21 #include <QDesktopWidget>
    22 #include <QMenuBar>
    23 #include <QTimer>
    24 #include <QContextMenuEvent>
    25 #include <QResizeEvent>
    26 
    27 #include <QStylePainter>
    28 #include <QStyleOption>
    29 #include <QPaintEvent>
    30 #include <QPainter>
    31 #include <QDrag>
     21#include <QWidget>
     22#include <QList>
     23#include <QMap>
    3224
    3325/* GUI includes: */
    34 #include "VBoxGlobal.h"
    35 #include "UIExtraDataManager.h"
    36 #include "UISession.h"
    37 #include "UIActionPoolRuntime.h"
    38 #include "UIIndicatorsPool.h"
    39 #include "UIKeyboardHandler.h"
    40 #include "UIMouseHandler.h"
    41 #include "UIMachineLogic.h"
    42 #include "UIMachineWindowNormal.h"
    43 #include "UIMachineView.h"
    44 #include "QIStatusBar.h"
    45 #include "QIStatusBarIndicator.h"
    46 #ifdef Q_WS_MAC
    47 # include "VBoxUtils.h"
    48 # include "UIImageTools.h"
    49 #endif /* Q_WS_MAC */
     26#include "QIWithRetranslateUI.h"
     27#include "UIExtraDataDefs.h"
    5028
    51 #include "QIWithRetranslateUI.h"
    52 #include "QIToolButton.h"
    53 #include "UIIconPool.h"
    54 #include "UIConverter.h"
    55 #include "UIAnimationFramework.h"
    56 
    57 /* COM includes: */
    58 #include "CConsole.h"
    59 #include "CMediumAttachment.h"
    60 #include "CUSBController.h"
    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     /* Revoke hovered state: */
    242     m_fHovered = false;
    243     /* Update: */
    244     update();
    245 
    246     /* Initialize dragging: */
    247     m_mousePressPosition = QPoint();
    248     QDrag *pDrag = new QDrag(this);
    249     connect(pDrag, SIGNAL(destroyed(QObject*)), this, SIGNAL(sigDragObjectDestroy()));
    250     QMimeData *pMimeData = new QMimeData;
    251     pMimeData->setData(MimeType, gpConverter->toInternalString(m_type).toLatin1());
    252     pDrag->setMimeData(pMimeData);
    253     pDrag->setPixmap(m_pixmap);
    254     pDrag->exec();
    255 }
    256 
     29/* Forward declarations: */
     30class UIAnimation;
     31class QHBoxLayout;
     32class QIToolButton;
     33class UIStatusBarEditorButton;
    25734
    25835/** QWidget reimplementation
     
    399176};
    400177
    401 UIStatusBarEditorWindow::UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect)
    402     : QIWithRetranslateUI2<QWidget>(pParent, Qt::Tool | Qt::FramelessWindowHint)
    403     , m_rect(rect), m_statusBarRect(statusBarRect)
    404     , m_pAnimation(0), m_fExpanded(false)
    405     , m_pMainLayout(0), m_pButtonLayout(0)
    406     , m_pButtonClose(0)
    407     , m_pButtonDropToken(0)
    408     , m_fDropAfterTokenButton(true)
    409 {
    410     /* Prepare: */
    411     prepare();
    412 }
    413 
    414 void UIStatusBarEditorWindow::sltParentGeometryChanged(const QRect &rect)
    415 {
    416     /* Update rectangle: */
    417     m_rect = rect;
    418     /* Update animation: */
    419     updateAnimation();
    420     /* Adjust geometry: */
    421     adjustGeometry();
    422 }
    423 
    424 void UIStatusBarEditorWindow::sltHandleConfigurationChange()
    425 {
    426     /* Update status buttons: */
    427     updateStatusButtons();
    428 }
    429 
    430 void UIStatusBarEditorWindow::sltHandleButtonClick()
    431 {
    432     /* Make sure sender is valid: */
    433     UIStatusBarEditorButton *pButton = qobject_cast<UIStatusBarEditorButton*>(sender());
    434     AssertPtrReturnVoid(pButton);
    435 
    436     /* Get sender type: */
    437     const IndicatorType type = pButton->type();
    438 
    439     /* Load current status-bar indicator restrictions: */
    440     QList<IndicatorType> restrictions =
    441         gEDataManager->restrictedStatusBarIndicators(vboxGlobal().managedVMUuid());
    442 
    443     /* Invert restriction for sender type: */
    444     if (restrictions.contains(type))
    445         restrictions.removeAll(type);
    446     else
    447         restrictions.append(type);
    448 
    449     /* Save updated status-bar indicator restrictions: */
    450     gEDataManager->setRestrictedStatusBarIndicators(restrictions, vboxGlobal().managedVMUuid());
    451 }
    452 
    453 void UIStatusBarEditorWindow::sltHandleDragObjectDestroy()
    454 {
    455     /* Reset token: */
    456     m_pButtonDropToken = 0;
    457     m_fDropAfterTokenButton = true;
    458     /* Update: */
    459     update();
    460 }
    461 
    462 void UIStatusBarEditorWindow::prepare()
    463 {
    464     /* Do not count that window as important for application,
    465      * it will NOT be taken into account when other top-level windows will be closed: */
    466     setAttribute(Qt::WA_QuitOnClose, false);
    467     /* Delete window when closed: */
    468     setAttribute(Qt::WA_DeleteOnClose);
    469 #if defined(Q_WS_MAC) || defined(Q_WS_WIN)
    470     /* Make sure we have no background
    471      * until the first one paint-event: */
    472     setAttribute(Qt::WA_NoSystemBackground);
    473 #endif /* Q_WS_MAC || Q_WS_WIN */
    474 #if defined(Q_WS_MAC)
    475     /* Using native API to enable translucent background for the Mac host.
    476      * - We also want to disable window-shadows which is possible
    477      *   using Qt::WA_MacNoShadow only since Qt 4.8,
    478      *   while minimum supported version is 4.7.1 for now: */
    479     ::darwinSetShowsWindowTransparent(this, true);
    480 #elif defined(Q_WS_WIN)
    481     /* Using Qt API to enable translucent background:
    482      * - Under Win host Qt conflicts with 3D stuff (black seamless regions).
    483      * - Under Mac host Qt doesn't allows to disable window-shadows
    484      *   until version 4.8, but minimum supported version is 4.7.1 for now.
    485      * - Under x11 host Qt has it broken with KDE 4.9 (black background): */
    486     setAttribute(Qt::WA_TranslucentBackground);
    487 #endif /* Q_WS_WIN */
    488     /* Track D&D events: */
    489     setAcceptDrops(true);
    490 
    491     /* Create main-layout: */
    492     m_pMainLayout = new QHBoxLayout(this);
    493     AssertPtrReturnVoid(m_pMainLayout);
    494     {
    495         /* Configure main-layout: */
    496 #ifdef Q_WS_MAC
    497         /* Standard margins on Mac OS X are too big: */
    498         m_pMainLayout->setContentsMargins(10, 10, 10, 5);
    499 #else /* !Q_WS_MAC */
    500         /* Standard margins on Windows/X11: */
    501         int iLeft, iTop, iRight, iBottom;
    502         m_pMainLayout->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
    503         if (iBottom >= 5)
    504             iBottom -= 5;
    505         m_pMainLayout->setContentsMargins(iLeft, iTop, iRight, iBottom);
    506 #endif /* !Q_WS_MAC */
    507         m_pMainLayout->setSpacing(0);
    508         /* Create close-button: */
    509         m_pButtonClose = new QIToolButton;
    510         AssertPtrReturnVoid(m_pButtonClose);
    511         {
    512             /* Configure close-button: */
    513             m_pButtonClose->setFocusPolicy(Qt::StrongFocus);
    514             m_pButtonClose->setMinimumSize(QSize(1, 1));
    515             m_pButtonClose->setShortcut(Qt::Key_Escape);
    516             m_pButtonClose->setIcon(UIIconPool::iconSet(":/ok_16px.png"));
    517             connect(m_pButtonClose, SIGNAL(clicked(bool)), this, SLOT(close()));
    518             /* Add close-button into main-layout: */
    519             m_pMainLayout->addWidget(m_pButtonClose);
    520         }
    521         /* Insert stretch: */
    522         m_pMainLayout->addStretch();
    523         /* Create button-layout: */
    524         m_pButtonLayout = new QHBoxLayout;
    525         AssertPtrReturnVoid(m_pButtonLayout);
    526         {
    527             /* Configure button-layout: */
    528             m_pButtonLayout->setContentsMargins(0, 0, 0, 0);
    529             m_pButtonLayout->setSpacing(5);
    530             /* Add button-layout into main-layout: */
    531             m_pMainLayout->addLayout(m_pButtonLayout);
    532         }
    533         /* Prepare status buttons: */
    534         prepareStatusButtons();
    535     }
    536 
    537     /* Translate contents: */
    538     retranslateUi();
    539 
    540     /* Prepare animation: */
    541     prepareAnimation();
    542     /* Prepare geometry: */
    543     prepareGeometry();
    544 }
    545 
    546 void UIStatusBarEditorWindow::prepareStatusButtons()
    547 {
    548     /* Create status buttons: */
    549     for (int i = IndicatorType_Invalid; i < IndicatorType_Max; ++i)
    550     {
    551         /* Get current type: */
    552         const IndicatorType type = (IndicatorType)i;
    553         /* Skip inappropriate types: */
    554         if (type == IndicatorType_Invalid || type == IndicatorType_KeyboardExtension)
    555             continue;
    556         /* Create status button: */
    557         prepareStatusButton(type);
    558     }
    559 
    560     /* Listen for the status-bar configuration changes: */
    561     connect(gEDataManager, SIGNAL(sigStatusBarConfigurationChange()),
    562             this, SLOT(sltHandleConfigurationChange()));
    563     /* Update status buttons: */
    564     updateStatusButtons();
    565 }
    566 
    567 void UIStatusBarEditorWindow::prepareStatusButton(IndicatorType type)
    568 {
    569     /* Create status button: */
    570     UIStatusBarEditorButton *pButton = new UIStatusBarEditorButton(type);
    571     AssertPtrReturnVoid(pButton);
    572     {
    573         /* Configure status button: */
    574         connect(pButton, SIGNAL(sigClick()), this, SLOT(sltHandleButtonClick()));
    575         connect(pButton, SIGNAL(sigDragObjectDestroy()), this, SLOT(sltHandleDragObjectDestroy()));
    576         /* Add status button into button-layout: */
    577         m_pButtonLayout->addWidget(pButton);
    578         /* Insert status button into map: */
    579         m_buttons.insert(type, pButton);
    580     }
    581 }
    582 
    583 void UIStatusBarEditorWindow::prepareAnimation()
    584 {
    585     /* Prepare geometry animation itself: */
    586     connect(this, SIGNAL(sigShown()), this, SIGNAL(sigExpand()), Qt::QueuedConnection);
    587     m_pAnimation = UIAnimation::installPropertyAnimation(this, "geometry", "startGeometry", "finalGeometry",
    588                                                          SIGNAL(sigExpand()), SIGNAL(sigCollapse()));
    589     connect(m_pAnimation, SIGNAL(sigStateEnteredStart()), this, SLOT(sltMarkAsCollapsed()));
    590     connect(m_pAnimation, SIGNAL(sigStateEnteredFinal()), this, SLOT(sltMarkAsExpanded()));
    591     /* Update animation: */
    592     updateAnimation();
    593 }
    594 
    595 void UIStatusBarEditorWindow::prepareGeometry()
    596 {
    597     /* Prepare geometry based on minimum size-hint: */
    598     connect(this, SIGNAL(sigShown()), this, SLOT(sltActivateWindow()), Qt::QueuedConnection);
    599     const QSize msh = minimumSizeHint();
    600     setGeometry(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - msh.height(),
    601                 qMax(m_rect.width(), msh.width()), msh.height());
    602 #ifdef Q_WS_WIN
    603     raise();
    604 #endif /* Q_WS_WIN */
    605 }
    606 
    607 void UIStatusBarEditorWindow::updateStatusButtons()
    608 {
    609     /* Recache status-bar configuration: */
    610     m_restrictions = gEDataManager->restrictedStatusBarIndicators(vboxGlobal().managedVMUuid());
    611     m_order = gEDataManager->statusBarIndicatorOrder(vboxGlobal().managedVMUuid());
    612     for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
    613         if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension &&
    614             !m_order.contains((IndicatorType)iType))
    615             m_order << (IndicatorType)iType;
    616 
    617     /* Update configuration for all the status buttons: */
    618     foreach (const IndicatorType &type, m_order)
    619     {
    620         /* Get button: */
    621         UIStatusBarEditorButton *pButton = m_buttons.value(type);
    622         /* Update button 'checked' state: */
    623         pButton->setChecked(!m_restrictions.contains(type));
    624         /* Make sure it have valid position: */
    625         const int iWantedIndex = position(type);
    626         const int iActualIndex = m_pButtonLayout->indexOf(pButton);
    627         if (iActualIndex != iWantedIndex)
    628         {
    629             /* Re-inject button into main-layout at proper position: */
    630             m_pButtonLayout->removeWidget(pButton);
    631             m_pButtonLayout->insertWidget(iWantedIndex, pButton);
    632         }
    633     }
    634 }
    635 
    636 void UIStatusBarEditorWindow::updateAnimation()
    637 {
    638     /* Calculate geometry animation boundaries
    639      * based on size-hint and minimum size-hint: */
    640     const QSize sh = sizeHint();
    641     const QSize msh = minimumSizeHint();
    642     m_startGeometry = QRect(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - msh.height(),
    643                             qMax(m_rect.width(), msh.width()), msh.height());
    644     m_finalGeometry = QRect(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - sh.height(),
    645                             qMax(m_rect.width(), sh.width()), sh.height());
    646     m_pAnimation->update();
    647 }
    648 
    649 void UIStatusBarEditorWindow::adjustGeometry()
    650 {
    651     /* Adjust geometry based on size-hint: */
    652     const QSize sh = sizeHint();
    653     setGeometry(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - sh.height(),
    654                 qMax(m_rect.width(), sh.width()), sh.height());
    655 #ifdef Q_WS_WIN
    656     raise();
    657 #endif /* Q_WS_WIN */
    658 }
    659 
    660 void UIStatusBarEditorWindow::retranslateUi()
    661 {
    662     /* Translate close-button: */
    663     m_pButtonClose->setToolTip(tr("Close"));
    664 }
    665 
    666 void UIStatusBarEditorWindow::showEvent(QShowEvent*)
    667 {
    668     /* If window isn't expanded: */
    669     if (!m_fExpanded)
    670     {
    671         /* Start expand animation: */
    672         emit sigShown();
    673     }
    674 }
    675 
    676 void UIStatusBarEditorWindow::closeEvent(QCloseEvent *pEvent)
    677 {
    678     /* If window isn't expanded: */
    679     if (!m_fExpanded)
    680     {
    681         /* Ignore close-event: */
    682         pEvent->ignore();
    683         return;
    684     }
    685 
    686     /* If animation state is Final: */
    687     const QString strAnimationState = property("AnimationState").toString();
    688     bool fAnimationComplete = strAnimationState == "Final";
    689     if (fAnimationComplete)
    690     {
    691         /* Ignore close-event: */
    692         pEvent->ignore();
    693         /* And start collapse animation: */
    694         emit sigCollapse();
    695     }
    696 }
    697 
    698 void UIStatusBarEditorWindow::paintEvent(QPaintEvent*)
    699 {
    700     /* Prepare painter: */
    701     QPainter painter(this);
    702 
    703     /* Prepare palette colors: */
    704     const QPalette pal = palette();
    705     QColor color0 = pal.color(QPalette::Window);
    706     QColor color1 = pal.color(QPalette::Window).lighter(110);
    707     color1.setAlpha(0);
    708     QColor color2 = pal.color(QPalette::Window).darker(200);
    709 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
    710     QColor color3 = pal.color(QPalette::Window).darker(120);
    711 #endif /* Q_WS_WIN || Q_WS_X11 */
    712 
    713     /* Left corner: */
    714     QRadialGradient grad1(QPointF(5, 5), 5);
    715     {
    716         grad1.setColorAt(0, color2);
    717         grad1.setColorAt(1, color1);
    718     }
    719     /* Right corner: */
    720     QRadialGradient grad2(QPointF(width() - 5, 5), 5);
    721     {
    722         grad2.setColorAt(0, color2);
    723         grad2.setColorAt(1, color1);
    724     }
    725     /* Top line: */
    726     QLinearGradient grad3(QPointF(5, 0), QPointF(5, 5));
    727     {
    728         grad3.setColorAt(0, color1);
    729         grad3.setColorAt(1, color2);
    730     }
    731     /* Left line: */
    732     QLinearGradient grad4(QPointF(0, 5), QPointF(5, 5));
    733     {
    734         grad4.setColorAt(0, color1);
    735         grad4.setColorAt(1, color2);
    736     }
    737     /* Right line: */
    738     QLinearGradient grad5(QPointF(width(), 5), QPointF(width() - 5, 5));
    739     {
    740         grad5.setColorAt(0, color1);
    741         grad5.setColorAt(1, color2);
    742     }
    743 
    744     /* Paint frames: */
    745     painter.fillRect(QRect(5, 5, width() - 5 * 2, height() - 5), color0);
    746     painter.fillRect(QRect(0, 0, 5, 5), grad1);
    747     painter.fillRect(QRect(width() - 5, 0, 5, 5), grad2);
    748     painter.fillRect(QRect(5, 0, width() - 5 * 2, 5), grad3);
    749     painter.fillRect(QRect(0, 5, 5, height() - 5), grad4);
    750     painter.fillRect(QRect(width() - 5, 5, 5, height() - 5), grad5);
    751 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
    752     painter.save();
    753     painter.setPen(color3);
    754     painter.drawLine(QLine(QPoint(5 + 1, 5 + 1),                      QPoint(width() - 1 - 5 - 1, 5 + 1)));
    755     painter.drawLine(QLine(QPoint(width() - 1 - 5 - 1, 5 + 1),        QPoint(width() - 1 - 5 - 1, height() - 1)));
    756     painter.drawLine(QLine(QPoint(width() - 1 - 5 - 1, height() - 1), QPoint(5 + 1, height() - 1)));
    757     painter.drawLine(QLine(QPoint(5 + 1, height() - 1),               QPoint(5 + 1, 5 + 1)));
    758     painter.restore();
    759 #endif /* Q_WS_WIN || Q_WS_X11 */
    760 
    761     /* Paint drop token: */
    762     if (m_pButtonDropToken)
    763     {
    764         QStyleOption option;
    765         option.state |= QStyle::State_Horizontal;
    766         const QRect geo = m_pButtonDropToken->geometry();
    767         option.rect = !m_fDropAfterTokenButton ?
    768                       QRect(geo.topLeft() - QPoint(5, 5),
    769                             geo.bottomLeft() + QPoint(0, 5)) :
    770                       QRect(geo.topRight() - QPoint(0, 5),
    771                             geo.bottomRight() + QPoint(5, 5));
    772         QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator,
    773                                              &option, &painter);
    774     }
    775 }
    776 
    777 void UIStatusBarEditorWindow::dragEnterEvent(QDragEnterEvent *pEvent)
    778 {
    779     /* Make sure event is valid: */
    780     AssertPtrReturnVoid(pEvent);
    781     /* And mime-data is set: */
    782     const QMimeData *pMimeData = pEvent->mimeData();
    783     AssertPtrReturnVoid(pMimeData);
    784     /* Make sure mime-data format is valid: */
    785     if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
    786         return;
    787 
    788     /* Accept drag-enter event: */
    789     pEvent->acceptProposedAction();
    790 }
    791 
    792 void UIStatusBarEditorWindow::dragMoveEvent(QDragMoveEvent *pEvent)
    793 {
    794     /* Make sure event is valid: */
    795     AssertPtrReturnVoid(pEvent);
    796     /* And mime-data is set: */
    797     const QMimeData *pMimeData = pEvent->mimeData();
    798     AssertPtrReturnVoid(pMimeData);
    799     /* Make sure mime-data format is valid: */
    800     if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
    801         return;
    802 
    803     /* Reset token: */
    804     m_pButtonDropToken = 0;
    805     m_fDropAfterTokenButton = true;
    806 
    807     /* Get event position: */
    808     const QPoint pos = pEvent->pos();
    809     /* Search for most suitable button: */
    810     foreach (const IndicatorType &type, m_order)
    811     {
    812         m_pButtonDropToken = m_buttons.value(type);
    813         const QRect geo = m_pButtonDropToken->geometry();
    814         if (pos.x() < geo.center().x())
    815         {
    816             m_fDropAfterTokenButton = false;
    817             break;
    818         }
    819     }
    820     /* Update: */
    821     update();
    822 }
    823 
    824 void UIStatusBarEditorWindow::dragLeaveEvent(QDragLeaveEvent*)
    825 {
    826     /* Reset token: */
    827     m_pButtonDropToken = 0;
    828     m_fDropAfterTokenButton = true;
    829     /* Update: */
    830     update();
    831 }
    832 
    833 void UIStatusBarEditorWindow::dropEvent(QDropEvent *pEvent)
    834 {
    835     /* Make sure event is valid: */
    836     AssertPtrReturnVoid(pEvent);
    837     /* And mime-data is set: */
    838     const QMimeData *pMimeData = pEvent->mimeData();
    839     AssertPtrReturnVoid(pMimeData);
    840     /* Make sure mime-data format is valid: */
    841     if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
    842         return;
    843 
    844     /* Make sure token-button set: */
    845     if (!m_pButtonDropToken)
    846         return;
    847 
    848     /* Determine type of token-button: */
    849     const IndicatorType tokenType = m_pButtonDropToken->type();
    850     /* Determine type of dropped-button: */
    851     const QString strDroppedType =
    852         QString::fromLatin1(pMimeData->data(UIStatusBarEditorButton::MimeType));
    853     const IndicatorType droppedType =
    854         gpConverter->fromInternalString<IndicatorType>(strDroppedType);
    855 
    856     /* Make sure these types are different: */
    857     if (droppedType == tokenType)
    858         return;
    859 
    860     /* Load current status-bar indicator order and make sure it's complete: */
    861     QList<IndicatorType> order =
    862         gEDataManager->statusBarIndicatorOrder(vboxGlobal().managedVMUuid());
    863     for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
    864         if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension &&
    865             !order.contains((IndicatorType)iType))
    866             order << (IndicatorType)iType;
    867 
    868     /* Remove type of dropped-button: */
    869     order.removeAll(droppedType);
    870     /* Insert type of dropped-button into position of token-button: */
    871     int iPosition = order.indexOf(tokenType);
    872     if (m_fDropAfterTokenButton)
    873         ++iPosition;
    874     order.insert(iPosition, droppedType);
    875 
    876     /* Save updated status-bar indicator order: */
    877     gEDataManager->setStatusBarIndicatorOrder(order, vboxGlobal().managedVMUuid());
    878 }
    879 
    880 int UIStatusBarEditorWindow::position(IndicatorType type) const
    881 {
    882     int iPosition = 0;
    883     foreach (const IndicatorType &iteratedType, m_order)
    884         if (iteratedType == type)
    885             return iPosition;
    886         else
    887             ++iPosition;
    888     return iPosition;
    889 }
    890 
    891 
    892 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId)
    893     : UIMachineWindow(pMachineLogic, uScreenId)
    894     , m_pIndicatorsPool(0)
    895 {
    896 }
    897 
    898 void UIMachineWindowNormal::sltMachineStateChanged()
    899 {
    900     /* Call to base-class: */
    901     UIMachineWindow::sltMachineStateChanged();
    902 
    903     /* Update pause and virtualization stuff: */
    904     updateAppearanceOf(UIVisualElement_PauseStuff | UIVisualElement_FeaturesStuff);
    905 }
    906 
    907 void UIMachineWindowNormal::sltMediumChange(const CMediumAttachment &attachment)
    908 {
    909     /* Update corresponding medium stuff: */
    910     KDeviceType type = attachment.GetType();
    911     if (type == KDeviceType_HardDisk)
    912         updateAppearanceOf(UIVisualElement_HDStuff);
    913     if (type == KDeviceType_DVD)
    914         updateAppearanceOf(UIVisualElement_CDStuff);
    915     if (type == KDeviceType_Floppy)
    916         updateAppearanceOf(UIVisualElement_FDStuff);
    917 }
    918 
    919 void UIMachineWindowNormal::sltUSBControllerChange()
    920 {
    921     /* Update USB stuff: */
    922     updateAppearanceOf(UIVisualElement_USBStuff);
    923 }
    924 
    925 void UIMachineWindowNormal::sltUSBDeviceStateChange()
    926 {
    927     /* Update USB stuff: */
    928     updateAppearanceOf(UIVisualElement_USBStuff);
    929 }
    930 
    931 void UIMachineWindowNormal::sltNetworkAdapterChange()
    932 {
    933     /* Update network stuff: */
    934     updateAppearanceOf(UIVisualElement_NetworkStuff);
    935 }
    936 
    937 void UIMachineWindowNormal::sltSharedFolderChange()
    938 {
    939     /* Update shared-folders stuff: */
    940     updateAppearanceOf(UIVisualElement_SharedFolderStuff);
    941 }
    942 
    943 void UIMachineWindowNormal::sltVideoCaptureChange()
    944 {
    945     /* Update video-capture stuff: */
    946     updateAppearanceOf(UIVisualElement_VideoCapture);
    947 }
    948 
    949 void UIMachineWindowNormal::sltCPUExecutionCapChange()
    950 {
    951     /* Update virtualization stuff: */
    952     updateAppearanceOf(UIVisualElement_FeaturesStuff);
    953 }
    954 
    955 void UIMachineWindowNormal::sltShowStatusBarContextMenu(const QPoint &position)
    956 {
    957     /* Prepare context-menu: */
    958     QMenu menu;
    959     /* Having just one action to configure status-bar: */
    960     QAction *pAction = menu.addAction(UIIconPool::iconSet(":/vm_settings_16px.png"),
    961                                       tr("Configure status-bar..."),
    962                                       this, SLOT(sltOpenStatusBarEditorWindow()));
    963     pAction->setEnabled(!uisession()->property("StatusBarEditorOpened").toBool());
    964     /* Execute context-menu: */
    965     menu.exec(statusBar()->mapToGlobal(position));
    966 }
    967 
    968 void UIMachineWindowNormal::sltOpenStatusBarEditorWindow()
    969 {
    970     /* Prevent user from opening another one editor: */
    971     uisession()->setProperty("StatusBarEditorOpened", true);
    972     /* Create status-bar editor: */
    973     UIStatusBarEditorWindow *pStatusBarEditor =
    974         new UIStatusBarEditorWindow(this, m_normalGeometry, statusBar()->geometry());
    975     AssertPtrReturnVoid(pStatusBarEditor);
    976     {
    977         /* Configure status-bar editor: */
    978         connect(this, SIGNAL(sigGeometryChange(const QRect&)),
    979                 pStatusBarEditor, SLOT(sltParentGeometryChanged(const QRect&)));
    980         connect(pStatusBarEditor, SIGNAL(destroyed(QObject*)),
    981                 this, SLOT(sltStatusBarEditorWindowClosed()));
    982 #ifdef Q_WS_MAC
    983         connect(machineLogic(), SIGNAL(sigNotifyAbout3DOverlayVisibilityChange(bool)),
    984                 pStatusBarEditor, SLOT(sltActivateWindow()));
    985 #endif /* Q_WS_MAC */
    986         /* Show window: */
    987         pStatusBarEditor->show();
    988     }
    989 }
    990 
    991 void UIMachineWindowNormal::sltStatusBarEditorWindowClosed()
    992 {
    993     /* Allow user to open editor again: */
    994     uisession()->setProperty("StatusBarEditorOpened", QVariant());
    995 }
    996 
    997 void UIMachineWindowNormal::sltHandleIndicatorContextMenuRequest(IndicatorType indicatorType, const QPoint &position)
    998 {
    999     /* Determine action depending on indicator-type: */
    1000     UIAction *pAction = 0;
    1001     switch (indicatorType)
    1002     {
    1003         case IndicatorType_HardDisks:     pAction = gActionPool->action(UIActionIndexRuntime_Menu_HardDisks);        break;
    1004         case IndicatorType_OpticalDisks:  pAction = gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices);   break;
    1005         case IndicatorType_FloppyDisks:   pAction = gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices);    break;
    1006         case IndicatorType_USB:           pAction = gActionPool->action(UIActionIndexRuntime_Menu_USBDevices);       break;
    1007         case IndicatorType_Network:       pAction = gActionPool->action(UIActionIndexRuntime_Menu_Network);          break;
    1008         case IndicatorType_SharedFolders: pAction = gActionPool->action(UIActionIndexRuntime_Menu_SharedFolders);    break;
    1009         case IndicatorType_VideoCapture:  pAction = gActionPool->action(UIActionIndexRuntime_Menu_VideoCapture);     break;
    1010         case IndicatorType_Mouse:         pAction = gActionPool->action(UIActionIndexRuntime_Menu_MouseIntegration); break;
    1011         case IndicatorType_Keyboard:      pAction = gActionPool->action(UIActionIndexRuntime_Menu_Keyboard);         break;
    1012         default: break;
    1013     }
    1014     /* Raise action's context-menu: */
    1015     if (pAction && pAction->isEnabled())
    1016         pAction->menu()->exec(position);
    1017 }
    1018 
    1019 void UIMachineWindowNormal::prepareSessionConnections()
    1020 {
    1021     /* Call to base-class: */
    1022     UIMachineWindow::prepareSessionConnections();
    1023 
    1024     /* Medium change updater: */
    1025     connect(machineLogic()->uisession(), SIGNAL(sigMediumChange(const CMediumAttachment &)),
    1026             this, SLOT(sltMediumChange(const CMediumAttachment &)));
    1027 
    1028     /* USB controller change updater: */
    1029     connect(machineLogic()->uisession(), SIGNAL(sigUSBControllerChange()),
    1030             this, SLOT(sltUSBControllerChange()));
    1031 
    1032     /* USB device state-change updater: */
    1033     connect(machineLogic()->uisession(), SIGNAL(sigUSBDeviceStateChange(const CUSBDevice &, bool, const CVirtualBoxErrorInfo &)),
    1034             this, SLOT(sltUSBDeviceStateChange()));
    1035 
    1036     /* Network adapter change updater: */
    1037     connect(machineLogic()->uisession(), SIGNAL(sigNetworkAdapterChange(const CNetworkAdapter &)),
    1038             this, SLOT(sltNetworkAdapterChange()));
    1039 
    1040     /* Shared folder change updater: */
    1041     connect(machineLogic()->uisession(), SIGNAL(sigSharedFolderChange()),
    1042             this, SLOT(sltSharedFolderChange()));
    1043 
    1044     /* Video capture change updater: */
    1045     connect(machineLogic()->uisession(), SIGNAL(sigVideoCaptureChange()),
    1046             this, SLOT(sltVideoCaptureChange()));
    1047 
    1048     /* CPU execution cap change updater: */
    1049     connect(machineLogic()->uisession(), SIGNAL(sigCPUExecutionCapChange()),
    1050             this, SLOT(sltCPUExecutionCapChange()));
    1051 }
    1052 
    1053 void UIMachineWindowNormal::prepareMenu()
    1054 {
    1055     /* Call to base-class: */
    1056     UIMachineWindow::prepareMenu();
    1057 
    1058 #ifndef Q_WS_MAC
    1059     /* Prepare application menu-bar: */
    1060     RuntimeMenuType restrictedMenus = gEDataManager->restrictedRuntimeMenuTypes(vboxGlobal().managedVMUuid());
    1061     RuntimeMenuType allowedMenus = static_cast<RuntimeMenuType>(RuntimeMenuType_All ^ restrictedMenus);
    1062     setMenuBar(uisession()->newMenuBar(allowedMenus));
    1063 #endif /* !Q_WS_MAC */
    1064 }
    1065 
    1066 void UIMachineWindowNormal::prepareStatusBar()
    1067 {
    1068     /* Call to base-class: */
    1069     UIMachineWindow::prepareStatusBar();
    1070 
    1071     /* Create status-bar: */
    1072     setStatusBar(new QIStatusBar);
    1073     AssertPtrReturnVoid(statusBar());
    1074     {
    1075         /* Configure status-bar: */
    1076         statusBar()->setContextMenuPolicy(Qt::CustomContextMenu);
    1077         connect(statusBar(), SIGNAL(customContextMenuRequested(const QPoint&)),
    1078                 this, SLOT(sltShowStatusBarContextMenu(const QPoint&)));
    1079         /* Create indicator-pool: */
    1080         m_pIndicatorsPool = new UIIndicatorsPool(machineLogic()->uisession());
    1081         AssertPtrReturnVoid(m_pIndicatorsPool);
    1082         {
    1083             /* Configure indicator-pool: */
    1084             connect(m_pIndicatorsPool, SIGNAL(sigContextMenuRequest(IndicatorType, const QPoint&)),
    1085                     this, SLOT(sltHandleIndicatorContextMenuRequest(IndicatorType, const QPoint&)));
    1086             /* Add indicator-pool into status-bar: */
    1087             statusBar()->addPermanentWidget(m_pIndicatorsPool, 0);
    1088         }
    1089     }
    1090 
    1091 #ifdef Q_WS_MAC
    1092     /* For the status-bar on Cocoa: */
    1093     setUnifiedTitleAndToolBarOnMac(true);
    1094 #endif /* Q_WS_MAC */
    1095 }
    1096 
    1097 void UIMachineWindowNormal::prepareVisualState()
    1098 {
    1099     /* Call to base-class: */
    1100     UIMachineWindow::prepareVisualState();
    1101 
    1102 #ifdef VBOX_GUI_WITH_CUSTOMIZATIONS1
    1103     /* The background has to go black: */
    1104     QPalette palette(centralWidget()->palette());
    1105     palette.setColor(centralWidget()->backgroundRole(), Qt::black);
    1106     centralWidget()->setPalette(palette);
    1107     centralWidget()->setAutoFillBackground(true);
    1108     setAutoFillBackground(true);
    1109 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */
    1110 
    1111 #ifdef Q_WS_MAC
    1112     /* Beta label? */
    1113     if (vboxGlobal().isBeta())
    1114     {
    1115         QPixmap betaLabel = ::betaLabel(QSize(100, 16));
    1116         ::darwinLabelWindow(this, &betaLabel, true);
    1117     }
    1118 #endif /* Q_WS_MAC */
    1119 }
    1120 
    1121 void UIMachineWindowNormal::loadSettings()
    1122 {
    1123     /* Call to base-class: */
    1124     UIMachineWindow::loadSettings();
    1125 
    1126     /* Get machine: */
    1127     CMachine m = machine();
    1128 
    1129     /* Load GUI customizations: */
    1130     {
    1131         VBoxGlobalSettings settings = vboxGlobal().settings();
    1132 #ifndef Q_WS_MAC
    1133         menuBar()->setHidden(settings.isFeatureActive("noMenuBar"));
    1134 #endif /* !Q_WS_MAC */
    1135         statusBar()->setHidden(settings.isFeatureActive("noStatusBar"));
    1136         if (statusBar()->isHidden())
    1137             m_pIndicatorsPool->setAutoUpdateIndicatorStates(false);
    1138     }
    1139 
    1140     /* Load window geometry: */
    1141     {
    1142         /* Load extra-data: */
    1143         QRect geo = gEDataManager->machineWindowGeometry(machineLogic()->visualStateType(),
    1144                                                          m_uScreenId, vboxGlobal().managedVMUuid());
    1145 
    1146         /* If we do have proper geometry: */
    1147         if (!geo.isNull())
    1148         {
    1149             /* If previous machine-state was SAVED: */
    1150             if (m.GetState() == KMachineState_Saved)
    1151             {
    1152                 /* Restore window geometry: */
    1153                 m_normalGeometry = geo;
    1154                 setGeometry(m_normalGeometry);
    1155             }
    1156             /* If previous machine-state was NOT SAVED: */
    1157             else
    1158             {
    1159                 /* Restore only window position: */
    1160                 m_normalGeometry = QRect(geo.x(), geo.y(), width(), height());
    1161                 setGeometry(m_normalGeometry);
    1162                 /* And normalize to the optimal-size: */
    1163                 normalizeGeometry(false);
    1164             }
    1165 
    1166             /* Maximize (if necessary): */
    1167             if (gEDataManager->machineWindowShouldBeMaximized(machineLogic()->visualStateType(),
    1168                                                               m_uScreenId, vboxGlobal().managedVMUuid()))
    1169                 setWindowState(windowState() | Qt::WindowMaximized);
    1170         }
    1171         /* If we do NOT have proper geometry: */
    1172         else
    1173         {
    1174             /* Get available geometry, for screen with (x,y) coords if possible: */
    1175             QRect availableGeo = !geo.isNull() ? QApplication::desktop()->availableGeometry(QPoint(geo.x(), geo.y())) :
    1176                                                  QApplication::desktop()->availableGeometry(this);
    1177 
    1178             /* Normalize to the optimal size: */
    1179             normalizeGeometry(true);
    1180             /* Move newly created window to the screen-center: */
    1181             m_normalGeometry = geometry();
    1182             m_normalGeometry.moveCenter(availableGeo.center());
    1183             setGeometry(m_normalGeometry);
    1184         }
    1185 
    1186         /* Normalize to the optimal size: */
    1187 #ifdef Q_WS_X11
    1188         QTimer::singleShot(0, this, SLOT(sltNormalizeGeometry()));
    1189 #else /* !Q_WS_X11 */
    1190         normalizeGeometry(true);
    1191 #endif /* !Q_WS_X11 */
    1192     }
    1193 }
    1194 
    1195 void UIMachineWindowNormal::saveSettings()
    1196 {
    1197     /* Save window geometry: */
    1198     {
    1199         gEDataManager->setMachineWindowGeometry(machineLogic()->visualStateType(),
    1200                                                 m_uScreenId, m_normalGeometry,
    1201                                                 isMaximizedChecked(), vboxGlobal().managedVMUuid());
    1202     }
    1203 
    1204     /* Call to base-class: */
    1205     UIMachineWindow::saveSettings();
    1206 }
    1207 
    1208 bool UIMachineWindowNormal::event(QEvent *pEvent)
    1209 {
    1210     switch (pEvent->type())
    1211     {
    1212         case QEvent::Resize:
    1213         {
    1214             QResizeEvent *pResizeEvent = static_cast<QResizeEvent*>(pEvent);
    1215             if (!isMaximizedChecked())
    1216             {
    1217                 m_normalGeometry.setSize(pResizeEvent->size());
    1218                 emit sigGeometryChange(m_normalGeometry);
    1219 #ifdef VBOX_WITH_DEBUGGER_GUI
    1220                 /* Update debugger window position: */
    1221                 updateDbgWindows();
    1222 #endif /* VBOX_WITH_DEBUGGER_GUI */
    1223             }
    1224             break;
    1225         }
    1226         case QEvent::Move:
    1227         {
    1228             if (!isMaximizedChecked())
    1229             {
    1230                 m_normalGeometry.moveTo(geometry().x(), geometry().y());
    1231                 emit sigGeometryChange(m_normalGeometry);
    1232 #ifdef VBOX_WITH_DEBUGGER_GUI
    1233                 /* Update debugger window position: */
    1234                 updateDbgWindows();
    1235 #endif /* VBOX_WITH_DEBUGGER_GUI */
    1236             }
    1237             break;
    1238         }
    1239         case QEvent::WindowActivate:
    1240             emit sigGeometryChange(m_normalGeometry);
    1241             break;
    1242         default:
    1243             break;
    1244     }
    1245     return UIMachineWindow::event(pEvent);
    1246 }
    1247 
    1248 void UIMachineWindowNormal::showInNecessaryMode()
    1249 {
    1250     /* Make sure this window should be shown at all: */
    1251     if (!uisession()->isScreenVisible(m_uScreenId))
    1252         return hide();
    1253 
    1254     /* Make sure this window is not minimized: */
    1255     if (isMinimized())
    1256         return;
    1257 
    1258     /* Show in normal mode: */
    1259     show();
    1260 }
    1261 
    1262 /**
    1263  * Adjusts machine-window size to correspond current guest screen size.
    1264  * @param fAdjustPosition determines whether is it necessary to adjust position too.
    1265  */
    1266 void UIMachineWindowNormal::normalizeGeometry(bool fAdjustPosition)
    1267 {
    1268 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS1
    1269     /* Skip if maximized: */
    1270     if (isMaximized())
    1271         return;
    1272 
    1273     /* Calculate client window offsets: */
    1274     QRect frameGeo = frameGeometry();
    1275     QRect geo = geometry();
    1276     int dl = geo.left() - frameGeo.left();
    1277     int dt = geo.top() - frameGeo.top();
    1278     int dr = frameGeo.right() - geo.right();
    1279     int db = frameGeo.bottom() - geo.bottom();
    1280 
    1281     /* Get the best size w/o scroll-bars: */
    1282     QSize s = sizeHint();
    1283 
    1284     /* Resize the frame to fit the contents: */
    1285     s -= size();
    1286     frameGeo.setRight(frameGeo.right() + s.width());
    1287     frameGeo.setBottom(frameGeo.bottom() + s.height());
    1288 
    1289     /* Adjust position if necessary: */
    1290     if (fAdjustPosition)
    1291     {
    1292         QRegion availableGeo;
    1293         QDesktopWidget *dwt = QApplication::desktop();
    1294         if (dwt->isVirtualDesktop())
    1295             /* Compose complex available region: */
    1296             for (int i = 0; i < dwt->numScreens(); ++i)
    1297                 availableGeo += dwt->availableGeometry(i);
    1298         else
    1299             /* Get just a simple available rectangle */
    1300             availableGeo = dwt->availableGeometry(pos());
    1301 
    1302         frameGeo = VBoxGlobal::normalizeGeometry(frameGeo, availableGeo);
    1303     }
    1304 
    1305     /* Finally, set the frame geometry: */
    1306     setGeometry(frameGeo.left() + dl, frameGeo.top() + dt,
    1307                 frameGeo.width() - dl - dr, frameGeo.height() - dt - db);
    1308 
    1309 #else /* !VBOX_GUI_WITH_CUSTOMIZATIONS1 */
    1310     Q_UNUSED(fAdjustPosition);
    1311 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */
    1312 }
    1313 
    1314 void UIMachineWindowNormal::updateAppearanceOf(int iElement)
    1315 {
    1316     /* Call to base-class: */
    1317     UIMachineWindow::updateAppearanceOf(iElement);
    1318 
    1319     /* Update machine window content: */
    1320     if (iElement & UIVisualElement_PauseStuff)
    1321     {
    1322         if (!statusBar()->isHidden())
    1323         {
    1324             if (uisession()->isPaused())
    1325                 m_pIndicatorsPool->setAutoUpdateIndicatorStates(false);
    1326             else if (uisession()->isRunning())
    1327                 m_pIndicatorsPool->setAutoUpdateIndicatorStates(true);
    1328         }
    1329     }
    1330     if (iElement & UIVisualElement_HDStuff)
    1331         m_pIndicatorsPool->updateAppearance(IndicatorType_HardDisks);
    1332     if (iElement & UIVisualElement_CDStuff)
    1333         m_pIndicatorsPool->updateAppearance(IndicatorType_OpticalDisks);
    1334     if (iElement & UIVisualElement_FDStuff)
    1335         m_pIndicatorsPool->updateAppearance(IndicatorType_FloppyDisks);
    1336     if (iElement & UIVisualElement_NetworkStuff)
    1337         m_pIndicatorsPool->updateAppearance(IndicatorType_Network);
    1338     if (iElement & UIVisualElement_USBStuff)
    1339         m_pIndicatorsPool->updateAppearance(IndicatorType_USB);
    1340     if (iElement & UIVisualElement_SharedFolderStuff)
    1341         m_pIndicatorsPool->updateAppearance(IndicatorType_SharedFolders);
    1342     if (iElement & UIVisualElement_VideoCapture)
    1343         m_pIndicatorsPool->updateAppearance(IndicatorType_VideoCapture);
    1344     if (iElement & UIVisualElement_FeaturesStuff)
    1345         m_pIndicatorsPool->updateAppearance(IndicatorType_Features);
    1346 }
    1347 
    1348 bool UIMachineWindowNormal::isMaximizedChecked()
    1349 {
    1350 #ifdef Q_WS_MAC
    1351     /* On the Mac the WindowStateChange signal doesn't seems to be delivered
    1352      * when the user get out of the maximized state. So check this ourself. */
    1353     return ::darwinIsWindowMaximized(this);
    1354 #else /* Q_WS_MAC */
    1355     return isMaximized();
    1356 #endif /* !Q_WS_MAC */
    1357 }
    1358 
    1359 #include "UIMachineWindowNormal.moc"
    1360 
     178#endif /* !___UIStatusBarEditorWindow_h___ */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp

    r52060 r52070  
    2525#include <QResizeEvent>
    2626
    27 #include <QStylePainter>
    28 #include <QStyleOption>
    29 #include <QPaintEvent>
    30 #include <QPainter>
    31 #include <QDrag>
    32 
    3327/* GUI includes: */
    3428#include "VBoxGlobal.h"
     29#include "UIMachineWindowNormal.h"
     30#include "UIStatusBarEditorWindow.h"
     31#include "UIActionPoolRuntime.h"
    3532#include "UIExtraDataManager.h"
    36 #include "UISession.h"
    37 #include "UIActionPoolRuntime.h"
    3833#include "UIIndicatorsPool.h"
    3934#include "UIKeyboardHandler.h"
    4035#include "UIMouseHandler.h"
    4136#include "UIMachineLogic.h"
    42 #include "UIMachineWindowNormal.h"
    4337#include "UIMachineView.h"
     38#include "UIIconPool.h"
     39#include "UISession.h"
    4440#include "QIStatusBar.h"
    4541#include "QIStatusBarIndicator.h"
     
    4945#endif /* Q_WS_MAC */
    5046
    51 #include "QIWithRetranslateUI.h"
    52 #include "QIToolButton.h"
    53 #include "UIIconPool.h"
    54 #include "UIConverter.h"
    55 #include "UIAnimationFramework.h"
    56 
    5747/* COM includes: */
    5848#include "CConsole.h"
     
    6050#include "CUSBController.h"
    6151#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     /* Revoke hovered state: */
    242     m_fHovered = false;
    243     /* Update: */
    244     update();
    245 
    246     /* Initialize dragging: */
    247     m_mousePressPosition = QPoint();
    248     QDrag *pDrag = new QDrag(this);
    249     connect(pDrag, SIGNAL(destroyed(QObject*)), this, SIGNAL(sigDragObjectDestroy()));
    250     QMimeData *pMimeData = new QMimeData;
    251     pMimeData->setData(MimeType, gpConverter->toInternalString(m_type).toLatin1());
    252     pDrag->setMimeData(pMimeData);
    253     pDrag->setPixmap(m_pixmap);
    254     pDrag->exec();
    255 }
    256 
    257 
    258 /** QWidget reimplementation
    259   * providing user with possibility to edit status-bar layout. */
    260 class UIStatusBarEditorWindow : public QIWithRetranslateUI2<QWidget>
    261 {
    262     Q_OBJECT;
    263     Q_PROPERTY(QRect startGeometry READ startGeometry);
    264     Q_PROPERTY(QRect finalGeometry READ finalGeometry);
    265 
    266 signals:
    267 
    268     /** Notifies about window shown. */
    269     void sigShown();
    270     /** Commands window to expand. */
    271     void sigExpand();
    272     /** Commands window to collapse. */
    273     void sigCollapse();
    274 
    275 public:
    276 
    277     /** Constructor, passes @a pParent to the QIRichToolButton constructor.
    278       * @param rect is used to define initial cached parent geometry.
    279       * @param statusBarRect is used to define initial cached status-bar geometry. */
    280     UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect);
    281 
    282 private slots:
    283 
    284     /** Mark window as expanded. */
    285     void sltMarkAsExpanded() { m_fExpanded = true; }
    286     /** Mark window as collapsed. */
    287     void sltMarkAsCollapsed() { close(); m_fExpanded = false; }
    288 
    289     /** Handles parent geometry change. */
    290     void sltParentGeometryChanged(const QRect &rect);
    291 
    292     /** Handles configuration change. */
    293     void sltHandleConfigurationChange();
    294 
    295     /** Handles button click. */
    296     void sltHandleButtonClick();
    297 
    298     /** Handles drag object destroy. */
    299     void sltHandleDragObjectDestroy();
    300 
    301     /** Performs window activation. */
    302     void sltActivateWindow() { activateWindow(); }
    303 
    304 private:
    305 
    306     /** Prepare routine. */
    307     void prepare();
    308     /** Prepare status buttons routine. */
    309     void prepareStatusButtons();
    310     /** Prepare status button routine. */
    311     void prepareStatusButton(IndicatorType type);
    312     /** Prepare animation routine. */
    313     void prepareAnimation();
    314     /** Prepare geometry. */
    315     void prepareGeometry();
    316 
    317     /** Updates status buttons. */
    318     void updateStatusButtons();
    319     /** Updates animation. */
    320     void updateAnimation();
    321     /** Update geometry. */
    322     void adjustGeometry();
    323 
    324     /** Retranslation routine. */
    325     virtual void retranslateUi();
    326 
    327     /** Show event handler. */
    328     virtual void showEvent(QShowEvent *pEvent);
    329     /** Close event handler. */
    330     virtual void closeEvent(QCloseEvent *pEvent);
    331 
    332     /** Paint event handler. */
    333     virtual void paintEvent(QPaintEvent *pEvent);
    334 
    335     /** Drag-enter event handler. */
    336     virtual void dragEnterEvent(QDragEnterEvent *pEvent);
    337     /** Drag-move event handler. */
    338     virtual void dragMoveEvent(QDragMoveEvent *pEvent);
    339     /** Drag-leave event handler. */
    340     virtual void dragLeaveEvent(QDragLeaveEvent *pEvent);
    341     /** Drop event handler. */
    342     virtual void dropEvent(QDropEvent *pEvent);
    343 
    344     /** Returns position for passed @a type. */
    345     int position(IndicatorType type) const;
    346 
    347     /** Returns cached start-geometry. */
    348     QRect startGeometry() const { return m_startGeometry; }
    349     /** Returns cached final-geometry. */
    350     QRect finalGeometry() const { return m_finalGeometry; }
    351 
    352     /** @name Geometry
    353       * @{ */
    354         /** Holds the cached parent geometry. */
    355         QRect m_rect;
    356         /** Holds the cached status-bar geometry. */
    357         QRect m_statusBarRect;
    358     /** @} */
    359 
    360     /** @name Geometry: Animation
    361       * @{ */
    362         /** Holds the expand/collapse animation instance. */
    363         UIAnimation *m_pAnimation;
    364         /** Holds whether window is expanded. */
    365         bool m_fExpanded;
    366         /** Holds the cached start-geometry. */
    367         QRect m_startGeometry;
    368         /** Holds the cached final-geometry. */
    369         QRect m_finalGeometry;
    370     /** @} */
    371 
    372     /** @name Contents
    373       * @{ */
    374         /** Holds the main-layout instance. */
    375         QHBoxLayout *m_pMainLayout;
    376         /** Holds the button-layout instance. */
    377         QHBoxLayout *m_pButtonLayout;
    378         /** Holds the close-button instance. */
    379         QIToolButton *m_pButtonClose;
    380         /** Holds status-bar buttons. */
    381         QMap<IndicatorType, UIStatusBarEditorButton*> m_buttons;
    382     /** @} */
    383 
    384     /** @name Contents: Restrictions
    385       * @{ */
    386         /** Holds the cached status-bar button restrictions. */
    387         QList<IndicatorType> m_restrictions;
    388     /** @} */
    389 
    390     /** @name Contents: Order
    391       * @{ */
    392         /** Holds the cached status-bar button order. */
    393         QList<IndicatorType> m_order;
    394         /** Holds the token-button to drop dragged-button nearby. */
    395         UIStatusBarEditorButton *m_pButtonDropToken;
    396         /** Holds whether dragged-button should be dropped <b>after</b> the token-button. */
    397         bool m_fDropAfterTokenButton;
    398     /** @} */
    399 };
    400 
    401 UIStatusBarEditorWindow::UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect)
    402     : QIWithRetranslateUI2<QWidget>(pParent, Qt::Tool | Qt::FramelessWindowHint)
    403     , m_rect(rect), m_statusBarRect(statusBarRect)
    404     , m_pAnimation(0), m_fExpanded(false)
    405     , m_pMainLayout(0), m_pButtonLayout(0)
    406     , m_pButtonClose(0)
    407     , m_pButtonDropToken(0)
    408     , m_fDropAfterTokenButton(true)
    409 {
    410     /* Prepare: */
    411     prepare();
    412 }
    413 
    414 void UIStatusBarEditorWindow::sltParentGeometryChanged(const QRect &rect)
    415 {
    416     /* Update rectangle: */
    417     m_rect = rect;
    418     /* Update animation: */
    419     updateAnimation();
    420     /* Adjust geometry: */
    421     adjustGeometry();
    422 }
    423 
    424 void UIStatusBarEditorWindow::sltHandleConfigurationChange()
    425 {
    426     /* Update status buttons: */
    427     updateStatusButtons();
    428 }
    429 
    430 void UIStatusBarEditorWindow::sltHandleButtonClick()
    431 {
    432     /* Make sure sender is valid: */
    433     UIStatusBarEditorButton *pButton = qobject_cast<UIStatusBarEditorButton*>(sender());
    434     AssertPtrReturnVoid(pButton);
    435 
    436     /* Get sender type: */
    437     const IndicatorType type = pButton->type();
    438 
    439     /* Load current status-bar indicator restrictions: */
    440     QList<IndicatorType> restrictions =
    441         gEDataManager->restrictedStatusBarIndicators(vboxGlobal().managedVMUuid());
    442 
    443     /* Invert restriction for sender type: */
    444     if (restrictions.contains(type))
    445         restrictions.removeAll(type);
    446     else
    447         restrictions.append(type);
    448 
    449     /* Save updated status-bar indicator restrictions: */
    450     gEDataManager->setRestrictedStatusBarIndicators(restrictions, vboxGlobal().managedVMUuid());
    451 }
    452 
    453 void UIStatusBarEditorWindow::sltHandleDragObjectDestroy()
    454 {
    455     /* Reset token: */
    456     m_pButtonDropToken = 0;
    457     m_fDropAfterTokenButton = true;
    458     /* Update: */
    459     update();
    460 }
    461 
    462 void UIStatusBarEditorWindow::prepare()
    463 {
    464     /* Do not count that window as important for application,
    465      * it will NOT be taken into account when other top-level windows will be closed: */
    466     setAttribute(Qt::WA_QuitOnClose, false);
    467     /* Delete window when closed: */
    468     setAttribute(Qt::WA_DeleteOnClose);
    469 #if defined(Q_WS_MAC) || defined(Q_WS_WIN)
    470     /* Make sure we have no background
    471      * until the first one paint-event: */
    472     setAttribute(Qt::WA_NoSystemBackground);
    473 #endif /* Q_WS_MAC || Q_WS_WIN */
    474 #if defined(Q_WS_MAC)
    475     /* Using native API to enable translucent background for the Mac host.
    476      * - We also want to disable window-shadows which is possible
    477      *   using Qt::WA_MacNoShadow only since Qt 4.8,
    478      *   while minimum supported version is 4.7.1 for now: */
    479     ::darwinSetShowsWindowTransparent(this, true);
    480 #elif defined(Q_WS_WIN)
    481     /* Using Qt API to enable translucent background:
    482      * - Under Win host Qt conflicts with 3D stuff (black seamless regions).
    483      * - Under Mac host Qt doesn't allows to disable window-shadows
    484      *   until version 4.8, but minimum supported version is 4.7.1 for now.
    485      * - Under x11 host Qt has it broken with KDE 4.9 (black background): */
    486     setAttribute(Qt::WA_TranslucentBackground);
    487 #endif /* Q_WS_WIN */
    488     /* Track D&D events: */
    489     setAcceptDrops(true);
    490 
    491     /* Create main-layout: */
    492     m_pMainLayout = new QHBoxLayout(this);
    493     AssertPtrReturnVoid(m_pMainLayout);
    494     {
    495         /* Configure main-layout: */
    496 #ifdef Q_WS_MAC
    497         /* Standard margins on Mac OS X are too big: */
    498         m_pMainLayout->setContentsMargins(10, 10, 10, 5);
    499 #else /* !Q_WS_MAC */
    500         /* Standard margins on Windows/X11: */
    501         int iLeft, iTop, iRight, iBottom;
    502         m_pMainLayout->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
    503         if (iBottom >= 5)
    504             iBottom -= 5;
    505         m_pMainLayout->setContentsMargins(iLeft, iTop, iRight, iBottom);
    506 #endif /* !Q_WS_MAC */
    507         m_pMainLayout->setSpacing(0);
    508         /* Create close-button: */
    509         m_pButtonClose = new QIToolButton;
    510         AssertPtrReturnVoid(m_pButtonClose);
    511         {
    512             /* Configure close-button: */
    513             m_pButtonClose->setFocusPolicy(Qt::StrongFocus);
    514             m_pButtonClose->setMinimumSize(QSize(1, 1));
    515             m_pButtonClose->setShortcut(Qt::Key_Escape);
    516             m_pButtonClose->setIcon(UIIconPool::iconSet(":/ok_16px.png"));
    517             connect(m_pButtonClose, SIGNAL(clicked(bool)), this, SLOT(close()));
    518             /* Add close-button into main-layout: */
    519             m_pMainLayout->addWidget(m_pButtonClose);
    520         }
    521         /* Insert stretch: */
    522         m_pMainLayout->addStretch();
    523         /* Create button-layout: */
    524         m_pButtonLayout = new QHBoxLayout;
    525         AssertPtrReturnVoid(m_pButtonLayout);
    526         {
    527             /* Configure button-layout: */
    528             m_pButtonLayout->setContentsMargins(0, 0, 0, 0);
    529             m_pButtonLayout->setSpacing(5);
    530             /* Add button-layout into main-layout: */
    531             m_pMainLayout->addLayout(m_pButtonLayout);
    532         }
    533         /* Prepare status buttons: */
    534         prepareStatusButtons();
    535     }
    536 
    537     /* Translate contents: */
    538     retranslateUi();
    539 
    540     /* Prepare animation: */
    541     prepareAnimation();
    542     /* Prepare geometry: */
    543     prepareGeometry();
    544 }
    545 
    546 void UIStatusBarEditorWindow::prepareStatusButtons()
    547 {
    548     /* Create status buttons: */
    549     for (int i = IndicatorType_Invalid; i < IndicatorType_Max; ++i)
    550     {
    551         /* Get current type: */
    552         const IndicatorType type = (IndicatorType)i;
    553         /* Skip inappropriate types: */
    554         if (type == IndicatorType_Invalid || type == IndicatorType_KeyboardExtension)
    555             continue;
    556         /* Create status button: */
    557         prepareStatusButton(type);
    558     }
    559 
    560     /* Listen for the status-bar configuration changes: */
    561     connect(gEDataManager, SIGNAL(sigStatusBarConfigurationChange()),
    562             this, SLOT(sltHandleConfigurationChange()));
    563     /* Update status buttons: */
    564     updateStatusButtons();
    565 }
    566 
    567 void UIStatusBarEditorWindow::prepareStatusButton(IndicatorType type)
    568 {
    569     /* Create status button: */
    570     UIStatusBarEditorButton *pButton = new UIStatusBarEditorButton(type);
    571     AssertPtrReturnVoid(pButton);
    572     {
    573         /* Configure status button: */
    574         connect(pButton, SIGNAL(sigClick()), this, SLOT(sltHandleButtonClick()));
    575         connect(pButton, SIGNAL(sigDragObjectDestroy()), this, SLOT(sltHandleDragObjectDestroy()));
    576         /* Add status button into button-layout: */
    577         m_pButtonLayout->addWidget(pButton);
    578         /* Insert status button into map: */
    579         m_buttons.insert(type, pButton);
    580     }
    581 }
    582 
    583 void UIStatusBarEditorWindow::prepareAnimation()
    584 {
    585     /* Prepare geometry animation itself: */
    586     connect(this, SIGNAL(sigShown()), this, SIGNAL(sigExpand()), Qt::QueuedConnection);
    587     m_pAnimation = UIAnimation::installPropertyAnimation(this, "geometry", "startGeometry", "finalGeometry",
    588                                                          SIGNAL(sigExpand()), SIGNAL(sigCollapse()));
    589     connect(m_pAnimation, SIGNAL(sigStateEnteredStart()), this, SLOT(sltMarkAsCollapsed()));
    590     connect(m_pAnimation, SIGNAL(sigStateEnteredFinal()), this, SLOT(sltMarkAsExpanded()));
    591     /* Update animation: */
    592     updateAnimation();
    593 }
    594 
    595 void UIStatusBarEditorWindow::prepareGeometry()
    596 {
    597     /* Prepare geometry based on minimum size-hint: */
    598     connect(this, SIGNAL(sigShown()), this, SLOT(sltActivateWindow()), Qt::QueuedConnection);
    599     const QSize msh = minimumSizeHint();
    600     setGeometry(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - msh.height(),
    601                 qMax(m_rect.width(), msh.width()), msh.height());
    602 #ifdef Q_WS_WIN
    603     raise();
    604 #endif /* Q_WS_WIN */
    605 }
    606 
    607 void UIStatusBarEditorWindow::updateStatusButtons()
    608 {
    609     /* Recache status-bar configuration: */
    610     m_restrictions = gEDataManager->restrictedStatusBarIndicators(vboxGlobal().managedVMUuid());
    611     m_order = gEDataManager->statusBarIndicatorOrder(vboxGlobal().managedVMUuid());
    612     for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
    613         if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension &&
    614             !m_order.contains((IndicatorType)iType))
    615             m_order << (IndicatorType)iType;
    616 
    617     /* Update configuration for all the status buttons: */
    618     foreach (const IndicatorType &type, m_order)
    619     {
    620         /* Get button: */
    621         UIStatusBarEditorButton *pButton = m_buttons.value(type);
    622         /* Update button 'checked' state: */
    623         pButton->setChecked(!m_restrictions.contains(type));
    624         /* Make sure it have valid position: */
    625         const int iWantedIndex = position(type);
    626         const int iActualIndex = m_pButtonLayout->indexOf(pButton);
    627         if (iActualIndex != iWantedIndex)
    628         {
    629             /* Re-inject button into main-layout at proper position: */
    630             m_pButtonLayout->removeWidget(pButton);
    631             m_pButtonLayout->insertWidget(iWantedIndex, pButton);
    632         }
    633     }
    634 }
    635 
    636 void UIStatusBarEditorWindow::updateAnimation()
    637 {
    638     /* Calculate geometry animation boundaries
    639      * based on size-hint and minimum size-hint: */
    640     const QSize sh = sizeHint();
    641     const QSize msh = minimumSizeHint();
    642     m_startGeometry = QRect(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - msh.height(),
    643                             qMax(m_rect.width(), msh.width()), msh.height());
    644     m_finalGeometry = QRect(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - sh.height(),
    645                             qMax(m_rect.width(), sh.width()), sh.height());
    646     m_pAnimation->update();
    647 }
    648 
    649 void UIStatusBarEditorWindow::adjustGeometry()
    650 {
    651     /* Adjust geometry based on size-hint: */
    652     const QSize sh = sizeHint();
    653     setGeometry(m_rect.x(), m_rect.y() + m_rect.height() - m_statusBarRect.height() - sh.height(),
    654                 qMax(m_rect.width(), sh.width()), sh.height());
    655 #ifdef Q_WS_WIN
    656     raise();
    657 #endif /* Q_WS_WIN */
    658 }
    659 
    660 void UIStatusBarEditorWindow::retranslateUi()
    661 {
    662     /* Translate close-button: */
    663     m_pButtonClose->setToolTip(tr("Close"));
    664 }
    665 
    666 void UIStatusBarEditorWindow::showEvent(QShowEvent*)
    667 {
    668     /* If window isn't expanded: */
    669     if (!m_fExpanded)
    670     {
    671         /* Start expand animation: */
    672         emit sigShown();
    673     }
    674 }
    675 
    676 void UIStatusBarEditorWindow::closeEvent(QCloseEvent *pEvent)
    677 {
    678     /* If window isn't expanded: */
    679     if (!m_fExpanded)
    680     {
    681         /* Ignore close-event: */
    682         pEvent->ignore();
    683         return;
    684     }
    685 
    686     /* If animation state is Final: */
    687     const QString strAnimationState = property("AnimationState").toString();
    688     bool fAnimationComplete = strAnimationState == "Final";
    689     if (fAnimationComplete)
    690     {
    691         /* Ignore close-event: */
    692         pEvent->ignore();
    693         /* And start collapse animation: */
    694         emit sigCollapse();
    695     }
    696 }
    697 
    698 void UIStatusBarEditorWindow::paintEvent(QPaintEvent*)
    699 {
    700     /* Prepare painter: */
    701     QPainter painter(this);
    702 
    703     /* Prepare palette colors: */
    704     const QPalette pal = palette();
    705     QColor color0 = pal.color(QPalette::Window);
    706     QColor color1 = pal.color(QPalette::Window).lighter(110);
    707     color1.setAlpha(0);
    708     QColor color2 = pal.color(QPalette::Window).darker(200);
    709 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
    710     QColor color3 = pal.color(QPalette::Window).darker(120);
    711 #endif /* Q_WS_WIN || Q_WS_X11 */
    712 
    713     /* Left corner: */
    714     QRadialGradient grad1(QPointF(5, 5), 5);
    715     {
    716         grad1.setColorAt(0, color2);
    717         grad1.setColorAt(1, color1);
    718     }
    719     /* Right corner: */
    720     QRadialGradient grad2(QPointF(width() - 5, 5), 5);
    721     {
    722         grad2.setColorAt(0, color2);
    723         grad2.setColorAt(1, color1);
    724     }
    725     /* Top line: */
    726     QLinearGradient grad3(QPointF(5, 0), QPointF(5, 5));
    727     {
    728         grad3.setColorAt(0, color1);
    729         grad3.setColorAt(1, color2);
    730     }
    731     /* Left line: */
    732     QLinearGradient grad4(QPointF(0, 5), QPointF(5, 5));
    733     {
    734         grad4.setColorAt(0, color1);
    735         grad4.setColorAt(1, color2);
    736     }
    737     /* Right line: */
    738     QLinearGradient grad5(QPointF(width(), 5), QPointF(width() - 5, 5));
    739     {
    740         grad5.setColorAt(0, color1);
    741         grad5.setColorAt(1, color2);
    742     }
    743 
    744     /* Paint frames: */
    745     painter.fillRect(QRect(5, 5, width() - 5 * 2, height() - 5), color0);
    746     painter.fillRect(QRect(0, 0, 5, 5), grad1);
    747     painter.fillRect(QRect(width() - 5, 0, 5, 5), grad2);
    748     painter.fillRect(QRect(5, 0, width() - 5 * 2, 5), grad3);
    749     painter.fillRect(QRect(0, 5, 5, height() - 5), grad4);
    750     painter.fillRect(QRect(width() - 5, 5, 5, height() - 5), grad5);
    751 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
    752     painter.save();
    753     painter.setPen(color3);
    754     painter.drawLine(QLine(QPoint(5 + 1, 5 + 1),                      QPoint(width() - 1 - 5 - 1, 5 + 1)));
    755     painter.drawLine(QLine(QPoint(width() - 1 - 5 - 1, 5 + 1),        QPoint(width() - 1 - 5 - 1, height() - 1)));
    756     painter.drawLine(QLine(QPoint(width() - 1 - 5 - 1, height() - 1), QPoint(5 + 1, height() - 1)));
    757     painter.drawLine(QLine(QPoint(5 + 1, height() - 1),               QPoint(5 + 1, 5 + 1)));
    758     painter.restore();
    759 #endif /* Q_WS_WIN || Q_WS_X11 */
    760 
    761     /* Paint drop token: */
    762     if (m_pButtonDropToken)
    763     {
    764         QStyleOption option;
    765         option.state |= QStyle::State_Horizontal;
    766         const QRect geo = m_pButtonDropToken->geometry();
    767         option.rect = !m_fDropAfterTokenButton ?
    768                       QRect(geo.topLeft() - QPoint(5, 5),
    769                             geo.bottomLeft() + QPoint(0, 5)) :
    770                       QRect(geo.topRight() - QPoint(0, 5),
    771                             geo.bottomRight() + QPoint(5, 5));
    772         QApplication::style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator,
    773                                              &option, &painter);
    774     }
    775 }
    776 
    777 void UIStatusBarEditorWindow::dragEnterEvent(QDragEnterEvent *pEvent)
    778 {
    779     /* Make sure event is valid: */
    780     AssertPtrReturnVoid(pEvent);
    781     /* And mime-data is set: */
    782     const QMimeData *pMimeData = pEvent->mimeData();
    783     AssertPtrReturnVoid(pMimeData);
    784     /* Make sure mime-data format is valid: */
    785     if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
    786         return;
    787 
    788     /* Accept drag-enter event: */
    789     pEvent->acceptProposedAction();
    790 }
    791 
    792 void UIStatusBarEditorWindow::dragMoveEvent(QDragMoveEvent *pEvent)
    793 {
    794     /* Make sure event is valid: */
    795     AssertPtrReturnVoid(pEvent);
    796     /* And mime-data is set: */
    797     const QMimeData *pMimeData = pEvent->mimeData();
    798     AssertPtrReturnVoid(pMimeData);
    799     /* Make sure mime-data format is valid: */
    800     if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
    801         return;
    802 
    803     /* Reset token: */
    804     m_pButtonDropToken = 0;
    805     m_fDropAfterTokenButton = true;
    806 
    807     /* Get event position: */
    808     const QPoint pos = pEvent->pos();
    809     /* Search for most suitable button: */
    810     foreach (const IndicatorType &type, m_order)
    811     {
    812         m_pButtonDropToken = m_buttons.value(type);
    813         const QRect geo = m_pButtonDropToken->geometry();
    814         if (pos.x() < geo.center().x())
    815         {
    816             m_fDropAfterTokenButton = false;
    817             break;
    818         }
    819     }
    820     /* Update: */
    821     update();
    822 }
    823 
    824 void UIStatusBarEditorWindow::dragLeaveEvent(QDragLeaveEvent*)
    825 {
    826     /* Reset token: */
    827     m_pButtonDropToken = 0;
    828     m_fDropAfterTokenButton = true;
    829     /* Update: */
    830     update();
    831 }
    832 
    833 void UIStatusBarEditorWindow::dropEvent(QDropEvent *pEvent)
    834 {
    835     /* Make sure event is valid: */
    836     AssertPtrReturnVoid(pEvent);
    837     /* And mime-data is set: */
    838     const QMimeData *pMimeData = pEvent->mimeData();
    839     AssertPtrReturnVoid(pMimeData);
    840     /* Make sure mime-data format is valid: */
    841     if (!pMimeData->hasFormat(UIStatusBarEditorButton::MimeType))
    842         return;
    843 
    844     /* Make sure token-button set: */
    845     if (!m_pButtonDropToken)
    846         return;
    847 
    848     /* Determine type of token-button: */
    849     const IndicatorType tokenType = m_pButtonDropToken->type();
    850     /* Determine type of dropped-button: */
    851     const QString strDroppedType =
    852         QString::fromLatin1(pMimeData->data(UIStatusBarEditorButton::MimeType));
    853     const IndicatorType droppedType =
    854         gpConverter->fromInternalString<IndicatorType>(strDroppedType);
    855 
    856     /* Make sure these types are different: */
    857     if (droppedType == tokenType)
    858         return;
    859 
    860     /* Load current status-bar indicator order and make sure it's complete: */
    861     QList<IndicatorType> order =
    862         gEDataManager->statusBarIndicatorOrder(vboxGlobal().managedVMUuid());
    863     for (int iType = IndicatorType_Invalid; iType < IndicatorType_Max; ++iType)
    864         if (iType != IndicatorType_Invalid && iType != IndicatorType_KeyboardExtension &&
    865             !order.contains((IndicatorType)iType))
    866             order << (IndicatorType)iType;
    867 
    868     /* Remove type of dropped-button: */
    869     order.removeAll(droppedType);
    870     /* Insert type of dropped-button into position of token-button: */
    871     int iPosition = order.indexOf(tokenType);
    872     if (m_fDropAfterTokenButton)
    873         ++iPosition;
    874     order.insert(iPosition, droppedType);
    875 
    876     /* Save updated status-bar indicator order: */
    877     gEDataManager->setStatusBarIndicatorOrder(order, vboxGlobal().managedVMUuid());
    878 }
    879 
    880 int UIStatusBarEditorWindow::position(IndicatorType type) const
    881 {
    882     int iPosition = 0;
    883     foreach (const IndicatorType &iteratedType, m_order)
    884         if (iteratedType == type)
    885             return iPosition;
    886         else
    887             ++iPosition;
    888     return iPosition;
    889 }
    890 
    89152
    89253UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId)
     
    1357518}
    1358519
    1359 #include "UIMachineWindowNormal.moc"
    1360 
Note: See TracChangeset for help on using the changeset viewer.

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