- Timestamp:
- Jul 17, 2014 9:09:10 AM (11 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r52053 r52070 303 303 src/runtime/UIMultiScreenLayout.h \ 304 304 src/runtime/UISession.h \ 305 src/runtime/UIStatusBarEditorWindow.h \ 305 306 src/runtime/UIVMCloseDialog.h \ 306 307 src/runtime/fullscreen/UIKeyboardHandlerFullscreen.h \ … … 482 483 src/runtime/UIMachine.cpp \ 483 484 src/runtime/UIMachineMenuBar.cpp \ 484 src/runtime/ normal/UIMachineWindowNormal.cpp \485 src/runtime/UIStatusBarEditorWindow.cpp \ 485 486 src/selector/UIActionPoolSelector.cpp \ 486 487 src/selector/UIVMDesktop.cpp \ … … 579 580 src/runtime/UIMultiScreenLayout.cpp \ 580 581 src/runtime/UISession.cpp \ 582 src/runtime/UIStatusBarEditorWindow.cpp \ 581 583 src/runtime/UIVMCloseDialog.cpp \ 582 584 src/runtime/fullscreen/UIKeyboardHandlerFullscreen.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIStatusBarEditorWindow.cpp
r52064 r52070 1 1 /* $Id$ */ 2 2 /** @file 3 * 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * UIMachineWindowNormal class implementation 3 * VBox Qt GUI - UIStatusBarEditorWindow class implementation. 6 4 */ 7 5 8 6 /* 9 * Copyright (C) 2010-201 2Oracle Corporation7 * Copyright (C) 2010-2014 Oracle Corporation 10 8 * 11 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 19 17 20 18 /* Qt includes: */ 21 #include <QDesktopWidget>22 #include <QMenuBar>23 #include <QTimer>24 #include <QContextMenuEvent>25 #include <QResizeEvent>26 27 19 #include <QStylePainter> 28 20 #include <QStyleOption> 21 #include <QHBoxLayout> 29 22 #include <QPaintEvent> 23 #include <QMouseEvent> 30 24 #include <QPainter> 25 #include <QPixmap> 31 26 #include <QDrag> 32 27 33 28 /* 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" 34 35 #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_MAC47 # 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"62 36 63 37 … … 125 99 QPoint m_mousePressPosition; 126 100 }; 101 127 102 128 103 /* static */ … … 255 230 } 256 231 257 258 /** QWidget reimplementation259 * 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 Geometry353 * @{ */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: Animation361 * @{ */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 Contents373 * @{ */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: Restrictions385 * @{ */386 /** Holds the cached status-bar button restrictions. */387 QList<IndicatorType> m_restrictions;388 /** @} */389 390 /** @name Contents: Order391 * @{ */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 232 401 233 UIStatusBarEditorWindow::UIStatusBarEditorWindow(QWidget *pParent, const QRect &rect, const QRect &statusBarRect) … … 889 721 } 890 722 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$ */2 1 /** @file 3 * 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * UIMachineWindowNormal class implementation 2 * VBox Qt GUI - UIStatusBarEditorWindow class declaration. 6 3 */ 7 4 8 5 /* 9 * Copyright (C) 2010-201 2Oracle Corporation6 * Copyright (C) 2010-2014 Oracle Corporation 10 7 * 11 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 18 15 */ 19 16 17 #ifndef ___UIStatusBarEditorWindow_h___ 18 #define ___UIStatusBarEditorWindow_h___ 19 20 20 /* 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> 32 24 33 25 /* 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" 50 28 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: */ 30 class UIAnimation; 31 class QHBoxLayout; 32 class QIToolButton; 33 class UIStatusBarEditorButton; 257 34 258 35 /** QWidget reimplementation … … 399 176 }; 400 177 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 25 25 #include <QResizeEvent> 26 26 27 #include <QStylePainter>28 #include <QStyleOption>29 #include <QPaintEvent>30 #include <QPainter>31 #include <QDrag>32 33 27 /* GUI includes: */ 34 28 #include "VBoxGlobal.h" 29 #include "UIMachineWindowNormal.h" 30 #include "UIStatusBarEditorWindow.h" 31 #include "UIActionPoolRuntime.h" 35 32 #include "UIExtraDataManager.h" 36 #include "UISession.h"37 #include "UIActionPoolRuntime.h"38 33 #include "UIIndicatorsPool.h" 39 34 #include "UIKeyboardHandler.h" 40 35 #include "UIMouseHandler.h" 41 36 #include "UIMachineLogic.h" 42 #include "UIMachineWindowNormal.h"43 37 #include "UIMachineView.h" 38 #include "UIIconPool.h" 39 #include "UISession.h" 44 40 #include "QIStatusBar.h" 45 41 #include "QIStatusBarIndicator.h" … … 49 45 #endif /* Q_WS_MAC */ 50 46 51 #include "QIWithRetranslateUI.h"52 #include "QIToolButton.h"53 #include "UIIconPool.h"54 #include "UIConverter.h"55 #include "UIAnimationFramework.h"56 57 47 /* COM includes: */ 58 48 #include "CConsole.h" … … 60 50 #include "CUSBController.h" 61 51 #include "CUSBDeviceFilters.h" 62 63 64 /** QWidget extension65 * 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 else180 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 reimplementation259 * 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 Geometry353 * @{ */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: Animation361 * @{ */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 Contents373 * @{ */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: Restrictions385 * @{ */386 /** Holds the cached status-bar button restrictions. */387 QList<IndicatorType> m_restrictions;388 /** @} */389 390 /** @name Contents: Order391 * @{ */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 else447 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 background471 * 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 possible477 * 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-shadows484 * 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_MAC497 /* 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_WIN603 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 boundaries639 * 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_WIN656 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) const881 {882 int iPosition = 0;883 foreach (const IndicatorType &iteratedType, m_order)884 if (iteratedType == type)885 return iPosition;886 else887 ++iPosition;888 return iPosition;889 }890 891 52 892 53 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId) … … 1357 518 } 1358 519 1359 #include "UIMachineWindowNormal.moc"1360
Note:
See TracChangeset
for help on using the changeset viewer.