Changeset 91003 in vbox for trunk/src/VBox
- Timestamp:
- Aug 30, 2021 3:40:14 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 146643
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 11 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r90941 r91003 1344 1344 src/globals/UICloudNetworkingStuff.cpp \ 1345 1345 src/globals/UICommon.cpp \ 1346 src/globals/UICursor.cpp \ 1346 1347 src/globals/UICustomFileSystemModel.cpp \ 1347 1348 src/globals/UIDefs.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/extensions/QISplitter.cpp
r88792 r91003 24 24 /* GUI includes: */ 25 25 #include "QISplitter.h" 26 #include "UICommon.h" 26 #ifdef VBOX_WS_MAC 27 # include "UICursor.h" 28 #endif 27 29 28 30 … … 325 327 { 326 328 m_fHandleGrabbed = true; 327 UIC ommon::setCursor(this, Qt::SplitHCursor);329 UICursor::setCursor(this, Qt::SplitHCursor); 328 330 qApp->postEvent(pHandle, new QMouseEvent(newME)); 329 331 return true; … … 337 339 && pMouseEvent->buttons().testFlag(Qt::LeftButton))) 338 340 { 339 UIC ommon::setCursor(this, Qt::SplitHCursor);341 UICursor::setCursor(this, Qt::SplitHCursor); 340 342 qApp->postEvent(pHandle, new QMouseEvent(newME)); 341 343 return true; … … 345 347 /* If not, reset the state. */ 346 348 m_fHandleGrabbed = false; 347 UIC ommon::setCursor(this, Qt::ArrowCursor);349 UICursor::setCursor(this, Qt::ArrowCursor); 348 350 } 349 351 } … … 356 358 { 357 359 m_fHandleGrabbed = false; 358 UIC ommon::setCursor(this, Qt::ArrowCursor);360 UICursor::setCursor(this, Qt::ArrowCursor); 359 361 break; 360 362 } -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.cpp
r90967 r91003 1737 1737 } 1738 1738 1739 /* static */1740 void UICommon::setCursor(QWidget *pWidget, const QCursor &cursor)1741 {1742 if (!pWidget)1743 return;1744 1745 #ifdef VBOX_WS_X111746 /* As reported in https://www.virtualbox.org/ticket/16348,1747 * in X11 QWidget::setCursor(..) call uses RENDER1748 * extension. Qt (before 5.11) fails to handle the case where the mentioned extension1749 * is missing. Please see https://codereview.qt-project.org/#/c/225665/ for Qt patch: */1750 if ((UICommon::qtRTMajorVersion() < 5) ||1751 (UICommon::qtRTMajorVersion() == 5 && UICommon::qtRTMinorVersion() < 11))1752 {1753 if (X11CheckExtension("RENDER"))1754 pWidget->setCursor(cursor);1755 }1756 else1757 {1758 pWidget->setCursor(cursor);1759 }1760 #else1761 pWidget->setCursor(cursor);1762 #endif1763 }1764 1765 /* static */1766 void UICommon::setCursor(QGraphicsWidget *pWidget, const QCursor &cursor)1767 {1768 if (!pWidget)1769 return;1770 1771 #ifdef VBOX_WS_X111772 /* As reported in https://www.virtualbox.org/ticket/16348,1773 * in X11 QGraphicsWidget::setCursor(..) call uses RENDER1774 * extension. Qt (before 5.11) fails to handle the case where the mentioned extension1775 * is missing. Please see https://codereview.qt-project.org/#/c/225665/ for Qt patch: */1776 if ((UICommon::qtRTMajorVersion() < 5) ||1777 (UICommon::qtRTMajorVersion() == 5 && UICommon::qtRTMinorVersion() < 11))1778 {1779 if (X11CheckExtension("RENDER"))1780 pWidget->setCursor(cursor);1781 }1782 else1783 {1784 pWidget->setCursor(cursor);1785 }1786 #else1787 pWidget->setCursor(cursor);1788 #endif1789 }1790 1791 /* static */1792 void UICommon::unsetCursor(QWidget *pWidget)1793 {1794 if (!pWidget)1795 return;1796 1797 #ifdef VBOX_WS_X111798 /* As reported in https://www.virtualbox.org/ticket/16348,1799 * in X11 QWidget::unsetCursor(..) call uses RENDER1800 * extension. Qt (before 5.11) fails to handle the case where the mentioned extension1801 * is missing. Please see https://codereview.qt-project.org/#/c/225665/ for Qt patch: */1802 if ((UICommon::qtRTMajorVersion() < 5) ||1803 (UICommon::qtRTMajorVersion() == 5 && UICommon::qtRTMinorVersion() < 11))1804 {1805 if (X11CheckExtension("RENDER"))1806 pWidget->unsetCursor();1807 }1808 else1809 {1810 pWidget->unsetCursor();1811 }1812 #else1813 pWidget->unsetCursor();1814 #endif1815 }1816 1817 /* static */1818 void UICommon::unsetCursor(QGraphicsWidget *pWidget)1819 {1820 if (!pWidget)1821 return;1822 1823 #ifdef VBOX_WS_X111824 /* As reported in https://www.virtualbox.org/ticket/16348,1825 * in X11 QGraphicsWidget::unsetCursor(..) call uses RENDER1826 * extension. Qt (before 5.11) fails to handle the case where the mentioned extension1827 * is missing. Please see https://codereview.qt-project.org/#/c/225665/ for Qt patch: */1828 if ((UICommon::qtRTMajorVersion() < 5) ||1829 (UICommon::qtRTMajorVersion() == 5 && UICommon::qtRTMinorVersion() < 11))1830 {1831 if (X11CheckExtension("RENDER"))1832 pWidget->unsetCursor();1833 }1834 else1835 {1836 pWidget->unsetCursor();1837 }1838 #else1839 pWidget->unsetCursor();1840 #endif1841 }1842 1843 1844 1739 #if defined(VBOX_WS_X11) 1845 1740 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICommon.h
r90967 r91003 342 342 /** Activates the specified window with given @a wId. Can @a fSwitchDesktop if requested. */ 343 343 static bool activateWindow(WId wId, bool fSwitchDesktop = true); 344 345 /** Does some checks on certain platforms before calling QWidget::setCursor(...). */346 static void setCursor(QWidget *pWidget, const QCursor &cursor);347 static void setCursor(QGraphicsWidget *pWidget, const QCursor &cursor);348 static void unsetCursor(QWidget *pWidget);349 static void unsetCursor(QGraphicsWidget *pWidget);350 344 351 345 #ifdef VBOX_WS_X11 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICursor.cpp
r90967 r91003 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIC ommon classimplementation.3 * VBox Qt GUI - UICursor namespace implementation. 4 4 */ 5 5 … … 17 17 18 18 /* Qt includes: */ 19 #include <QDesktopServices>20 #include <QDir>21 #include <QFileDialog>22 19 #include <QGraphicsWidget> 23 #include <QLibraryInfo> 24 #include <QLocale> 25 #include <QMenu> 26 #include <QMutex> 27 #include <QPainter> 28 #include <QProcess> 29 #include <QProgressDialog> 30 #include <QSessionManager> 31 #include <QSettings> 32 #include <QSpinBox> 33 #include <QStandardPaths> 34 #include <QStyleOptionSpinBox> 35 #include <QThread> 36 #include <QTimer> 37 #include <QToolButton> 38 #include <QToolTip> 39 #include <QTranslator> 40 #ifdef VBOX_WS_WIN 41 # include <QEventLoop> 42 # include <QStyleFactory> 43 #endif 44 #ifdef VBOX_WS_X11 45 # include <QScreen> 46 # include <QScrollBar> 47 # include <QTextBrowser> 48 # include <QX11Info> 49 #endif 50 #ifdef VBOX_GUI_WITH_PIDFILE 51 # include <QTextStream> 52 #endif 20 #include <QWidget> 53 21 54 22 /* GUI includes: */ 55 #include "QIDialogButtonBox.h"56 #include "QIFileDialog.h"57 #include "QIMessageBox.h"58 #include "QIWithRestorableGeometry.h"59 23 #include "UICommon.h" 60 #include "UIConverter.h" 61 #include "UIDesktopWidgetWatchdog.h" 62 #include "UIExtraDataManager.h" 63 #include "UIFDCreationDialog.h" 64 #include "UIIconPool.h" 65 #include "UIMedium.h" 66 #include "UIMediumEnumerator.h" 67 #include "UIMediumSelector.h" 68 #include "UIMessageCenter.h" 69 #include "UIModalWindowManager.h" 70 #include "UINotificationCenter.h" 71 #include "UIPopupCenter.h" 72 #include "UIShortcutPool.h" 73 #include "UIThreadPool.h" 74 #include "UITranslator.h" 75 #include "UIVirtualBoxClientEventHandler.h" 76 #include "UIVirtualBoxEventHandler.h" 77 #include "UIVisoCreator.h" 78 #include "UIWizardNewVD.h" 79 #include "VBoxLicenseViewer.h" 80 #ifdef VBOX_WS_MAC 81 # include "UIMachineWindowFullscreen.h" 82 # include "UIMachineWindowSeamless.h" 83 # include "VBoxUtils-darwin.h" 84 #endif 85 #ifdef VBOX_WS_X11 86 # include "UIHostComboEditor.h" 87 # include "VBoxX11Helper.h" 88 #endif 89 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 90 # include "UINetworkRequestManager.h" 91 # include "UIUpdateManager.h" 92 #endif 93 94 /* COM includes: */ 95 #include "CAudioAdapter.h" 96 #include "CBIOSSettings.h" 97 #include "CCloudMachine.h" 98 #include "CConsole.h" 99 #include "CExtPack.h" 100 #include "CExtPackFile.h" 101 #include "CExtPackManager.h" 102 #include "CHostUSBDevice.h" 103 #include "CHostVideoInputDevice.h" 104 #include "CMachine.h" 105 #include "CMediumAttachment.h" 106 #include "CNetworkAdapter.h" 107 #include "CSerialPort.h" 108 #include "CSharedFolder.h" 109 #include "CSnapshot.h" 110 #include "CStorageController.h" 111 #include "CSystemProperties.h" 112 #include "CUSBController.h" 113 #include "CUSBDevice.h" 114 #include "CUSBDeviceFilter.h" 115 #include "CUSBDeviceFilters.h" 116 #include "CVRDEServer.h" 117 118 /* Other VBox includes: */ 119 #include <iprt/asm.h> 120 #include <iprt/ctype.h> 121 #include <iprt/env.h> 122 #include <iprt/err.h> 123 #include <iprt/file.h> 124 #include <iprt/getopt.h> 125 #include <iprt/ldr.h> 126 #include <iprt/param.h> 127 #include <iprt/path.h> 128 #include <iprt/stream.h> 129 #include <iprt/system.h> 130 #ifdef VBOX_WS_X11 131 # include <iprt/mem.h> 132 #endif 133 #include <VBox/sup.h> 134 #include <VBox/VBoxOGL.h> 135 #include <VBox/vd.h> 136 #include <VBox/com/Guid.h> 137 138 /* VirtualBox interface declarations: */ 139 #include <VBox/com/VirtualBox.h> 140 141 /* External includes: */ 142 #ifdef VBOX_WS_WIN 143 # include <iprt/win/shlobj.h> 144 #endif 145 #ifdef VBOX_WS_X11 146 # include <xcb/xcb.h> 147 #endif 148 149 /* External includes: */ 150 #include <math.h> 151 #ifdef VBOX_WS_MAC 152 # include <sys/utsname.h> 153 #endif 154 #ifdef VBOX_WS_X11 155 // WORKAROUND: 156 // typedef CARD8 BOOL in Xmd.h conflicts with #define BOOL PRBool 157 // in COMDefs.h. A better fix would be to isolate X11-specific 158 // stuff by placing XX* helpers below to a separate source file. 159 # undef BOOL 160 # include <X11/X.h> 161 # include <X11/Xmd.h> 162 # include <X11/Xlib.h> 163 # include <X11/Xatom.h> 164 # include <X11/Xutil.h> 165 # include <X11/extensions/Xinerama.h> 166 # define BOOL PRBool 167 #endif 168 169 /* Namespaces: */ 170 using namespace UIExtraDataDefs; 171 using namespace UIMediumDefs; 24 #include "UICursor.h" 172 25 173 26 174 27 /* static */ 175 UICommon *UICommon::s_pInstance = 0; 176 177 /* static */ 178 void UICommon::create(UIType enmType) 179 { 180 /* Make sure instance is NOT created yet: */ 181 AssertReturnVoid(!s_pInstance); 182 183 /* Create instance: */ 184 new UICommon(enmType); 185 /* Prepare instance: */ 186 s_pInstance->prepare(); 187 } 188 189 /* static */ 190 void UICommon::destroy() 191 { 192 /* Make sure instance is NOT destroyed yet: */ 193 AssertPtrReturnVoid(s_pInstance); 194 195 /* Cleanup instance: 196 * 1. By default, automatically on QApplication::aboutToQuit() signal. 197 * 2. But if QApplication was not started at all and we perform 198 * early shutdown, we should do cleanup ourselves. */ 199 if (s_pInstance->isValid()) 200 s_pInstance->cleanup(); 201 /* Destroy instance: */ 202 delete s_pInstance; 203 } 204 205 UICommon::UICommon(UIType enmType) 206 : m_enmType(enmType) 207 , m_fValid(false) 208 , m_fCleaningUp(false) 209 #ifdef VBOX_WS_WIN 210 , m_fDataCommitted(false) 211 #endif 212 #ifdef VBOX_WS_MAC 213 , m_enmMacOSVersion(MacOSXRelease_Old) 214 #endif 215 #ifdef VBOX_WS_X11 216 , m_enmWindowManagerType(X11WMType_Unknown) 217 , m_fCompositingManagerRunning(false) 218 #endif 219 , m_fSeparateProcess(false) 220 , m_fShowStartVMErrors(true) 221 #if defined(DEBUG_bird) 222 , m_fAgressiveCaching(false) 223 #else 224 , m_fAgressiveCaching(true) 225 #endif 226 , m_fRestoreCurrentSnapshot(false) 227 , m_fDisablePatm(false) 228 , m_fDisableCsam(false) 229 , m_fRecompileSupervisor(false) 230 , m_fRecompileUser(false) 231 , m_fExecuteAllInIem(false) 232 , m_uWarpPct(100) 233 #ifdef VBOX_WITH_DEBUGGER_GUI 234 , m_fDbgEnabled(0) 235 , m_fDbgAutoShow(0) 236 , m_fDbgAutoShowCommandLine(0) 237 , m_fDbgAutoShowStatistics(0) 238 , m_hVBoxDbg(NIL_RTLDRMOD) 239 , m_enmLaunchRunning(LaunchRunning_Default) 240 #endif 241 , m_fSettingsPwSet(false) 242 , m_fWrappersValid(false) 243 , m_fVBoxSVCAvailable(true) 244 , m_pThreadPool(0) 245 , m_pThreadPoolCloud(0) 246 , m_pIconPool(0) 247 , m_pMediumEnumerator(0) 248 { 249 /* Assign instance: */ 250 s_pInstance = this; 251 } 252 253 UICommon::~UICommon() 254 { 255 /* Unassign instance: */ 256 s_pInstance = 0; 257 } 258 259 void UICommon::prepare() 260 { 261 /* Make sure QApplication cleanup us on exit: */ 262 qApp->setFallbackSessionManagementEnabled(false); 263 connect(qApp, &QGuiApplication::aboutToQuit, 264 this, &UICommon::sltCleanup); 265 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS1 266 /* Make sure we handle host OS session shutdown as well: */ 267 connect(qApp, &QGuiApplication::commitDataRequest, 268 this, &UICommon::sltHandleCommitDataRequest); 269 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */ 270 271 #ifdef VBOX_WS_MAC 272 /* Determine OS release early: */ 273 m_enmMacOSVersion = determineOsRelease(); 274 #endif /* VBOX_WS_MAC */ 275 276 /* Create converter: */ 277 UIConverter::create(); 278 279 /* Create desktop-widget watchdog: */ 280 UIDesktopWidgetWatchdog::create(); 281 282 /* Create message-center: */ 283 UIMessageCenter::create(); 284 /* Create popup-center: */ 285 UIPopupCenter::create(); 286 287 /* Prepare general icon-pool: */ 288 m_pIconPool = new UIIconPoolGeneral; 289 290 /* Load translation based on the current locale: */ 291 UITranslator::loadLanguage(); 292 293 HRESULT rc = COMBase::InitializeCOM(true); 294 if (FAILED(rc)) 295 { 296 #ifdef VBOX_WITH_XPCOM 297 if (rc == NS_ERROR_FILE_ACCESS_DENIED) 298 { 299 char szHome[RTPATH_MAX] = ""; 300 com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome)); 301 msgCenter().cannotInitUserHome(QString(szHome)); 302 } 303 else 304 #endif 305 msgCenter().cannotInitCOM(rc); 306 return; 307 } 308 309 /* Make sure VirtualBoxClient instance created: */ 310 m_comVBoxClient.createInstance(CLSID_VirtualBoxClient); 311 if (!m_comVBoxClient.isOk()) 312 { 313 msgCenter().cannotCreateVirtualBoxClient(m_comVBoxClient); 314 return; 315 } 316 /* Make sure VirtualBox instance acquired: */ 317 m_comVBox = m_comVBoxClient.GetVirtualBox(); 318 if (!m_comVBoxClient.isOk()) 319 { 320 msgCenter().cannotAcquireVirtualBox(m_comVBoxClient); 321 return; 322 } 323 /* Init wrappers: */ 324 comWrappersReinit(); 325 326 /* Watch for the VBoxSVC availability changes: */ 327 connect(gVBoxClientEvents, &UIVirtualBoxClientEventHandler::sigVBoxSVCAvailabilityChange, 328 this, &UICommon::sltHandleVBoxSVCAvailabilityChange); 329 330 /* Prepare thread-pool instances: */ 331 m_pThreadPool = new UIThreadPool(3 /* worker count */, 5000 /* worker timeout */); 332 m_pThreadPoolCloud = new UIThreadPool(2 /* worker count */, 1000 /* worker timeout */); 333 334 #ifdef VBOX_WS_WIN 335 /* Load color theme: */ 336 loadColorTheme(); 337 #endif 338 339 /* Load translation based on the user settings: */ 340 QString strLanguageId = gEDataManager->languageId(); 341 if (!strLanguageId.isNull()) 342 UITranslator::loadLanguage(strLanguageId); 343 344 retranslateUi(); 345 346 connect(gEDataManager, &UIExtraDataManager::sigLanguageChange, 347 this, &UICommon::sltGUILanguageChange); 348 349 qApp->installEventFilter(this); 350 351 /* process command line */ 352 353 UIVisualStateType visualStateType = UIVisualStateType_Invalid; 354 355 #ifdef VBOX_WS_X11 356 /* Check whether we have compositing manager running: */ 357 m_fCompositingManagerRunning = X11IsCompositingManagerRunning(); 358 359 /* Acquire current Window Manager type: */ 360 m_enmWindowManagerType = X11WindowManagerType(); 361 #endif /* VBOX_WS_X11 */ 362 363 #ifdef VBOX_WITH_DEBUGGER_GUI 364 # ifdef VBOX_WITH_DEBUGGER_GUI_MENU 365 initDebuggerVar(&m_fDbgEnabled, "VBOX_GUI_DBG_ENABLED", GUI_Dbg_Enabled, true); 366 # else 367 initDebuggerVar(&m_fDbgEnabled, "VBOX_GUI_DBG_ENABLED", GUI_Dbg_Enabled, false); 368 # endif 369 initDebuggerVar(&m_fDbgAutoShow, "VBOX_GUI_DBG_AUTO_SHOW", GUI_Dbg_AutoShow, false); 370 m_fDbgAutoShowCommandLine = m_fDbgAutoShowStatistics = m_fDbgAutoShow; 371 #endif 372 373 /* 374 * Parse the command line options. 375 * 376 * This is a little sloppy but we're trying to tighten it up. Unfortuately, 377 * both on X11 and darwin (IIRC) there might be additional arguments aimed 378 * for client libraries with GUI processes. So, using RTGetOpt or similar 379 * is a bit hard since we have to cope with unknown options. 380 */ 381 m_fShowStartVMErrors = true; 382 bool startVM = false; 383 bool fSeparateProcess = false; 384 QString vmNameOrUuid; 385 386 const QStringList &arguments = QCoreApplication::arguments(); 387 const int argc = arguments.size(); 388 int i = 1; 389 while (i < argc) 390 { 391 const QByteArray &argBytes = arguments.at(i).toUtf8(); 392 const char *arg = argBytes.constData(); 393 enum { OptType_Unknown, OptType_VMRunner, OptType_VMSelector, OptType_MaybeBoth } enmOptType = OptType_Unknown; 394 /* NOTE: the check here must match the corresponding check for the 395 * options to start a VM in main.cpp and hardenedmain.cpp exactly, 396 * otherwise there will be weird error messages. */ 397 if ( !::strcmp(arg, "--startvm") 398 || !::strcmp(arg, "-startvm")) 399 { 400 enmOptType = OptType_VMRunner; 401 if (++i < argc) 402 { 403 vmNameOrUuid = arguments.at(i); 404 startVM = true; 405 } 406 } 407 else if (!::strcmp(arg, "-separate") || !::strcmp(arg, "--separate")) 408 { 409 enmOptType = OptType_VMRunner; 410 fSeparateProcess = true; 411 } 412 #ifdef VBOX_GUI_WITH_PIDFILE 413 else if (!::strcmp(arg, "-pidfile") || !::strcmp(arg, "--pidfile")) 414 { 415 enmOptType = OptType_MaybeBoth; 416 if (++i < argc) 417 m_strPidFile = arguments.at(i); 418 } 419 #endif /* VBOX_GUI_WITH_PIDFILE */ 420 /* Visual state type options: */ 421 else if (!::strcmp(arg, "-normal") || !::strcmp(arg, "--normal")) 422 { 423 enmOptType = OptType_MaybeBoth; 424 visualStateType = UIVisualStateType_Normal; 425 } 426 else if (!::strcmp(arg, "-fullscreen") || !::strcmp(arg, "--fullscreen")) 427 { 428 enmOptType = OptType_MaybeBoth; 429 visualStateType = UIVisualStateType_Fullscreen; 430 } 431 else if (!::strcmp(arg, "-seamless") || !::strcmp(arg, "--seamless")) 432 { 433 enmOptType = OptType_MaybeBoth; 434 visualStateType = UIVisualStateType_Seamless; 435 } 436 else if (!::strcmp(arg, "-scale") || !::strcmp(arg, "--scale")) 437 { 438 enmOptType = OptType_MaybeBoth; 439 visualStateType = UIVisualStateType_Scale; 440 } 441 /* Passwords: */ 442 else if (!::strcmp(arg, "--settingspw")) 443 { 444 enmOptType = OptType_MaybeBoth; 445 if (++i < argc) 446 { 447 RTStrCopy(m_astrSettingsPw, sizeof(m_astrSettingsPw), arguments.at(i).toLocal8Bit().constData()); 448 m_fSettingsPwSet = true; 449 } 450 } 451 else if (!::strcmp(arg, "--settingspwfile")) 452 { 453 enmOptType = OptType_MaybeBoth; 454 if (++i < argc) 455 { 456 const QByteArray &argFileBytes = arguments.at(i).toLocal8Bit(); 457 const char *pszFile = argFileBytes.constData(); 458 bool fStdIn = !::strcmp(pszFile, "stdin"); 459 int vrc = VINF_SUCCESS; 460 PRTSTREAM pStrm; 461 if (!fStdIn) 462 vrc = RTStrmOpen(pszFile, "r", &pStrm); 463 else 464 pStrm = g_pStdIn; 465 if (RT_SUCCESS(vrc)) 466 { 467 size_t cbFile; 468 vrc = RTStrmReadEx(pStrm, m_astrSettingsPw, sizeof(m_astrSettingsPw) - 1, &cbFile); 469 if (RT_SUCCESS(vrc)) 470 { 471 if (cbFile >= sizeof(m_astrSettingsPw) - 1) 472 cbFile = sizeof(m_astrSettingsPw) - 1; 473 unsigned i; 474 for (i = 0; i < cbFile && !RT_C_IS_CNTRL(m_astrSettingsPw[i]); i++) 475 ; 476 m_astrSettingsPw[i] = '\0'; 477 m_fSettingsPwSet = true; 478 } 479 if (!fStdIn) 480 RTStrmClose(pStrm); 481 } 482 } 483 } 484 /* Misc options: */ 485 else if (!::strcmp(arg, "-comment") || !::strcmp(arg, "--comment")) 486 { 487 enmOptType = OptType_MaybeBoth; 488 ++i; 489 } 490 else if (!::strcmp(arg, "--no-startvm-errormsgbox")) 491 { 492 enmOptType = OptType_VMRunner; 493 m_fShowStartVMErrors = false; 494 } 495 else if (!::strcmp(arg, "--aggressive-caching")) 496 { 497 enmOptType = OptType_MaybeBoth; 498 m_fAgressiveCaching = true; 499 } 500 else if (!::strcmp(arg, "--no-aggressive-caching")) 501 { 502 enmOptType = OptType_MaybeBoth; 503 m_fAgressiveCaching = false; 504 } 505 else if (!::strcmp(arg, "--restore-current")) 506 { 507 enmOptType = OptType_VMRunner; 508 m_fRestoreCurrentSnapshot = true; 509 } 510 /* Ad hoc VM reconfig options: */ 511 else if (!::strcmp(arg, "--fda")) 512 { 513 enmOptType = OptType_VMRunner; 514 if (++i < argc) 515 m_uFloppyImage = arguments.at(i); 516 } 517 else if (!::strcmp(arg, "--dvd") || !::strcmp(arg, "--cdrom")) 518 { 519 enmOptType = OptType_VMRunner; 520 if (++i < argc) 521 m_uDvdImage = arguments.at(i); 522 } 523 /* VMM Options: */ 524 else if (!::strcmp(arg, "--disable-patm")) 525 { 526 enmOptType = OptType_VMRunner; 527 m_fDisablePatm = true; 528 } 529 else if (!::strcmp(arg, "--disable-csam")) 530 { 531 enmOptType = OptType_VMRunner; 532 m_fDisableCsam = true; 533 } 534 else if (!::strcmp(arg, "--recompile-supervisor")) 535 { 536 enmOptType = OptType_VMRunner; 537 m_fRecompileSupervisor = true; 538 } 539 else if (!::strcmp(arg, "--recompile-user")) 540 { 541 enmOptType = OptType_VMRunner; 542 m_fRecompileUser = true; 543 } 544 else if (!::strcmp(arg, "--recompile-all")) 545 { 546 enmOptType = OptType_VMRunner; 547 m_fDisablePatm = m_fDisableCsam = m_fRecompileSupervisor = m_fRecompileUser = true; 548 } 549 else if (!::strcmp(arg, "--execute-all-in-iem")) 550 { 551 enmOptType = OptType_VMRunner; 552 m_fDisablePatm = m_fDisableCsam = m_fExecuteAllInIem = true; 553 } 554 else if (!::strcmp(arg, "--warp-pct")) 555 { 556 enmOptType = OptType_VMRunner; 557 if (++i < argc) 558 m_uWarpPct = RTStrToUInt32(arguments.at(i).toLocal8Bit().constData()); 559 } 560 #ifdef VBOX_WITH_DEBUGGER_GUI 561 /* Debugger/Debugging options: */ 562 else if (!::strcmp(arg, "-dbg") || !::strcmp(arg, "--dbg")) 563 { 564 enmOptType = OptType_VMRunner; 565 setDebuggerVar(&m_fDbgEnabled, true); 566 } 567 else if (!::strcmp( arg, "-debug") || !::strcmp(arg, "--debug")) 568 { 569 enmOptType = OptType_VMRunner; 570 setDebuggerVar(&m_fDbgEnabled, true); 571 setDebuggerVar(&m_fDbgAutoShow, true); 572 setDebuggerVar(&m_fDbgAutoShowCommandLine, true); 573 setDebuggerVar(&m_fDbgAutoShowStatistics, true); 574 } 575 else if (!::strcmp(arg, "--debug-command-line")) 576 { 577 enmOptType = OptType_VMRunner; 578 setDebuggerVar(&m_fDbgEnabled, true); 579 setDebuggerVar(&m_fDbgAutoShow, true); 580 setDebuggerVar(&m_fDbgAutoShowCommandLine, true); 581 } 582 else if (!::strcmp(arg, "--debug-statistics")) 583 { 584 enmOptType = OptType_VMRunner; 585 setDebuggerVar(&m_fDbgEnabled, true); 586 setDebuggerVar(&m_fDbgAutoShow, true); 587 setDebuggerVar(&m_fDbgAutoShowStatistics, true); 588 } 589 else if (!::strcmp(arg, "--statistics-expand") || !::strcmp(arg, "--stats-expand")) 590 { 591 enmOptType = OptType_VMRunner; 592 if (++i < argc) 593 { 594 if (!m_strDbgStatisticsExpand.isEmpty()) 595 m_strDbgStatisticsExpand.append('|'); 596 m_strDbgStatisticsExpand.append(arguments.at(i)); 597 } 598 } 599 else if (!::strncmp(arg, RT_STR_TUPLE("--statistics-expand=")) || !::strncmp(arg, RT_STR_TUPLE("--stats-expand="))) 600 { 601 enmOptType = OptType_VMRunner; 602 if (!m_strDbgStatisticsExpand.isEmpty()) 603 m_strDbgStatisticsExpand.append('|'); 604 m_strDbgStatisticsExpand.append(arguments.at(i).section('=', 1)); 605 } 606 else if (!::strcmp(arg, "--statistics-filter") || !::strcmp(arg, "--stats-filter")) 607 { 608 enmOptType = OptType_VMRunner; 609 if (++i < argc) 610 m_strDbgStatisticsFilter = arguments.at(i); 611 } 612 else if (!::strncmp(arg, RT_STR_TUPLE("--statistics-filter=")) || !::strncmp(arg, RT_STR_TUPLE("--stats-filter="))) 613 { 614 enmOptType = OptType_VMRunner; 615 m_strDbgStatisticsFilter = arguments.at(i).section('=', 1); 616 } 617 else if (!::strcmp(arg, "-no-debug") || !::strcmp(arg, "--no-debug")) 618 { 619 enmOptType = OptType_VMRunner; 620 setDebuggerVar(&m_fDbgEnabled, false); 621 setDebuggerVar(&m_fDbgAutoShow, false); 622 setDebuggerVar(&m_fDbgAutoShowCommandLine, false); 623 setDebuggerVar(&m_fDbgAutoShowStatistics, false); 624 } 625 /* Not quite debug options, but they're only useful with the debugger bits. */ 626 else if (!::strcmp(arg, "--start-paused")) 627 { 628 enmOptType = OptType_VMRunner; 629 m_enmLaunchRunning = LaunchRunning_No; 630 } 631 else if (!::strcmp(arg, "--start-running")) 632 { 633 enmOptType = OptType_VMRunner; 634 m_enmLaunchRunning = LaunchRunning_Yes; 635 } 636 #endif 637 if (enmOptType == OptType_VMRunner && m_enmType != UIType_RuntimeUI) 638 msgCenter().warnAboutUnrelatedOptionType(arg); 639 640 i++; 641 } 642 643 if (m_enmType == UIType_RuntimeUI && startVM) 644 { 645 /* m_fSeparateProcess makes sense only if a VM is started. */ 646 m_fSeparateProcess = fSeparateProcess; 647 648 /* Search for corresponding VM: */ 649 QUuid uuid = QUuid(vmNameOrUuid); 650 const CMachine machine = m_comVBox.FindMachine(vmNameOrUuid); 651 if (!uuid.isNull()) 652 { 653 if (machine.isNull() && showStartVMErrors()) 654 return msgCenter().cannotFindMachineById(m_comVBox, vmNameOrUuid); 655 } 656 else 657 { 658 if (machine.isNull() && showStartVMErrors()) 659 return msgCenter().cannotFindMachineByName(m_comVBox, vmNameOrUuid); 660 } 661 m_strManagedVMId = machine.GetId(); 662 663 if (m_fSeparateProcess) 664 { 665 /* Create a log file for VirtualBoxVM process. */ 666 QString str = machine.GetLogFolder(); 667 com::Utf8Str logDir(str.toUtf8().constData()); 668 669 /* make sure the Logs folder exists */ 670 if (!RTDirExists(logDir.c_str())) 671 RTDirCreateFullPath(logDir.c_str(), 0700); 672 673 com::Utf8Str logFile = com::Utf8StrFmt("%s%cVBoxUI.log", 674 logDir.c_str(), RTPATH_DELIMITER); 675 676 com::VBoxLogRelCreate("GUI (separate)", logFile.c_str(), 677 RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_RESTRICT_GROUPS, 678 "all all.restrict -default.restrict", 679 "VBOX_RELEASE_LOG", RTLOGDEST_FILE, 680 32768 /* cMaxEntriesPerGroup */, 681 0 /* cHistory */, 0 /* uHistoryFileTime */, 682 0 /* uHistoryFileSize */, NULL); 683 } 684 } 685 686 /* For Selector UI: */ 687 if (uiType() == UIType_SelectorUI) 688 { 689 /* We should create separate logging file for VM selector: */ 690 char szLogFile[RTPATH_MAX]; 691 const char *pszLogFile = NULL; 692 com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile)); 693 RTPathAppend(szLogFile, sizeof(szLogFile), "selectorwindow.log"); 694 pszLogFile = szLogFile; 695 /* Create release logger, to file: */ 696 com::VBoxLogRelCreate("GUI VM Selector Window", 697 pszLogFile, 698 RTLOGFLAGS_PREFIX_TIME_PROG, 699 "all", 700 "VBOX_GUI_SELECTORWINDOW_RELEASE_LOG", 701 RTLOGDEST_FILE | RTLOGDEST_F_NO_DENY, 702 UINT32_MAX, 703 10, 704 60 * 60, 705 _1M, 706 NULL /*pErrInfo*/); 707 708 LogRel(("Qt version: %s\n", qtRTVersionString().toUtf8().constData())); 709 } 710 711 if (m_fSettingsPwSet) 712 m_comVBox.SetSettingsSecret(m_astrSettingsPw); 713 714 if (visualStateType != UIVisualStateType_Invalid && !m_strManagedVMId.isNull()) 715 gEDataManager->setRequestedVisualState(visualStateType, m_strManagedVMId); 716 717 #ifdef VBOX_WITH_DEBUGGER_GUI 718 /* For Runtime UI: */ 719 if (uiType() == UIType_RuntimeUI) 720 { 721 /* Setup the debugger GUI: */ 722 if (RTEnvExist("VBOX_GUI_NO_DEBUGGER")) 723 m_fDbgEnabled = m_fDbgAutoShow = m_fDbgAutoShowCommandLine = m_fDbgAutoShowStatistics = false; 724 if (m_fDbgEnabled) 725 { 726 RTERRINFOSTATIC ErrInfo; 727 RTErrInfoInitStatic(&ErrInfo); 728 int vrc = SUPR3HardenedLdrLoadAppPriv("VBoxDbg", &m_hVBoxDbg, RTLDRLOAD_FLAGS_LOCAL, &ErrInfo.Core); 729 if (RT_FAILURE(vrc)) 730 { 731 m_hVBoxDbg = NIL_RTLDRMOD; 732 m_fDbgAutoShow = m_fDbgAutoShowCommandLine = m_fDbgAutoShowStatistics = false; 733 LogRel(("Failed to load VBoxDbg, rc=%Rrc - %s\n", vrc, ErrInfo.Core.pszMsg)); 734 } 735 } 736 } 737 #endif 738 739 m_fValid = true; 740 741 /* Create medium-enumerator but don't do any immediate caching: */ 742 m_pMediumEnumerator = new UIMediumEnumerator; 743 { 744 /* Prepare medium-enumerator: */ 745 connect(m_pMediumEnumerator, &UIMediumEnumerator::sigMediumCreated, 746 this, &UICommon::sigMediumCreated); 747 connect(m_pMediumEnumerator, &UIMediumEnumerator::sigMediumDeleted, 748 this, &UICommon::sigMediumDeleted); 749 connect(m_pMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerationStarted, 750 this, &UICommon::sigMediumEnumerationStarted); 751 connect(m_pMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerated, 752 this, &UICommon::sigMediumEnumerated); 753 connect(m_pMediumEnumerator, &UIMediumEnumerator::sigMediumEnumerationFinished, 754 this, &UICommon::sigMediumEnumerationFinished); 755 } 756 757 /* Create shortcut pool: */ 758 UIShortcutPool::create(); 759 760 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 761 /* Create network manager: */ 762 UINetworkRequestManager::create(); 763 764 /* Schedule update manager: */ 765 UIUpdateManager::schedule(); 766 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 767 768 #ifdef RT_OS_LINUX 769 /* Make sure no wrong USB mounted: */ 770 checkForWrongUSBMounted(); 771 #endif /* RT_OS_LINUX */ 772 773 /* Populate the list of medium names to be excluded from the 774 recently used media extra data: */ 775 #if 0 /* bird: This is counter productive as it is _frequently_ necessary to re-insert the 776 viso to refresh the files (like after you rebuilt them on the host). 777 The guest caches ISOs aggressively and files sizes may change. */ 778 m_recentMediaExcludeList << "ad-hoc.viso"; 779 #endif 780 } 781 782 void UICommon::cleanup() 783 { 784 LogRel(("GUI: UICommon: Handling aboutToQuit request..\n")); 785 786 /// @todo Shouldn't that be protected with a mutex or something? 787 /* Remember that the cleanup is in progress preventing any unwanted 788 * stuff which could be called from the other threads: */ 789 m_fCleaningUp = true; 790 791 #ifdef VBOX_WS_WIN 792 /* Ask listeners to commit data if haven't yet: */ 793 if (!m_fDataCommitted) 794 { 795 emit sigAskToCommitData(); 796 m_fDataCommitted = true; 797 } 798 #else 799 /* Ask listeners to commit data: */ 800 emit sigAskToCommitData(); 801 #endif 802 803 #ifdef VBOX_WITH_DEBUGGER_GUI 804 /* For Runtime UI: */ 805 if ( uiType() == UIType_RuntimeUI 806 && m_hVBoxDbg != NIL_RTLDRMOD) 807 { 808 RTLdrClose(m_hVBoxDbg); 809 m_hVBoxDbg = NIL_RTLDRMOD; 810 } 811 #endif 812 813 #ifdef VBOX_GUI_WITH_NETWORK_MANAGER 814 /* Shutdown update manager: */ 815 UIUpdateManager::shutdown(); 816 817 /* Destroy network manager: */ 818 UINetworkRequestManager::destroy(); 819 #endif /* VBOX_GUI_WITH_NETWORK_MANAGER */ 820 821 /* Destroy shortcut pool: */ 822 UIShortcutPool::destroy(); 823 824 #ifdef VBOX_GUI_WITH_PIDFILE 825 deletePidfile(); 826 #endif /* VBOX_GUI_WITH_PIDFILE */ 827 828 /* Starting medium-enumerator cleanup: */ 829 m_meCleanupProtectionToken.lockForWrite(); 830 { 831 /* Destroy medium-enumerator: */ 832 delete m_pMediumEnumerator; 833 m_pMediumEnumerator = 0; 834 } 835 /* Finishing medium-enumerator cleanup: */ 836 m_meCleanupProtectionToken.unlock(); 837 838 /* Destroy the global (VirtualBox and VirtualBoxClient) Main event 839 * handlers which are used in both Manager and Runtime UIs. */ 840 UIVirtualBoxEventHandler::destroy(); 841 UIVirtualBoxClientEventHandler::destroy(); 842 843 /* Destroy the extra-data manager finally after everything 844 * above which could use it already destroyed: */ 845 UIExtraDataManager::destroy(); 846 847 /* Destroy converter: */ 848 UIConverter::destroy(); 849 850 /* Cleanup thread-pools: */ 851 delete m_pThreadPool; 852 m_pThreadPool = 0; 853 delete m_pThreadPoolCloud; 854 m_pThreadPoolCloud = 0; 855 /* Cleanup general icon-pool: */ 856 delete m_pIconPool; 857 m_pIconPool = 0; 858 859 /* Ensure CGuestOSType objects are no longer used: */ 860 m_guestOSFamilyIDs.clear(); 861 m_guestOSTypes.clear(); 862 863 /* Starting COM cleanup: */ 864 m_comCleanupProtectionToken.lockForWrite(); 865 { 866 /* First, make sure we don't use COM any more: */ 867 emit sigAskToDetachCOM(); 868 m_comHost.detach(); 869 m_comVBox.detach(); 870 m_comVBoxClient.detach(); 871 872 /* There may be UIMedium(s)EnumeratedEvent instances still in the message 873 * queue which reference COM objects. Remove them to release those objects 874 * before uninitializing the COM subsystem. */ 875 QApplication::removePostedEvents(this); 876 877 /* Finally cleanup COM itself: */ 878 COMBase::CleanupCOM(); 879 } 880 /* Finishing COM cleanup: */ 881 m_comCleanupProtectionToken.unlock(); 882 883 /* Notify listener it can close UI now: */ 884 emit sigAskToCloseUI(); 885 886 /* Destroy popup-center: */ 887 UIPopupCenter::destroy(); 888 /* Destroy message-center: */ 889 UIMessageCenter::destroy(); 890 891 /* Destroy desktop-widget watchdog: */ 892 UIDesktopWidgetWatchdog::destroy(); 893 894 m_fValid = false; 895 896 LogRel(("GUI: UICommon: aboutToQuit request handled!\n")); 897 } 898 899 /* static */ 900 QString UICommon::qtRTVersionString() 901 { 902 return QString::fromLatin1(qVersion()); 903 } 904 905 /* static */ 906 uint UICommon::qtRTVersion() 907 { 908 const QString strVersionRT = UICommon::qtRTVersionString(); 909 return (strVersionRT.section('.', 0, 0).toInt() << 16) + 910 (strVersionRT.section('.', 1, 1).toInt() << 8) + 911 strVersionRT.section('.', 2, 2).toInt(); 912 } 913 914 /* static */ 915 uint UICommon::qtRTMajorVersion() 916 { 917 return UICommon::qtRTVersionString().section('.', 0, 0).toInt(); 918 } 919 920 /* static */ 921 uint UICommon::qtRTMinorVersion() 922 { 923 return UICommon::qtRTVersionString().section('.', 1, 1).toInt(); 924 } 925 926 /* static */ 927 uint UICommon::qtRTRevisionNumber() 928 { 929 return UICommon::qtRTVersionString().section('.', 2, 2).toInt(); 930 } 931 932 /* static */ 933 QString UICommon::qtCTVersionString() 934 { 935 return QString::fromLatin1(QT_VERSION_STR); 936 } 937 938 /* static */ 939 uint UICommon::qtCTVersion() 940 { 941 const QString strVersionCompiled = UICommon::qtCTVersionString(); 942 return (strVersionCompiled.section('.', 0, 0).toInt() << 16) + 943 (strVersionCompiled.section('.', 1, 1).toInt() << 8) + 944 strVersionCompiled.section('.', 2, 2).toInt(); 945 } 946 947 QString UICommon::vboxVersionString() const 948 { 949 return m_comVBox.GetVersion(); 950 } 951 952 QString UICommon::vboxVersionStringNormalized() const 953 { 954 return m_comVBox.GetVersionNormalized(); 955 } 956 957 bool UICommon::isBeta() const 958 { 959 return vboxVersionString().contains("BETA", Qt::CaseInsensitive); 960 } 961 962 bool UICommon::brandingIsActive(bool fForce /* = false */) 963 { 964 if (fForce) 965 return true; 966 967 if (m_strBrandingConfigFilePath.isEmpty()) 968 { 969 m_strBrandingConfigFilePath = QDir(QApplication::applicationDirPath()).absolutePath(); 970 m_strBrandingConfigFilePath += "/custom/custom.ini"; 971 } 972 973 return QFile::exists(m_strBrandingConfigFilePath); 974 } 975 976 QString UICommon::brandingGetKey(QString strKey) const 977 { 978 QSettings settings(m_strBrandingConfigFilePath, QSettings::IniFormat); 979 return settings.value(QString("%1").arg(strKey)).toString(); 980 } 981 982 #ifdef VBOX_WS_MAC 983 /* static */ 984 MacOSXRelease UICommon::determineOsRelease() 985 { 986 /* Prepare 'utsname' struct: */ 987 utsname info; 988 if (uname(&info) != -1) 989 { 990 /* Compose map of known releases: */ 991 QMap<int, MacOSXRelease> release; 992 release[10] = MacOSXRelease_SnowLeopard; 993 release[11] = MacOSXRelease_Lion; 994 release[12] = MacOSXRelease_MountainLion; 995 release[13] = MacOSXRelease_Mavericks; 996 release[14] = MacOSXRelease_Yosemite; 997 release[15] = MacOSXRelease_ElCapitan; 998 999 /* Cut the major release index of the string we have, s.a. 'man uname': */ 1000 const int iRelease = QString(info.release).section('.', 0, 0).toInt(); 1001 1002 /* Return release if determined, return 'New' if version more recent than latest, return 'Old' otherwise: */ 1003 return release.value(iRelease, iRelease > release.keys().last() ? MacOSXRelease_New : MacOSXRelease_Old); 1004 } 1005 /* Return 'Old' by default: */ 1006 return MacOSXRelease_Old; 1007 } 1008 #endif /* VBOX_WS_MAC */ 1009 1010 #ifdef VBOX_WS_WIN 1011 /* static */ 1012 void UICommon::loadColorTheme() 1013 { 1014 /* Load saved color theme: */ 1015 UIColorThemeType enmColorTheme = gEDataManager->colorTheme(); 1016 1017 /* Check whether we have dark system theme requested: */ 1018 if (enmColorTheme == UIColorThemeType_Auto) 1019 { 1020 QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 1021 QSettings::NativeFormat); 1022 if (settings.value("AppsUseLightTheme") == 0) 1023 enmColorTheme = UIColorThemeType_Dark; 1024 } 1025 1026 /* Check whether dark theme was requested by any means: */ 1027 if (enmColorTheme == UIColorThemeType_Dark) 1028 { 1029 qApp->setStyle(QStyleFactory::create("Fusion")); 1030 QPalette darkPalette; 1031 QColor windowColor1 = QColor(59, 60, 61); 1032 QColor windowColor2 = QColor(63, 64, 65); 1033 QColor baseColor1 = QColor(46, 47, 48); 1034 QColor baseColor2 = QColor(56, 57, 58); 1035 QColor disabledColor = QColor(113, 114, 115); 1036 darkPalette.setColor(QPalette::Window, windowColor1); 1037 darkPalette.setColor(QPalette::WindowText, Qt::white); 1038 darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, disabledColor); 1039 darkPalette.setColor(QPalette::Base, baseColor1); 1040 darkPalette.setColor(QPalette::AlternateBase, baseColor2); 1041 darkPalette.setColor(QPalette::PlaceholderText, disabledColor); 1042 darkPalette.setColor(QPalette::Text, Qt::white); 1043 darkPalette.setColor(QPalette::Disabled, QPalette::Text, disabledColor); 1044 darkPalette.setColor(QPalette::Button, windowColor2); 1045 darkPalette.setColor(QPalette::ButtonText, Qt::white); 1046 darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledColor); 1047 darkPalette.setColor(QPalette::BrightText, Qt::red); 1048 darkPalette.setColor(QPalette::Link, QColor(179, 214, 242)); 1049 darkPalette.setColor(QPalette::Highlight, QColor(29, 84, 92)); 1050 darkPalette.setColor(QPalette::HighlightedText, Qt::white); 1051 darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor); 1052 qApp->setPalette(darkPalette); 1053 qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2b2b2b; border: 1px solid #737373; }"); 1054 } 1055 } 1056 #endif /* VBOX_WS_WIN */ 1057 1058 bool UICommon::processArgs() 1059 { 1060 /* Among those arguments: */ 1061 bool fResult = false; 1062 const QStringList args = qApp->arguments(); 1063 1064 /* We are looking for a list of file URLs passed to the executable: */ 1065 QList<QUrl> listArgUrls; 1066 for (int i = 1; i < args.size(); ++i) 1067 { 1068 /* But we break out after the first parameter, cause there 1069 * could be parameters with arguments (e.g. --comment comment). */ 1070 if (args.at(i).startsWith("-")) 1071 break; 1072 1073 #ifdef VBOX_WS_MAC 1074 const QString strArg = ::darwinResolveAlias(args.at(i)); 1075 #else 1076 const QString strArg = args.at(i); 1077 #endif 1078 1079 /* So if the argument file exists, we add it to URL list: */ 1080 if ( !strArg.isEmpty() 1081 && QFile::exists(strArg)) 1082 listArgUrls << QUrl::fromLocalFile(QFileInfo(strArg).absoluteFilePath()); 1083 } 1084 1085 /* If there are file URLs: */ 1086 if (!listArgUrls.isEmpty()) 1087 { 1088 /* We enumerate them and: */ 1089 for (int i = 0; i < listArgUrls.size(); ++i) 1090 { 1091 /* Check which of them has allowed VM extensions: */ 1092 const QUrl url = listArgUrls.at(i); 1093 const QString strFile = url.toLocalFile(); 1094 if (UICommon::hasAllowedExtension(strFile, VBoxFileExts)) 1095 { 1096 /* So that we could run existing VMs: */ 1097 CVirtualBox comVBox = virtualBox(); 1098 CMachine comMachine = comVBox.FindMachine(strFile); 1099 if (!comMachine.isNull()) 1100 { 1101 fResult = true; 1102 launchMachine(comMachine); 1103 /* And remove their URLs from the ULR list: */ 1104 listArgUrls.removeAll(url); 1105 } 1106 } 1107 } 1108 } 1109 1110 /* And if there are *still* URLs: */ 1111 if (!listArgUrls.isEmpty()) 1112 { 1113 /* We store them, they will be handled later: */ 1114 m_listArgUrls = listArgUrls; 1115 } 1116 1117 return fResult; 1118 } 1119 1120 bool UICommon::argumentUrlsPresent() const 1121 { 1122 return !m_listArgUrls.isEmpty(); 1123 } 1124 1125 QList<QUrl> UICommon::takeArgumentUrls() 1126 { 1127 const QList<QUrl> result = m_listArgUrls; 1128 m_listArgUrls.clear(); 1129 return result; 1130 } 1131 1132 #ifdef VBOX_WITH_DEBUGGER_GUI 1133 1134 bool UICommon::isDebuggerEnabled() const 1135 { 1136 return isDebuggerWorker(&m_fDbgEnabled, GUI_Dbg_Enabled); 1137 } 1138 1139 bool UICommon::isDebuggerAutoShowEnabled() const 1140 { 1141 return isDebuggerWorker(&m_fDbgAutoShow, GUI_Dbg_AutoShow); 1142 } 1143 1144 bool UICommon::isDebuggerAutoShowCommandLineEnabled() const 1145 { 1146 return isDebuggerWorker(&m_fDbgAutoShowCommandLine, GUI_Dbg_AutoShow); 1147 } 1148 1149 bool UICommon::isDebuggerAutoShowStatisticsEnabled() const 1150 { 1151 return isDebuggerWorker(&m_fDbgAutoShowStatistics, GUI_Dbg_AutoShow); 1152 } 1153 1154 #endif /* VBOX_WITH_DEBUGGER_GUI */ 1155 1156 bool UICommon::shouldStartPaused() const 1157 { 1158 #ifdef VBOX_WITH_DEBUGGER_GUI 1159 return m_enmLaunchRunning == LaunchRunning_Default ? isDebuggerAutoShowEnabled() : m_enmLaunchRunning == LaunchRunning_No; 1160 #else 1161 return false; 1162 #endif 1163 } 1164 1165 #ifdef VBOX_GUI_WITH_PIDFILE 1166 1167 void UICommon::createPidfile() 1168 { 1169 if (!m_strPidFile.isEmpty()) 1170 { 1171 const qint64 iPid = qApp->applicationPid(); 1172 QFile file(m_strPidFile); 1173 if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) 1174 { 1175 QTextStream out(&file); 1176 out << iPid << endl; 1177 } 1178 else 1179 LogRel(("Failed to create pid file %s\n", m_strPidFile.toUtf8().constData())); 1180 } 1181 } 1182 1183 void UICommon::deletePidfile() 1184 { 1185 if ( !m_strPidFile.isEmpty() 1186 && QFile::exists(m_strPidFile)) 1187 QFile::remove(m_strPidFile); 1188 } 1189 1190 #endif /* VBOX_GUI_WITH_PIDFILE */ 1191 1192 /* static */ 1193 QString UICommon::helpFile() 1194 { 1195 #if defined (VBOX_WITH_QHELP_VIEWER) 1196 const QString strName = "UserManual"; 1197 const QString strSuffix = "qhc"; 1198 #else 1199 #if defined(VBOX_WS_WIN) 1200 const QString strName = "VirtualBox"; 1201 const QString strSuffix = "chm"; 1202 #elif defined(VBOX_WS_MAC) 1203 const QString strName = "UserManual"; 1204 const QString strSuffix = "pdf"; 1205 #elif defined(VBOX_WS_X11) 1206 //# if defined(VBOX_OSE) || !defined(VBOX_WITH_KCHMVIEWER) 1207 const QString strName = "UserManual"; 1208 const QString strSuffix = "pdf"; 1209 #endif 1210 #endif 1211 /* Where are the docs located? */ 1212 char szDocsPath[RTPATH_MAX]; 1213 int rc = RTPathAppDocs(szDocsPath, sizeof(szDocsPath)); 1214 AssertRC(rc); 1215 1216 /* Make sure that the language is in two letter code. 1217 * Note: if languageId() returns an empty string lang.name() will 1218 * return "C" which is an valid language code. */ 1219 QLocale lang(UITranslator::languageId()); 1220 1221 /* Construct the path and the filename: */ 1222 QString strManual = QString("%1/%2_%3.%4").arg(szDocsPath) 1223 .arg(strName) 1224 .arg(lang.name()) 1225 .arg(strSuffix); 1226 1227 /* Check if a help file with that name exists: */ 1228 QFileInfo fi(strManual); 1229 if (fi.exists()) 1230 return strManual; 1231 1232 /* Fall back to the standard: */ 1233 strManual = QString("%1/%2.%4").arg(szDocsPath) 1234 .arg(strName) 1235 .arg(strSuffix); 1236 return strManual; 1237 } 1238 1239 /* static */ 1240 QString UICommon::documentsPath() 1241 { 1242 QString strPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); 1243 QDir dir(strPath); 1244 if (dir.exists()) 1245 return QDir::cleanPath(dir.canonicalPath()); 1246 else 1247 { 1248 dir.setPath(QDir::homePath() + "/Documents"); 1249 if (dir.exists()) 1250 return QDir::cleanPath(dir.canonicalPath()); 1251 else 1252 return QDir::homePath(); 1253 } 1254 } 1255 1256 /* static */ 1257 bool UICommon::hasAllowedExtension(const QString &strFileName, const QStringList &extensions) 1258 { 1259 foreach (const QString &strExtension, extensions) 1260 if (strFileName.endsWith(strExtension, Qt::CaseInsensitive)) 1261 return true; 1262 return false; 1263 } 1264 1265 /* static */ 1266 QString UICommon::findUniqueFileName(const QString &strFullFolderPath, const QString &strBaseFileName) 1267 { 1268 QDir folder(strFullFolderPath); 1269 if (!folder.exists()) 1270 return strBaseFileName; 1271 QFileInfoList folderContent = folder.entryInfoList(); 1272 QSet<QString> fileNameSet; 1273 foreach (const QFileInfo &fileInfo, folderContent) 1274 { 1275 /* Remove the extension : */ 1276 fileNameSet.insert(fileInfo.completeBaseName()); 1277 } 1278 int iSuffix = 0; 1279 QString strNewName(strBaseFileName); 1280 while (fileNameSet.contains(strNewName)) 1281 { 1282 strNewName = strBaseFileName + QString("_") + QString::number(++iSuffix); 1283 } 1284 return strNewName; 1285 } 1286 1287 /* static */ 1288 QRect UICommon::normalizeGeometry(const QRect &rectangle, const QRegion &boundRegion, bool fCanResize /* = true */) 1289 { 1290 /* Perform direct and flipped search of position for @a rectangle to make sure it is fully contained 1291 * inside @a boundRegion region by moving & resizing (if @a fCanResize is specified) @a rectangle if 1292 * necessary. Selects the minimum shifted result between direct and flipped variants. */ 1293 1294 /* Direct search for normalized rectangle: */ 1295 QRect var1(getNormalized(rectangle, boundRegion, fCanResize)); 1296 1297 /* Flipped search for normalized rectangle: */ 1298 QRect var2(flip(getNormalized(flip(rectangle).boundingRect(), 1299 flip(boundRegion), fCanResize)).boundingRect()); 1300 1301 /* Calculate shift from starting position for both variants: */ 1302 double dLength1 = sqrt(pow((double)(var1.x() - rectangle.x()), (double)2) + 1303 pow((double)(var1.y() - rectangle.y()), (double)2)); 1304 double dLength2 = sqrt(pow((double)(var2.x() - rectangle.x()), (double)2) + 1305 pow((double)(var2.y() - rectangle.y()), (double)2)); 1306 1307 /* Return minimum shifted variant: */ 1308 return dLength1 > dLength2 ? var2 : var1; 1309 } 1310 1311 /* static */ 1312 QRect UICommon::getNormalized(const QRect &rectangle, const QRegion &boundRegion, bool /* fCanResize = true */) 1313 { 1314 /* Ensures that the given rectangle @a rectangle is fully contained within the region @a boundRegion 1315 * by moving @a rectangle if necessary. If @a rectangle is larger than @a boundRegion, top left 1316 * corner of @a rectangle is aligned with the top left corner of maximum available rectangle and, 1317 * if @a fCanResize is true, @a rectangle is shrinked to become fully visible. */ 1318 1319 /* Storing available horizontal sub-rectangles & vertical shifts: */ 1320 const int iWindowVertical = rectangle.center().y(); 1321 QList<QRect> rectanglesList; 1322 QList<int> shiftsList; 1323 foreach (QRect currentItem, boundRegion.rects()) 1324 { 1325 const int iCurrentDelta = qAbs(iWindowVertical - currentItem.center().y()); 1326 const int iShift2Top = currentItem.top() - rectangle.top(); 1327 const int iShift2Bot = currentItem.bottom() - rectangle.bottom(); 1328 1329 int iTtemPosition = 0; 1330 foreach (QRect item, rectanglesList) 1331 { 1332 const int iDelta = qAbs(iWindowVertical - item.center().y()); 1333 if (iDelta > iCurrentDelta) 1334 break; 1335 else 1336 ++iTtemPosition; 1337 } 1338 rectanglesList.insert(iTtemPosition, currentItem); 1339 1340 int iShift2TopPos = 0; 1341 foreach (int iShift, shiftsList) 1342 if (qAbs(iShift) > qAbs(iShift2Top)) 1343 break; 1344 else 1345 ++iShift2TopPos; 1346 shiftsList.insert(iShift2TopPos, iShift2Top); 1347 1348 int iShift2BotPos = 0; 1349 foreach (int iShift, shiftsList) 1350 if (qAbs(iShift) > qAbs(iShift2Bot)) 1351 break; 1352 else 1353 ++iShift2BotPos; 1354 shiftsList.insert(iShift2BotPos, iShift2Bot); 1355 } 1356 1357 /* Trying to find the appropriate place for window: */ 1358 QRect result; 1359 for (int i = -1; i < shiftsList.size(); ++i) 1360 { 1361 /* Move to appropriate vertical: */ 1362 QRect newRectangle(rectangle); 1363 if (i >= 0) 1364 newRectangle.translate(0, shiftsList[i]); 1365 1366 /* Search horizontal shift: */ 1367 int iMaxShift = 0; 1368 foreach (QRect item, rectanglesList) 1369 { 1370 QRect trectangle(newRectangle.translated(item.left() - newRectangle.left(), 0)); 1371 if (!item.intersects(trectangle)) 1372 continue; 1373 1374 if (newRectangle.left() < item.left()) 1375 { 1376 const int iShift = item.left() - newRectangle.left(); 1377 iMaxShift = qAbs(iShift) > qAbs(iMaxShift) ? iShift : iMaxShift; 1378 } 1379 else if (newRectangle.right() > item.right()) 1380 { 1381 const int iShift = item.right() - newRectangle.right(); 1382 iMaxShift = qAbs(iShift) > qAbs(iMaxShift) ? iShift : iMaxShift; 1383 } 1384 } 1385 1386 /* Shift across the horizontal direction: */ 1387 newRectangle.translate(iMaxShift, 0); 1388 1389 /* Check the translated rectangle to feat the rules: */ 1390 if (boundRegion.united(newRectangle) == boundRegion) 1391 result = newRectangle; 1392 1393 if (!result.isNull()) 1394 break; 1395 } 1396 1397 if (result.isNull()) 1398 { 1399 /* Resize window to feat desirable size 1400 * using max of available rectangles: */ 1401 QRect maxRectangle; 1402 quint64 uMaxSquare = 0; 1403 foreach (QRect item, rectanglesList) 1404 { 1405 const quint64 uSquare = item.width() * item.height(); 1406 if (uSquare > uMaxSquare) 1407 { 1408 uMaxSquare = uSquare; 1409 maxRectangle = item; 1410 } 1411 } 1412 1413 result = rectangle; 1414 result.moveTo(maxRectangle.x(), maxRectangle.y()); 1415 if (maxRectangle.right() < result.right()) 1416 result.setRight(maxRectangle.right()); 1417 if (maxRectangle.bottom() < result.bottom()) 1418 result.setBottom(maxRectangle.bottom()); 1419 } 1420 1421 return result; 1422 } 1423 1424 /* static */ 1425 QRegion UICommon::flip(const QRegion ®ion) 1426 { 1427 QRegion result; 1428 QVector<QRect> rectangles(region.rects()); 1429 foreach (QRect rectangle, rectangles) 1430 result += QRect(rectangle.y(), rectangle.x(), 1431 rectangle.height(), rectangle.width()); 1432 return result; 1433 } 1434 1435 /* static */ 1436 void UICommon::centerWidget(QWidget *pWidget, QWidget *pRelative, bool fCanResize /* = true */) 1437 { 1438 /* If necessary, pWidget's position is adjusted to make it fully visible within 1439 * the available desktop area. If pWidget is bigger then this area, it will also 1440 * be resized unless fCanResize is false or there is an inappropriate minimum 1441 * size limit (in which case the top left corner will be simply aligned with the top 1442 * left corner of the available desktop area). pWidget must be a top-level widget. 1443 * pRelative may be any widget, but if it's not top-level itself, its top-level 1444 * widget will be used for calculations. pRelative can also be NULL, in which case 1445 * pWidget will be centered relative to the available desktop area. */ 1446 1447 AssertReturnVoid(pWidget); 1448 AssertReturnVoid(pWidget->isTopLevel()); 1449 1450 QRect deskGeo, parentGeo; 1451 if (pRelative) 1452 { 1453 pRelative = pRelative->window(); 1454 deskGeo = gpDesktop->availableGeometry(pRelative); 1455 parentGeo = pRelative->frameGeometry(); 1456 // WORKAROUND: 1457 // On X11/Gnome, geo/frameGeo.x() and y() are always 0 for top level 1458 // widgets with parents, what a shame. Use mapToGlobal() to workaround. 1459 QPoint d = pRelative->mapToGlobal(QPoint(0, 0)); 1460 d.rx() -= pRelative->geometry().x() - pRelative->x(); 1461 d.ry() -= pRelative->geometry().y() - pRelative->y(); 1462 parentGeo.moveTopLeft(d); 1463 } 1464 else 1465 { 1466 deskGeo = gpDesktop->availableGeometry(); 1467 parentGeo = deskGeo; 1468 } 1469 1470 // WORKAROUND: 1471 // On X11, there is no way to determine frame geometry (including WM 1472 // decorations) before the widget is shown for the first time. Stupidly 1473 // enumerate other top level widgets to find the thickest frame. The code 1474 // is based on the idea taken from QDialog::adjustPositionInternal(). 1475 1476 int iExtraW = 0; 1477 int iExtraH = 0; 1478 1479 QWidgetList list = QApplication::topLevelWidgets(); 1480 QListIterator<QWidget*> it(list); 1481 while ((iExtraW == 0 || iExtraH == 0) && it.hasNext()) 1482 { 1483 int iFrameW, iFrameH; 1484 QWidget *pCurrent = it.next(); 1485 if (!pCurrent->isVisible()) 1486 continue; 1487 1488 iFrameW = pCurrent->frameGeometry().width() - pCurrent->width(); 1489 iFrameH = pCurrent->frameGeometry().height() - pCurrent->height(); 1490 1491 iExtraW = qMax(iExtraW, iFrameW); 1492 iExtraH = qMax(iExtraH, iFrameH); 1493 } 1494 1495 /* On non-X11 platforms, the following would be enough instead of the above workaround: */ 1496 // QRect geo = frameGeometry(); 1497 QRect geo = QRect(0, 0, pWidget->width() + iExtraW, 1498 pWidget->height() + iExtraH); 1499 1500 geo.moveCenter(QPoint(parentGeo.x() + (parentGeo.width() - 1) / 2, 1501 parentGeo.y() + (parentGeo.height() - 1) / 2)); 1502 1503 /* Ensure the widget is within the available desktop area: */ 1504 QRect newGeo = normalizeGeometry(geo, deskGeo, fCanResize); 1505 #ifdef VBOX_WS_MAC 1506 // WORKAROUND: 1507 // No idea why, but Qt doesn't respect if there is a unified toolbar on the 1508 // ::move call. So manually add the height of the toolbar before setting 1509 // the position. 1510 if (pRelative) 1511 newGeo.translate(0, ::darwinWindowToolBarHeight(pWidget)); 1512 #endif /* VBOX_WS_MAC */ 1513 1514 pWidget->move(newGeo.topLeft()); 1515 1516 if ( fCanResize 1517 && (geo.width() != newGeo.width() || geo.height() != newGeo.height())) 1518 pWidget->resize(newGeo.width() - iExtraW, newGeo.height() - iExtraH); 1519 } 1520 1521 #ifdef VBOX_WS_X11 1522 typedef struct { 1523 /** User specified flags */ 1524 uint32_t flags; 1525 /** User-specified position */ 1526 int32_t x, y; 1527 /** User-specified size */ 1528 int32_t width, height; 1529 /** Program-specified minimum size */ 1530 int32_t min_width, min_height; 1531 /** Program-specified maximum size */ 1532 int32_t max_width, max_height; 1533 /** Program-specified resize increments */ 1534 int32_t width_inc, height_inc; 1535 /** Program-specified minimum aspect ratios */ 1536 int32_t min_aspect_num, min_aspect_den; 1537 /** Program-specified maximum aspect ratios */ 1538 int32_t max_aspect_num, max_aspect_den; 1539 /** Program-specified base size */ 1540 int32_t base_width, base_height; 1541 /** Program-specified window gravity */ 1542 uint32_t win_gravity; 1543 } xcb_size_hints_t; 1544 #endif /* VBOX_WS_X11 */ 1545 1546 /* static */ 1547 void UICommon::setTopLevelGeometry(QWidget *pWidget, int x, int y, int w, int h) 1548 { 1549 AssertPtrReturnVoid(pWidget); 1550 #ifdef VBOX_WS_X11 1551 # define QWINDOWSIZE_MAX ((1<<24)-1) 1552 if (pWidget->isWindow() && pWidget->isVisible()) 1553 { 1554 // WORKAROUND: 1555 // X11 window managers are not required to accept geometry changes on 1556 // the top-level window. Unfortunately, current at Qt 5.6 and 5.7, Qt 1557 // assumes that the change will succeed, and resizes all sub-windows 1558 // unconditionally. By calling ConfigureWindow directly, Qt will see 1559 // our change request as an externally triggered one on success and not 1560 // at all if it is rejected. 1561 const double dDPR = gpDesktop->devicePixelRatio(pWidget); 1562 uint16_t fMask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y 1563 | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; 1564 uint32_t values[] = { (uint32_t)(x * dDPR), (uint32_t)(y * dDPR), (uint32_t)(w * dDPR), (uint32_t)(h * dDPR) }; 1565 xcb_configure_window(QX11Info::connection(), (xcb_window_t)pWidget->winId(), 1566 fMask, values); 1567 xcb_size_hints_t hints; 1568 hints.flags = 1 /* XCB_ICCCM_SIZE_HINT_US_POSITION */ 1569 | 2 /* XCB_ICCCM_SIZE_HINT_US_SIZE */ 1570 | 512 /* XCB_ICCCM_SIZE_P_WIN_GRAVITY */; 1571 hints.x = x * dDPR; 1572 hints.y = y * dDPR; 1573 hints.width = w * dDPR; 1574 hints.height = h * dDPR; 1575 hints.min_width = pWidget->minimumSize().width() * dDPR; 1576 hints.min_height = pWidget->minimumSize().height() * dDPR; 1577 hints.max_width = pWidget->maximumSize().width() * dDPR; 1578 hints.max_height = pWidget->maximumSize().height() * dDPR; 1579 hints.width_inc = pWidget->sizeIncrement().width() * dDPR; 1580 hints.height_inc = pWidget->sizeIncrement().height() * dDPR; 1581 hints.base_width = pWidget->baseSize().width() * dDPR; 1582 hints.base_height = pWidget->baseSize().height() * dDPR; 1583 hints.win_gravity = XCB_GRAVITY_STATIC; 1584 if (hints.min_width > 0 || hints.min_height > 0) 1585 hints.flags |= 16 /* XCB_ICCCM_SIZE_HINT_P_MIN_SIZE */; 1586 if (hints.max_width < QWINDOWSIZE_MAX || hints.max_height < QWINDOWSIZE_MAX) 1587 hints.flags |= 32 /* XCB_ICCCM_SIZE_HINT_P_MAX_SIZE */; 1588 if (hints.width_inc > 0 || hints.height_inc) 1589 hints.flags |= 64 /* XCB_ICCCM_SIZE_HINT_P_MIN_SIZE */ 1590 | 256 /* XCB_ICCCM_SIZE_HINT_BASE_SIZE */; 1591 xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, 1592 (xcb_window_t)pWidget->winId(), XCB_ATOM_WM_NORMAL_HINTS, 1593 XCB_ATOM_WM_SIZE_HINTS, 32, sizeof(hints) >> 2, &hints); 1594 xcb_flush(QX11Info::connection()); 1595 } 1596 else 1597 // WORKAROUND: 1598 // Call the Qt method if the window is not visible as otherwise no 1599 // Configure event will arrive to tell Qt what geometry we want. 1600 pWidget->setGeometry(x, y, w, h); 1601 # else /* !VBOX_WS_X11 */ 1602 pWidget->setGeometry(x, y, w, h); 1603 # endif /* !VBOX_WS_X11 */ 1604 } 1605 1606 /* static */ 1607 void UICommon::setTopLevelGeometry(QWidget *pWidget, const QRect &rect) 1608 { 1609 UICommon::setTopLevelGeometry(pWidget, rect.x(), rect.y(), rect.width(), rect.height()); 1610 } 1611 1612 #if defined(VBOX_WS_X11) 1613 1614 static char *XXGetProperty(Display *pDpy, Window windowHandle, Atom propType, const char *pszPropName) 1615 { 1616 Atom propNameAtom = XInternAtom(pDpy, pszPropName, True /* only_if_exists */); 1617 if (propNameAtom == None) 1618 return NULL; 1619 1620 Atom actTypeAtom = None; 1621 int actFmt = 0; 1622 unsigned long nItems = 0; 1623 unsigned long nBytesAfter = 0; 1624 unsigned char *propVal = NULL; 1625 int rc = XGetWindowProperty(pDpy, windowHandle, propNameAtom, 1626 0, LONG_MAX, False /* delete */, 1627 propType, &actTypeAtom, &actFmt, 1628 &nItems, &nBytesAfter, &propVal); 1629 if (rc != Success) 1630 return NULL; 1631 1632 return reinterpret_cast<char*>(propVal); 1633 } 1634 1635 static Bool XXSendClientMessage(Display *pDpy, Window windowHandle, const char *pszMsg, 1636 unsigned long aData0 = 0, unsigned long aData1 = 0, 1637 unsigned long aData2 = 0, unsigned long aData3 = 0, 1638 unsigned long aData4 = 0) 1639 { 1640 Atom msgAtom = XInternAtom(pDpy, pszMsg, True /* only_if_exists */); 1641 if (msgAtom == None) 1642 return False; 1643 1644 XEvent ev; 1645 1646 ev.xclient.type = ClientMessage; 1647 ev.xclient.serial = 0; 1648 ev.xclient.send_event = True; 1649 ev.xclient.display = pDpy; 1650 ev.xclient.window = windowHandle; 1651 ev.xclient.message_type = msgAtom; 1652 1653 /* Always send as 32 bit for now: */ 1654 ev.xclient.format = 32; 1655 ev.xclient.data.l[0] = aData0; 1656 ev.xclient.data.l[1] = aData1; 1657 ev.xclient.data.l[2] = aData2; 1658 ev.xclient.data.l[3] = aData3; 1659 ev.xclient.data.l[4] = aData4; 1660 1661 return XSendEvent(pDpy, DefaultRootWindow(pDpy), False, 1662 SubstructureRedirectMask, &ev) != 0; 1663 } 1664 1665 #endif 1666 1667 /* static */ 1668 bool UICommon::activateWindow(WId wId, bool fSwitchDesktop /* = true */) 1669 { 1670 RT_NOREF(fSwitchDesktop); 1671 bool fResult = true; 1672 1673 #if defined(VBOX_WS_WIN) 1674 1675 HWND handle = (HWND)wId; 1676 1677 if (IsIconic(handle)) 1678 fResult &= !!ShowWindow(handle, SW_RESTORE); 1679 else if (!IsWindowVisible(handle)) 1680 fResult &= !!ShowWindow(handle, SW_SHOW); 1681 1682 fResult &= !!SetForegroundWindow(handle); 1683 1684 #elif defined(VBOX_WS_X11) 1685 1686 Display *pDisplay = QX11Info::display(); 1687 1688 if (fSwitchDesktop) 1689 { 1690 /* try to find the desktop ID using the NetWM property */ 1691 CARD32 *pDesktop = (CARD32 *) XXGetProperty(pDisplay, wId, XA_CARDINAL, 1692 "_NET_WM_DESKTOP"); 1693 if (pDesktop == NULL) 1694 // WORKAROUND: 1695 // if the NetWM properly is not supported try to find 1696 // the desktop ID using the GNOME WM property. 1697 pDesktop = (CARD32 *) XXGetProperty(pDisplay, wId, XA_CARDINAL, 1698 "_WIN_WORKSPACE"); 1699 1700 if (pDesktop != NULL) 1701 { 1702 Bool ok = XXSendClientMessage(pDisplay, DefaultRootWindow(pDisplay), 1703 "_NET_CURRENT_DESKTOP", 1704 *pDesktop); 1705 if (!ok) 1706 { 1707 Log1WarningFunc(("Couldn't switch to pDesktop=%08X\n", pDesktop)); 1708 fResult = false; 1709 } 1710 XFree(pDesktop); 1711 } 1712 else 1713 { 1714 Log1WarningFunc(("Couldn't find a pDesktop ID for wId=%08X\n", wId)); 1715 fResult = false; 1716 } 1717 } 1718 1719 Bool ok = XXSendClientMessage(pDisplay, wId, "_NET_ACTIVE_WINDOW"); 1720 fResult &= !!ok; 1721 1722 XRaiseWindow(pDisplay, wId); 1723 1724 #else 1725 1726 NOREF(wId); 1727 NOREF(fSwitchDesktop); 1728 AssertFailed(); 1729 fResult = false; 1730 1731 #endif 1732 1733 if (!fResult) 1734 Log1WarningFunc(("Couldn't activate wId=%08X\n", wId)); 1735 1736 return fResult; 1737 } 1738 1739 /* static */ 1740 void UICommon::setCursor(QWidget *pWidget, const QCursor &cursor) 28 void UICursor::setCursor(QWidget *pWidget, const QCursor &cursor) 1741 29 { 1742 30 if (!pWidget) … … 1764 52 1765 53 /* static */ 1766 void UIC ommon::setCursor(QGraphicsWidget *pWidget, const QCursor &cursor)54 void UICursor::setCursor(QGraphicsWidget *pWidget, const QCursor &cursor) 1767 55 { 1768 56 if (!pWidget) … … 1790 78 1791 79 /* static */ 1792 void UIC ommon::unsetCursor(QWidget *pWidget)80 void UICursor::unsetCursor(QWidget *pWidget) 1793 81 { 1794 82 if (!pWidget) … … 1816 104 1817 105 /* static */ 1818 void UIC ommon::unsetCursor(QGraphicsWidget *pWidget)106 void UICursor::unsetCursor(QGraphicsWidget *pWidget) 1819 107 { 1820 108 if (!pWidget) … … 1840 128 #endif 1841 129 } 1842 1843 1844 #if defined(VBOX_WS_X11)1845 1846 /* static */1847 bool UICommon::supportsFullScreenMonitorsProtocolX11()1848 {1849 /* This method tests whether the current X11 window manager supports full-screen mode as we need it.1850 * Unfortunately the EWMH specification was not fully clear about whether we can expect to find1851 * all of these atoms on the _NET_SUPPORTED root window property, so we have to test with all1852 * interesting window managers. If this fails for a user when you think it should succeed1853 * they should try executing:1854 * xprop -root | egrep -w '_NET_WM_FULLSCREEN_MONITORS|_NET_WM_STATE|_NET_WM_STATE_FULLSCREEN'1855 * in an X11 terminal window.1856 * All three strings should be found under a property called "_NET_SUPPORTED(ATOM)". */1857 1858 /* Using a global to get at the display does not feel right, but that is how it is done elsewhere in the code. */1859 Display *pDisplay = QX11Info::display();1860 Atom atomSupported = XInternAtom(pDisplay, "_NET_SUPPORTED",1861 True /* only_if_exists */);1862 Atom atomWMFullScreenMonitors = XInternAtom(pDisplay,1863 "_NET_WM_FULLSCREEN_MONITORS",1864 True /* only_if_exists */);1865 Atom atomWMState = XInternAtom(pDisplay,1866 "_NET_WM_STATE",1867 True /* only_if_exists */);1868 Atom atomWMStateFullScreen = XInternAtom(pDisplay,1869 "_NET_WM_STATE_FULLSCREEN",1870 True /* only_if_exists */);1871 bool fFoundFullScreenMonitors = false;1872 bool fFoundState = false;1873 bool fFoundStateFullScreen = false;1874 Atom atomType;1875 int cFormat;1876 unsigned long cItems;1877 unsigned long cbLeft;1878 Atom *pAtomHints;1879 int rc;1880 unsigned i;1881 1882 if ( atomSupported == None || atomWMFullScreenMonitors == None1883 || atomWMState == None || atomWMStateFullScreen == None)1884 return false;1885 /* Get atom value: */1886 rc = XGetWindowProperty(pDisplay, DefaultRootWindow(pDisplay),1887 atomSupported, 0, 0x7fffffff /*LONG_MAX*/,1888 False /* delete */, XA_ATOM, &atomType,1889 &cFormat, &cItems, &cbLeft,1890 (unsigned char **)&pAtomHints);1891 if (rc != Success)1892 return false;1893 if (pAtomHints == NULL)1894 return false;1895 if (atomType == XA_ATOM && cFormat == 32 && cbLeft == 0)1896 for (i = 0; i < cItems; ++i)1897 {1898 if (pAtomHints[i] == atomWMFullScreenMonitors)1899 fFoundFullScreenMonitors = true;1900 if (pAtomHints[i] == atomWMState)1901 fFoundState = true;1902 if (pAtomHints[i] == atomWMStateFullScreen)1903 fFoundStateFullScreen = true;1904 }1905 XFree(pAtomHints);1906 return fFoundFullScreenMonitors && fFoundState && fFoundStateFullScreen;1907 }1908 1909 /* static */1910 bool UICommon::setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId)1911 {1912 return XXSendClientMessage(QX11Info::display(),1913 pWidget->window()->winId(),1914 "_NET_WM_FULLSCREEN_MONITORS",1915 uScreenId, uScreenId, uScreenId, uScreenId,1916 1 /* Source indication (1 = normal application) */);1917 }1918 1919 /* static */1920 QVector<Atom> UICommon::flagsNetWmState(QWidget *pWidget)1921 {1922 /* Get display: */1923 Display *pDisplay = QX11Info::display();1924 1925 /* Prepare atoms: */1926 QVector<Atom> resultNetWmState;1927 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);1928 1929 /* Get the size of the property data: */1930 Atom actual_type;1931 int iActualFormat;1932 ulong uPropertyLength;1933 ulong uBytesLeft;1934 uchar *pPropertyData = 0;1935 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(),1936 net_wm_state, 0, 0, False, XA_ATOM, &actual_type, &iActualFormat,1937 &uPropertyLength, &uBytesLeft, &pPropertyData) == Success &&1938 actual_type == XA_ATOM && iActualFormat == 32)1939 {1940 resultNetWmState.resize(uBytesLeft / 4);1941 XFree((char*)pPropertyData);1942 pPropertyData = 0;1943 1944 /* Fetch all data: */1945 if (XGetWindowProperty(pDisplay, pWidget->window()->winId(),1946 net_wm_state, 0, resultNetWmState.size(), False, XA_ATOM, &actual_type, &iActualFormat,1947 &uPropertyLength, &uBytesLeft, &pPropertyData) != Success)1948 resultNetWmState.clear();1949 else if (uPropertyLength != (ulong)resultNetWmState.size())1950 resultNetWmState.resize(uPropertyLength);1951 1952 /* Put it into resultNetWmState: */1953 if (!resultNetWmState.isEmpty())1954 memcpy(resultNetWmState.data(), pPropertyData, resultNetWmState.size() * sizeof(Atom));1955 if (pPropertyData)1956 XFree((char*)pPropertyData);1957 }1958 1959 /* Return result: */1960 return resultNetWmState;1961 }1962 1963 /* static */1964 bool UICommon::isFullScreenFlagSet(QWidget *pWidget)1965 {1966 /* Get display: */1967 Display *pDisplay = QX11Info::display();1968 1969 /* Prepare atoms: */1970 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */);1971 1972 /* Check if flagsNetWmState(pWidget) contains full-screen flag: */1973 return flagsNetWmState(pWidget).contains(net_wm_state_fullscreen);1974 }1975 1976 /* static */1977 void UICommon::setFullScreenFlag(QWidget *pWidget)1978 {1979 /* Get display: */1980 Display *pDisplay = QX11Info::display();1981 1982 /* Prepare atoms: */1983 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);1984 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);1985 Atom net_wm_state_fullscreen = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", True /* only if exists */);1986 1987 /* Append resultNetWmState with fullscreen flag if necessary: */1988 if (!resultNetWmState.contains(net_wm_state_fullscreen))1989 {1990 resultNetWmState.append(net_wm_state_fullscreen);1991 /* Apply property to widget again: */1992 XChangeProperty(pDisplay, pWidget->window()->winId(),1993 net_wm_state, XA_ATOM, 32, PropModeReplace,1994 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());1995 }1996 }1997 1998 /* static */1999 void UICommon::setSkipTaskBarFlag(QWidget *pWidget)2000 {2001 /* Get display: */2002 Display *pDisplay = QX11Info::display();2003 2004 /* Prepare atoms: */2005 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);2006 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);2007 Atom net_wm_state_skip_taskbar = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_TASKBAR", True /* only if exists */);2008 2009 /* Append resultNetWmState with skip-taskbar flag if necessary: */2010 if (!resultNetWmState.contains(net_wm_state_skip_taskbar))2011 {2012 resultNetWmState.append(net_wm_state_skip_taskbar);2013 /* Apply property to widget again: */2014 XChangeProperty(pDisplay, pWidget->window()->winId(),2015 net_wm_state, XA_ATOM, 32, PropModeReplace,2016 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());2017 }2018 }2019 2020 /* static */2021 void UICommon::setSkipPagerFlag(QWidget *pWidget)2022 {2023 /* Get display: */2024 Display *pDisplay = QX11Info::display();2025 2026 /* Prepare atoms: */2027 QVector<Atom> resultNetWmState = flagsNetWmState(pWidget);2028 Atom net_wm_state = XInternAtom(pDisplay, "_NET_WM_STATE", True /* only if exists */);2029 Atom net_wm_state_skip_pager = XInternAtom(pDisplay, "_NET_WM_STATE_SKIP_PAGER", True /* only if exists */);2030 2031 /* Append resultNetWmState with skip-pager flag if necessary: */2032 if (!resultNetWmState.contains(net_wm_state_skip_pager))2033 {2034 resultNetWmState.append(net_wm_state_skip_pager);2035 /* Apply property to widget again: */2036 XChangeProperty(pDisplay, pWidget->window()->winId(),2037 net_wm_state, XA_ATOM, 32, PropModeReplace,2038 (unsigned char*)resultNetWmState.data(), resultNetWmState.size());2039 }2040 }2041 2042 /* static */2043 void UICommon::setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString)2044 {2045 /* Make sure all arguments set: */2046 AssertReturnVoid(pWidget && !strNameString.isNull() && !strClassString.isNull());2047 2048 /* Define QByteArray objects to make sure data is alive within the scope: */2049 QByteArray nameByteArray;2050 /* Check the existence of RESOURCE_NAME env. variable and override name string if necessary: */2051 const char resourceName[] = "RESOURCE_NAME";2052 if (qEnvironmentVariableIsSet(resourceName))2053 nameByteArray = qgetenv(resourceName);2054 else2055 nameByteArray = strNameString.toLatin1();2056 QByteArray classByteArray = strClassString.toLatin1();2057 2058 AssertReturnVoid(nameByteArray.data() && classByteArray.data());2059 2060 XClassHint windowClass;2061 windowClass.res_name = nameByteArray.data();2062 windowClass.res_class = classByteArray.data();2063 /* Set WM_CLASS of the window to passed name and class strings: */2064 XSetClassHint(QX11Info::display(), pWidget->window()->winId(), &windowClass);2065 }2066 2067 /* static */2068 void UICommon::setXwaylandMayGrabKeyboardFlag(QWidget *pWidget)2069 {2070 XXSendClientMessage(QX11Info::display(), pWidget->window()->winId(),2071 "_XWAYLAND_MAY_GRAB_KEYBOARD", 1);2072 }2073 #endif /* VBOX_WS_X11 */2074 2075 /* static */2076 void UICommon::setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount)2077 {2078 /* Shame on Qt it hasn't stuff for tuning2079 * widget size suitable for reflecting content of desired size.2080 * For example QLineEdit, QSpinBox and similar widgets should have a methods2081 * to strict the minimum width to reflect at least [n] symbols. */2082 2083 /* Load options: */2084 QStyleOptionSpinBox option;2085 option.initFrom(pSpinBox);2086 2087 /* Acquire edit-field rectangle: */2088 QRect rect = pSpinBox->style()->subControlRect(QStyle::CC_SpinBox,2089 &option,2090 QStyle::SC_SpinBoxEditField,2091 pSpinBox);2092 2093 /* Calculate minimum-width magic: */2094 const int iSpinBoxWidth = pSpinBox->width();2095 const int iSpinBoxEditFieldWidth = rect.width();2096 const int iSpinBoxDelta = qMax(0, iSpinBoxWidth - iSpinBoxEditFieldWidth);2097 QFontMetrics metrics(pSpinBox->font(), pSpinBox);2098 const QString strDummy(cCount, '0');2099 const int iTextWidth = metrics.width(strDummy);2100 2101 /* Tune spin-box minimum-width: */2102 pSpinBox->setMinimumWidth(iTextWidth + iSpinBoxDelta);2103 }2104 2105 QString UICommon::vmGuestOSFamilyDescription(const QString &strFamilyId) const2106 {2107 AssertMsg(m_guestOSFamilyDescriptions.contains(strFamilyId),2108 ("Family ID incorrect: '%s'.", strFamilyId.toLatin1().constData()));2109 return m_guestOSFamilyDescriptions.value(strFamilyId);2110 }2111 2112 QList<CGuestOSType> UICommon::vmGuestOSTypeList(const QString &strFamilyId) const2113 {2114 AssertMsg(m_guestOSFamilyIDs.contains(strFamilyId),2115 ("Family ID incorrect: '%s'.", strFamilyId.toLatin1().constData()));2116 return m_guestOSFamilyIDs.contains(strFamilyId) ?2117 m_guestOSTypes[m_guestOSFamilyIDs.indexOf(strFamilyId)] : QList<CGuestOSType>();2118 }2119 2120 CGuestOSType UICommon::vmGuestOSType(const QString &strTypeId,2121 const QString &strFamilyId /* = QString() */) const2122 {2123 QList<CGuestOSType> list;2124 if (m_guestOSFamilyIDs.contains(strFamilyId))2125 {2126 list = m_guestOSTypes.at(m_guestOSFamilyIDs.indexOf(strFamilyId));2127 }2128 else2129 {2130 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++i)2131 list += m_guestOSTypes.at(i);2132 }2133 for (int j = 0; j < list.size(); ++j)2134 if (!list.at(j).GetId().compare(strTypeId))2135 return list.at(j);2136 return CGuestOSType();2137 }2138 2139 QString UICommon::vmGuestOSTypeDescription(const QString &strTypeId) const2140 {2141 for (int i = 0; i < m_guestOSFamilyIDs.size(); ++i)2142 {2143 QList<CGuestOSType> list(m_guestOSTypes[i]);2144 for (int j = 0; j < list.size(); ++j)2145 if (!list.at(j).GetId().compare(strTypeId))2146 return list.at(j).GetDescription();2147 }2148 return QString();2149 }2150 2151 /* static */2152 bool UICommon::isDOSType(const QString &strOSTypeId)2153 {2154 if ( strOSTypeId.left(3) == "dos"2155 || strOSTypeId.left(3) == "win"2156 || strOSTypeId.left(3) == "os2")2157 return true;2158 2159 return false;2160 }2161 2162 /* static */2163 bool UICommon::switchToMachine(CMachine &comMachine)2164 {2165 #ifdef VBOX_WS_MAC2166 const ULONG64 id = comMachine.ShowConsoleWindow();2167 #else2168 const WId id = (WId)comMachine.ShowConsoleWindow();2169 #endif2170 AssertWrapperOk(comMachine);2171 if (!comMachine.isOk())2172 return false;2173 2174 // WORKAROUND:2175 // id == 0 means the console window has already done everything2176 // necessary to implement the "show window" semantics.2177 if (id == 0)2178 return true;2179 2180 #if defined(VBOX_WS_WIN) || defined(VBOX_WS_X11)2181 2182 return activateWindow(id, true);2183 2184 #elif defined(VBOX_WS_MAC)2185 2186 // WORKAROUND:2187 // This is just for the case were the other process cannot steal2188 // the focus from us. It will send us a PSN so we can try.2189 ProcessSerialNumber psn;2190 psn.highLongOfPSN = id >> 32;2191 psn.lowLongOfPSN = (UInt32)id;2192 # ifdef __clang__2193 # pragma GCC diagnostic push2194 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"2195 OSErr rc = ::SetFrontProcess(&psn);2196 # pragma GCC diagnostic pop2197 # else2198 OSErr rc = ::SetFrontProcess(&psn);2199 # endif2200 if (!rc)2201 Log(("GUI: %#RX64 couldn't do SetFrontProcess on itself, the selector (we) had to do it...\n", id));2202 else2203 Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc));2204 return !rc;2205 2206 #else2207 2208 return false;2209 2210 #endif2211 }2212 2213 bool UICommon::launchMachine(CMachine &comMachine, LaunchMode enmLaunchMode /* = LaunchMode_Default */)2214 {2215 /* Switch to machine window(s) if possible: */2216 if ( comMachine.GetSessionState() == KSessionState_Locked /* precondition for CanShowConsoleWindow() */2217 && comMachine.CanShowConsoleWindow())2218 {2219 switch (uiType())2220 {2221 /* For Selector UI: */2222 case UIType_SelectorUI:2223 {2224 /* Just switch to existing VM window: */2225 return switchToMachine(comMachine);2226 }2227 /* For Runtime UI: */2228 case UIType_RuntimeUI:2229 {2230 /* Only separate UI process can reach that place.2231 * Switch to existing VM window and exit. */2232 switchToMachine(comMachine);2233 return false;2234 }2235 }2236 }2237 2238 /* Not for separate UI (which can connect to machine in any state): */2239 if (enmLaunchMode != LaunchMode_Separate)2240 {2241 /* Make sure machine-state is one of required: */2242 const KMachineState enmState = comMachine.GetState(); NOREF(enmState);2243 AssertMsg( enmState == KMachineState_PoweredOff2244 || enmState == KMachineState_Saved2245 || enmState == KMachineState_Teleported2246 || enmState == KMachineState_Aborted2247 , ("Machine must be PoweredOff/Saved/Teleported/Aborted (%d)", enmState));2248 }2249 2250 /* Create empty session instance: */2251 CSession comSession;2252 comSession.createInstance(CLSID_Session);2253 if (comSession.isNull())2254 {2255 msgCenter().cannotOpenSession(comSession);2256 return false;2257 }2258 2259 /* Configure environment: */2260 QVector<QString> astrEnv;2261 #ifdef VBOX_WS_WIN2262 /* Allow started VM process to be foreground window: */2263 AllowSetForegroundWindow(ASFW_ANY);2264 #endif2265 #ifdef VBOX_WS_X112266 /* Make sure VM process will start on the same2267 * display as window this wrapper is called from: */2268 const char *pDisplay = RTEnvGet("DISPLAY");2269 if (pDisplay)2270 astrEnv.append(QString("DISPLAY=%1").arg(pDisplay));2271 const char *pXauth = RTEnvGet("XAUTHORITY");2272 if (pXauth)2273 astrEnv.append(QString("XAUTHORITY=%1").arg(pXauth));2274 #endif2275 QString strType;2276 switch (enmLaunchMode)2277 {2278 case LaunchMode_Default: strType = ""; break;2279 case LaunchMode_Separate: strType = isSeparateProcess() ? "headless" : "separate"; break;2280 case LaunchMode_Headless: strType = "headless"; break;2281 default: AssertFailedReturn(false);2282 }2283 2284 /* Prepare "VM spawning" progress: */2285 CProgress comProgress = comMachine.LaunchVMProcess(comSession, strType, astrEnv);2286 if (!comMachine.isOk())2287 {2288 /* If the VM is started separately and the VM process is already running, then it is OK. */2289 if (enmLaunchMode == LaunchMode_Separate)2290 {2291 const KMachineState enmState = comMachine.GetState();2292 if ( enmState >= KMachineState_FirstOnline2293 && enmState <= KMachineState_LastOnline)2294 {2295 /* Already running: */2296 return true;2297 }2298 }2299 2300 msgCenter().cannotOpenSession(comMachine);2301 return false;2302 }2303 2304 /* Show "VM spawning" progress: */2305 msgCenter().showModalProgressDialog(comProgress, comMachine.GetName(),2306 ":/progress_start_90px.png", 0, 0);2307 if (!comProgress.isOk() || comProgress.GetResultCode() != 0)2308 msgCenter().cannotOpenSession(comProgress, comMachine.GetName());2309 2310 /* Unlock machine, close session: */2311 comSession.UnlockMachine();2312 2313 /* True finally: */2314 return true;2315 }2316 2317 CSession UICommon::openSession(const QUuid &uId, KLockType lockType /* = KLockType_Shared */)2318 {2319 /* Prepare session: */2320 CSession comSession;2321 2322 /* Simulate try-catch block: */2323 bool fSuccess = false;2324 do2325 {2326 /* Create empty session instance: */2327 comSession.createInstance(CLSID_Session);2328 if (comSession.isNull())2329 {2330 msgCenter().cannotOpenSession(comSession);2331 break;2332 }2333 2334 /* Search for the corresponding machine: */2335 CMachine comMachine = m_comVBox.FindMachine(uId.toString());2336 if (comMachine.isNull())2337 {2338 msgCenter().cannotFindMachineById(m_comVBox, uId);2339 break;2340 }2341 2342 if (lockType == KLockType_VM)2343 comSession.SetName("GUI/Qt");2344 2345 /* Lock found machine to session: */2346 comMachine.LockMachine(comSession, lockType);2347 if (!comMachine.isOk())2348 {2349 msgCenter().cannotOpenSession(comMachine);2350 break;2351 }2352 2353 /* Pass the language ID as the property to the guest: */2354 if (comSession.GetType() == KSessionType_Shared)2355 {2356 CMachine comStartedMachine = comSession.GetMachine();2357 /* Make sure that the language is in two letter code.2358 * Note: if languageId() returns an empty string lang.name() will2359 * return "C" which is an valid language code. */2360 QLocale lang(UITranslator::languageId());2361 comStartedMachine.SetGuestPropertyValue("/VirtualBox/HostInfo/GUI/LanguageID", lang.name());2362 }2363 2364 /* Success finally: */2365 fSuccess = true;2366 }2367 while (0);2368 /* Cleanup try-catch block: */2369 if (!fSuccess)2370 comSession.detach();2371 2372 /* Return session: */2373 return comSession;2374 }2375 2376 CSession UICommon::tryToOpenSessionFor(CMachine &comMachine)2377 {2378 /* Prepare session: */2379 CSession comSession;2380 2381 /* Session state unlocked? */2382 if (comMachine.GetSessionState() == KSessionState_Unlocked)2383 {2384 /* Open own 'write' session: */2385 comSession = openSession(comMachine.GetId());2386 AssertReturn(!comSession.isNull(), CSession());2387 comMachine = comSession.GetMachine();2388 }2389 /* Is this a Selector UI call? */2390 else if (uiType() == UIType_SelectorUI)2391 {2392 /* Open existing 'shared' session: */2393 comSession = openExistingSession(comMachine.GetId());2394 AssertReturn(!comSession.isNull(), CSession());2395 comMachine = comSession.GetMachine();2396 }2397 /* Else this is Runtime UI call2398 * which has session locked for itself. */2399 2400 /* Return session: */2401 return comSession;2402 }2403 2404 void UICommon::notifyCloudMachineUnregistered(const QString &strProviderShortName,2405 const QString &strProfileName,2406 const QUuid &uId)2407 {2408 emit sigCloudMachineUnregistered(strProviderShortName, strProfileName, uId);2409 }2410 2411 void UICommon::notifyCloudMachineRegistered(const QString &strProviderShortName,2412 const QString &strProfileName,2413 const CCloudMachine &comMachine)2414 {2415 emit sigCloudMachineRegistered(strProviderShortName, strProfileName, comMachine);2416 }2417 2418 void UICommon::enumerateMedia(const CMediumVector &comMedia /* = CMediumVector() */)2419 {2420 /* Make sure UICommon is already valid: */2421 AssertReturnVoid(m_fValid);2422 /* Ignore the request during UICommon cleanup: */2423 if (m_fCleaningUp)2424 return;2425 /* Ignore the request during startup snapshot restoring: */2426 if (shouldRestoreCurrentSnapshot())2427 return;2428 2429 /* Make sure medium-enumerator is already created: */2430 if (!m_pMediumEnumerator)2431 return;2432 2433 /* Redirect request to medium-enumerator under proper lock: */2434 if (m_meCleanupProtectionToken.tryLockForRead())2435 {2436 if (m_pMediumEnumerator)2437 m_pMediumEnumerator->enumerateMedia(comMedia);2438 m_meCleanupProtectionToken.unlock();2439 }2440 }2441 2442 void UICommon::refreshMedia()2443 {2444 /* Make sure UICommon is already valid: */2445 AssertReturnVoid(m_fValid);2446 /* Ignore the request during UICommon cleanup: */2447 if (m_fCleaningUp)2448 return;2449 /* Ignore the request during startup snapshot restoring: */2450 if (shouldRestoreCurrentSnapshot())2451 return;2452 2453 /* Make sure medium-enumerator is already created: */2454 if (!m_pMediumEnumerator)2455 return;2456 /* Make sure enumeration is not already started: */2457 if (m_pMediumEnumerator->isMediumEnumerationInProgress())2458 return;2459 2460 /* We assume it's safe to call it without locking,2461 * since we are performing blocking operation here. */2462 m_pMediumEnumerator->refreshMedia();2463 }2464 2465 bool UICommon::isFullMediumEnumerationRequested() const2466 {2467 /* Redirect request to medium-enumerator: */2468 return m_pMediumEnumerator2469 && m_pMediumEnumerator->isFullMediumEnumerationRequested();2470 }2471 2472 bool UICommon::isMediumEnumerationInProgress() const2473 {2474 /* Redirect request to medium-enumerator: */2475 return m_pMediumEnumerator2476 && m_pMediumEnumerator->isMediumEnumerationInProgress();2477 }2478 2479 UIMedium UICommon::medium(const QUuid &uMediumID) const2480 {2481 if (m_meCleanupProtectionToken.tryLockForRead())2482 {2483 /* Redirect call to medium-enumerator: */2484 UIMedium guiMedium;2485 if (m_pMediumEnumerator)2486 guiMedium = m_pMediumEnumerator->medium(uMediumID);2487 m_meCleanupProtectionToken.unlock();2488 return guiMedium;2489 }2490 return UIMedium();2491 }2492 2493 QList<QUuid> UICommon::mediumIDs() const2494 {2495 if (m_meCleanupProtectionToken.tryLockForRead())2496 {2497 /* Redirect call to medium-enumerator: */2498 QList<QUuid> listOfMedia;2499 if (m_pMediumEnumerator)2500 listOfMedia = m_pMediumEnumerator->mediumIDs();2501 m_meCleanupProtectionToken.unlock();2502 return listOfMedia;2503 }2504 return QList<QUuid>();2505 }2506 2507 void UICommon::createMedium(const UIMedium &guiMedium)2508 {2509 if (m_meCleanupProtectionToken.tryLockForRead())2510 {2511 /* Create medium in medium-enumerator: */2512 if (m_pMediumEnumerator)2513 m_pMediumEnumerator->createMedium(guiMedium);2514 m_meCleanupProtectionToken.unlock();2515 }2516 }2517 2518 QUuid UICommon::openMedium(UIMediumDeviceType enmMediumType, QString strMediumLocation, QWidget *pParent /* = 0 */)2519 {2520 /* Convert to native separators: */2521 strMediumLocation = QDir::toNativeSeparators(strMediumLocation);2522 2523 /* Initialize variables: */2524 CVirtualBox comVBox = virtualBox();2525 2526 /* Open corresponding medium: */2527 CMedium comMedium = comVBox.OpenMedium(strMediumLocation, mediumTypeToGlobal(enmMediumType), KAccessMode_ReadWrite, false);2528 2529 if (comVBox.isOk())2530 {2531 /* Prepare vbox medium wrapper: */2532 UIMedium guiMedium = medium(comMedium.GetId());2533 2534 /* First of all we should test if that medium already opened: */2535 if (guiMedium.isNull())2536 {2537 /* And create new otherwise: */2538 guiMedium = UIMedium(comMedium, enmMediumType, KMediumState_Created);2539 createMedium(guiMedium);2540 }2541 2542 /* Return guiMedium id: */2543 return guiMedium.id();2544 }2545 else2546 msgCenter().cannotOpenMedium(comVBox, strMediumLocation, pParent);2547 2548 return QUuid();2549 }2550 2551 QUuid UICommon::openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, QWidget *pParent,2552 const QString &strDefaultFolder /* = QString() */,2553 bool fUseLastFolder /* = false */)2554 {2555 /* Initialize variables: */2556 QList<QPair <QString, QString> > filters;2557 QStringList backends;2558 QStringList prefixes;2559 QString strFilter;2560 QString strTitle;2561 QString allType;2562 QString strLastFolder = defaultFolderPathForType(enmMediumType);2563 2564 /* For DVDs and Floppies always check first the last recently used medium folder. For hard disk use2565 the caller's setting: */2566 fUseLastFolder = (enmMediumType == UIMediumDeviceType_DVD) || (enmMediumType == UIMediumDeviceType_Floppy);2567 2568 switch (enmMediumType)2569 {2570 case UIMediumDeviceType_HardDisk:2571 {2572 filters = HDDBackends(virtualBox());2573 strTitle = tr("Please choose a virtual hard disk file");2574 allType = tr("All virtual hard disk files (%1)");2575 break;2576 }2577 case UIMediumDeviceType_DVD:2578 {2579 filters = DVDBackends(virtualBox());2580 strTitle = tr("Please choose a virtual optical disk file");2581 allType = tr("All virtual optical disk files (%1)");2582 break;2583 }2584 case UIMediumDeviceType_Floppy:2585 {2586 filters = FloppyBackends(virtualBox());2587 strTitle = tr("Please choose a virtual floppy disk file");2588 allType = tr("All virtual floppy disk files (%1)");2589 break;2590 }2591 default:2592 break;2593 }2594 QString strHomeFolder = fUseLastFolder && !strLastFolder.isEmpty() ? strLastFolder :2595 strDefaultFolder.isEmpty() ? homeFolder() : strDefaultFolder;2596 2597 /* Prepare filters and backends: */2598 for (int i = 0; i < filters.count(); ++i)2599 {2600 /* Get iterated filter: */2601 QPair<QString, QString> item = filters.at(i);2602 /* Create one backend filter string: */2603 backends << QString("%1 (%2)").arg(item.first).arg(item.second);2604 /* Save the suffix's for the "All" entry: */2605 prefixes << item.second;2606 }2607 if (!prefixes.isEmpty())2608 backends.insert(0, allType.arg(prefixes.join(" ").trimmed()));2609 backends << tr("All files (*)");2610 strFilter = backends.join(";;").trimmed();2611 2612 /* Create open file dialog: */2613 QStringList files = QIFileDialog::getOpenFileNames(strHomeFolder, strFilter, pParent, strTitle, 0, true, true);2614 2615 /* If dialog has some result: */2616 if (!files.empty() && !files[0].isEmpty())2617 {2618 QUuid uMediumId = openMedium(enmMediumType, files[0], pParent);2619 if (enmMediumType == UIMediumDeviceType_DVD || enmMediumType == UIMediumDeviceType_Floppy ||2620 (enmMediumType == UIMediumDeviceType_HardDisk && fUseLastFolder))2621 updateRecentlyUsedMediumListAndFolder(enmMediumType, medium(uMediumId).location());2622 return uMediumId;2623 }2624 return QUuid();2625 }2626 2627 2628 /**2629 * Helper for createVisoMediumWithVisoCreator.2630 * @returns IPRT status code.2631 * @param pStrmDst Where to write the quoted string.2632 * @param pszPrefix Stuff to put in front of it.2633 * @param rStr The string to quote and write out.2634 * @param pszPrefix Stuff to put after it.2635 */2636 DECLINLINE(int) visoWriteQuotedString(PRTSTREAM pStrmDst, const char *pszPrefix, QString const &rStr, const char *pszPostFix)2637 {2638 QByteArray const utf8Array = rStr.toUtf8();2639 const char *apszArgv[2] = { utf8Array.constData(), NULL };2640 char *pszQuoted;2641 int vrc = RTGetOptArgvToString(&pszQuoted, apszArgv, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);2642 if (RT_SUCCESS(vrc))2643 {2644 if (pszPrefix)2645 vrc = RTStrmPutStr(pStrmDst, pszPrefix);2646 if (RT_SUCCESS(vrc))2647 {2648 vrc = RTStrmPutStr(pStrmDst, pszQuoted);2649 if (pszPostFix && RT_SUCCESS(vrc))2650 vrc = RTStrmPutStr(pStrmDst, pszPostFix);2651 }2652 RTStrFree(pszQuoted);2653 }2654 2655 return vrc;2656 }2657 2658 2659 void UICommon::openMediumCreatorDialog(QWidget *pParent, UIMediumDeviceType enmMediumType,2660 const QString &strDefaultFolder /* = QString() */,2661 const QString &strMachineName /* = QString() */,2662 const QString &strMachineGuestOSTypeId /*= QString() */)2663 {2664 /* Depending on medium-type: */2665 QUuid uMediumId;2666 switch (enmMediumType)2667 {2668 case UIMediumDeviceType_HardDisk:2669 createVDWithWizard(pParent, strDefaultFolder, strMachineName, strMachineGuestOSTypeId);2670 break;2671 case UIMediumDeviceType_DVD:2672 uMediumId = createVisoMediumWithVisoCreator(pParent, strDefaultFolder, strMachineName);2673 break;2674 case UIMediumDeviceType_Floppy:2675 uMediumId = showCreateFloppyDiskDialog(pParent, strDefaultFolder, strMachineName);2676 break;2677 default:2678 break;2679 }2680 if (uMediumId.isNull())2681 return;2682 2683 /* Update the recent medium list only if the medium type is DVD or floppy: */2684 if (enmMediumType == UIMediumDeviceType_DVD || enmMediumType == UIMediumDeviceType_Floppy)2685 updateRecentlyUsedMediumListAndFolder(enmMediumType, medium(uMediumId).location());2686 }2687 2688 QUuid UICommon::createVisoMediumWithVisoCreator(QWidget *pParent, const QString &strDefaultFolder /* = QString */,2689 const QString &strMachineName /* = QString */)2690 {2691 QString strVisoSaveFolder(strDefaultFolder);2692 if (strVisoSaveFolder.isEmpty())2693 strVisoSaveFolder = defaultFolderPathForType(UIMediumDeviceType_DVD);2694 2695 QWidget *pDialogParent = windowManager().realParentWindow(pParent);2696 UIVisoCreator *pVisoCreator = new UIVisoCreator(pDialogParent, strMachineName);2697 2698 if (!pVisoCreator)2699 return QString();2700 windowManager().registerNewParent(pVisoCreator, pDialogParent);2701 pVisoCreator->setCurrentPath(gEDataManager->visoCreatorRecentFolder());2702 2703 if (pVisoCreator->exec(false /* not application modal */))2704 {2705 QStringList files = pVisoCreator->entryList();2706 QString strVisoName = pVisoCreator->visoName();2707 if (strVisoName.isEmpty())2708 strVisoName = strMachineName;2709 2710 if (files.empty() || files[0].isEmpty())2711 {2712 delete pVisoCreator;2713 return QUuid();2714 }2715 2716 gEDataManager->setVISOCreatorRecentFolder(pVisoCreator->currentPath());2717 2718 /* Produce the VISO. */2719 char szVisoPath[RTPATH_MAX];2720 QString strFileName = QString("%1%2").arg(strVisoName).arg(".viso");2721 int vrc = RTPathJoin(szVisoPath, sizeof(szVisoPath), strVisoSaveFolder.toUtf8().constData(), strFileName.toUtf8().constData());2722 if (RT_SUCCESS(vrc))2723 {2724 PRTSTREAM pStrmViso;2725 vrc = RTStrmOpen(szVisoPath, "w", &pStrmViso);2726 if (RT_SUCCESS(vrc))2727 {2728 RTUUID Uuid;2729 vrc = RTUuidCreate(&Uuid);2730 if (RT_SUCCESS(vrc))2731 {2732 RTStrmPrintf(pStrmViso, "--iprt-iso-maker-file-marker-bourne-sh %RTuuid\n", &Uuid);2733 vrc = visoWriteQuotedString(pStrmViso, "--volume-id=", strVisoName, "\n");2734 2735 for (int iFile = 0; iFile < files.size() && RT_SUCCESS(vrc); iFile++)2736 vrc = visoWriteQuotedString(pStrmViso, NULL, files[iFile], "\n");2737 2738 /* Append custom options if any to the file: */2739 const QStringList &customOptions = pVisoCreator->customOptions();2740 foreach (QString strLine, customOptions)2741 RTStrmPrintf(pStrmViso, "%s\n", strLine.toUtf8().constData());2742 2743 RTStrmFlush(pStrmViso);2744 if (RT_SUCCESS(vrc))2745 vrc = RTStrmError(pStrmViso);2746 }2747 2748 RTStrmClose(pStrmViso);2749 }2750 }2751 2752 /* Done. */2753 if (RT_SUCCESS(vrc))2754 {2755 delete pVisoCreator;2756 return openMedium(UIMediumDeviceType_DVD, QString(szVisoPath), pParent);2757 }2758 /** @todo error message. */2759 else2760 {2761 delete pVisoCreator;2762 return QUuid();2763 }2764 }2765 delete pVisoCreator;2766 return QUuid();2767 }2768 2769 QUuid UICommon::showCreateFloppyDiskDialog(QWidget *pParent, const QString &strDefaultFolder /* QString() */,2770 const QString &strMachineName /* = QString() */ )2771 {2772 QString strStartPath(strDefaultFolder);2773 2774 if (strStartPath.isEmpty())2775 strStartPath = defaultFolderPathForType(UIMediumDeviceType_Floppy);2776 2777 QWidget *pDialogParent = windowManager().realParentWindow(pParent);2778 2779 UIFDCreationDialog *pDialog = new UIFDCreationDialog(pParent, strStartPath, strMachineName);2780 if (!pDialog)2781 return QUuid();2782 windowManager().registerNewParent(pDialog, pDialogParent);2783 2784 if (pDialog->exec())2785 {2786 QUuid uMediumID = pDialog->mediumID();2787 delete pDialog;2788 return uMediumID;2789 }2790 delete pDialog;2791 return QUuid();2792 }2793 2794 int UICommon::openMediumSelectorDialog(QWidget *pParent, UIMediumDeviceType enmMediumType, QUuid &outUuid,2795 const QString &strMachineFolder, const QString &strMachineName,2796 const QString &strMachineGuestOSTypeId, bool fEnableCreate, const QUuid &uMachineID /* = QUuid() */)2797 {2798 QUuid uMachineOrGlobalId = uMachineID == QUuid() ? gEDataManager->GlobalID : uMachineID;2799 2800 QWidget *pDialogParent = windowManager().realParentWindow(pParent);2801 QPointer<UIMediumSelector> pSelector = new UIMediumSelector(enmMediumType, strMachineName,2802 strMachineFolder, strMachineGuestOSTypeId,2803 uMachineOrGlobalId, pDialogParent);2804 2805 if (!pSelector)2806 return static_cast<int>(UIMediumSelector::ReturnCode_Rejected);2807 pSelector->setEnableCreateAction(fEnableCreate);2808 windowManager().registerNewParent(pSelector, pDialogParent);2809 2810 int iResult = pSelector->exec(false);2811 UIMediumSelector::ReturnCode returnCode;2812 2813 if (iResult >= static_cast<int>(UIMediumSelector::ReturnCode_Max) || iResult < 0)2814 returnCode = UIMediumSelector::ReturnCode_Rejected;2815 else2816 returnCode = static_cast<UIMediumSelector::ReturnCode>(iResult);2817 2818 if (returnCode == UIMediumSelector::ReturnCode_Accepted)2819 {2820 QList<QUuid> selectedMediumIds = pSelector->selectedMediumIds();2821 2822 /* Currently we only care about the 0th since we support single selection by intention: */2823 if (selectedMediumIds.isEmpty())2824 returnCode = UIMediumSelector::ReturnCode_Rejected;2825 else2826 {2827 outUuid = selectedMediumIds[0];2828 updateRecentlyUsedMediumListAndFolder(enmMediumType, medium(outUuid).location());2829 }2830 }2831 delete pSelector;2832 return static_cast<int>(returnCode);2833 }2834 2835 void UICommon::createVDWithWizard(QWidget *pParent,2836 const QString &strMachineFolder /* = QString() */,2837 const QString &strMachineName /* = QString() */,2838 const QString &strMachineGuestOSTypeId /* = QString() */)2839 {2840 /* Initialize variables: */2841 QString strDefaultFolder = strMachineFolder;2842 if (strDefaultFolder.isEmpty())2843 strDefaultFolder = defaultFolderPathForType(UIMediumDeviceType_HardDisk);2844 2845 /* In case we dont have a 'guest os type id' default back to 'Other': */2846 const CGuestOSType comGuestOSType = virtualBox().GetGuestOSType( !strMachineGuestOSTypeId.isEmpty()2847 ? strMachineGuestOSTypeId2848 : "Other");2849 const QString strDiskName = findUniqueFileName(strDefaultFolder, !strMachineName.isEmpty()2850 ? strMachineName2851 : "NewVirtualDisk");2852 2853 /* Show New VD wizard: */2854 UISafePointerWizardNewVD pWizard = new UIWizardNewVD(pParent,2855 strDiskName,2856 strDefaultFolder,2857 comGuestOSType.GetRecommendedHDD());2858 if (!pWizard)2859 return;2860 QWidget *pDialogParent = windowManager().realParentWindow(pParent);2861 windowManager().registerNewParent(pWizard, pDialogParent);2862 pWizard->exec();2863 delete pWizard;2864 }2865 2866 void UICommon::prepareStorageMenu(QMenu &menu,2867 QObject *pListener, const char *pszSlotName,2868 const CMachine &comMachine, const QString &strControllerName, const StorageSlot &storageSlot)2869 {2870 /* Current attachment attributes: */2871 const CMediumAttachment comCurrentAttachment = comMachine.GetMediumAttachment(strControllerName,2872 storageSlot.port,2873 storageSlot.device);2874 const CMedium comCurrentMedium = comCurrentAttachment.GetMedium();2875 const QUuid uCurrentID = comCurrentMedium.isNull() ? QUuid() : comCurrentMedium.GetId();2876 const QString strCurrentLocation = comCurrentMedium.isNull() ? QString() : comCurrentMedium.GetLocation();2877 2878 /* Other medium-attachments of same machine: */2879 const CMediumAttachmentVector comAttachments = comMachine.GetMediumAttachments();2880 2881 /* Determine device & medium types: */2882 const UIMediumDeviceType enmMediumType = mediumTypeToLocal(comCurrentAttachment.GetType());2883 AssertMsgReturnVoid(enmMediumType != UIMediumDeviceType_Invalid, ("Incorrect storage medium type!\n"));2884 2885 /* Prepare open-existing-medium action: */2886 QAction *pActionOpenExistingMedium = menu.addAction(UIIconPool::iconSet(":/select_file_16px.png"),2887 QString(), pListener, pszSlotName);2888 pActionOpenExistingMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, comCurrentAttachment.GetPort(),2889 comCurrentAttachment.GetDevice(), enmMediumType)));2890 pActionOpenExistingMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Choose/Create a disk image..."));2891 2892 2893 /* Prepare open medium file action: */2894 QAction *pActionFileSelector = menu.addAction(UIIconPool::iconSet(":/select_file_16px.png"),2895 QString(), pListener, pszSlotName);2896 pActionFileSelector->setData(QVariant::fromValue(UIMediumTarget(strControllerName, comCurrentAttachment.GetPort(),2897 comCurrentAttachment.GetDevice(), enmMediumType,2898 UIMediumTarget::UIMediumTargetType_WithFileDialog)));2899 pActionFileSelector->setText(QApplication::translate("UIMachineSettingsStorage", "Choose a disk file..."));2900 2901 2902 /* Insert separator: */2903 menu.addSeparator();2904 2905 /* Get existing-host-drive vector: */2906 CMediumVector comMedia;2907 switch (enmMediumType)2908 {2909 case UIMediumDeviceType_DVD: comMedia = host().GetDVDDrives(); break;2910 case UIMediumDeviceType_Floppy: comMedia = host().GetFloppyDrives(); break;2911 default: break;2912 }2913 /* Prepare choose-existing-host-drive actions: */2914 foreach (const CMedium &comMedium, comMedia)2915 {2916 /* Make sure host-drive usage is unique: */2917 bool fIsHostDriveUsed = false;2918 foreach (const CMediumAttachment &comOtherAttachment, comAttachments)2919 {2920 if (comOtherAttachment != comCurrentAttachment)2921 {2922 const CMedium &comOtherMedium = comOtherAttachment.GetMedium();2923 if (!comOtherMedium.isNull() && comOtherMedium.GetId() == comMedium.GetId())2924 {2925 fIsHostDriveUsed = true;2926 break;2927 }2928 }2929 }2930 /* If host-drives usage is unique: */2931 if (!fIsHostDriveUsed)2932 {2933 QAction *pActionChooseHostDrive = menu.addAction(UIMedium(comMedium, enmMediumType).name(), pListener, pszSlotName);2934 pActionChooseHostDrive->setCheckable(true);2935 pActionChooseHostDrive->setChecked(!comCurrentMedium.isNull() && comMedium.GetId() == uCurrentID);2936 pActionChooseHostDrive->setData(QVariant::fromValue(UIMediumTarget(strControllerName,2937 comCurrentAttachment.GetPort(),2938 comCurrentAttachment.GetDevice(),2939 enmMediumType,2940 UIMediumTarget::UIMediumTargetType_WithID,2941 comMedium.GetId().toString())));2942 }2943 }2944 2945 /* Get recent-medium list: */2946 QStringList recentMediumList;2947 QStringList recentMediumListUsed;2948 switch (enmMediumType)2949 {2950 case UIMediumDeviceType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break;2951 case UIMediumDeviceType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break;2952 case UIMediumDeviceType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break;2953 default: break;2954 }2955 /* Prepare choose-recent-medium actions: */2956 foreach (const QString &strRecentMediumLocationBase, recentMediumList)2957 {2958 /* Confirm medium uniqueness: */2959 if (recentMediumListUsed.contains(strRecentMediumLocationBase))2960 continue;2961 /* Mark medium as known: */2962 recentMediumListUsed << strRecentMediumLocationBase;2963 /* Convert separators to native: */2964 const QString strRecentMediumLocation = QDir::toNativeSeparators(strRecentMediumLocationBase);2965 /* Confirm medium presence: */2966 if (!QFile::exists(strRecentMediumLocation))2967 continue;2968 /* Make sure recent-medium usage is unique: */2969 bool fIsRecentMediumUsed = false;2970 if (enmMediumType != UIMediumDeviceType_DVD)2971 foreach (const CMediumAttachment &otherAttachment, comAttachments)2972 {2973 if (otherAttachment != comCurrentAttachment)2974 {2975 const CMedium &comOtherMedium = otherAttachment.GetMedium();2976 if (!comOtherMedium.isNull() && comOtherMedium.GetLocation() == strRecentMediumLocation)2977 {2978 fIsRecentMediumUsed = true;2979 break;2980 }2981 }2982 }2983 /* If recent-medium usage is unique: */2984 if (!fIsRecentMediumUsed)2985 {2986 QAction *pActionChooseRecentMedium = menu.addAction(QFileInfo(strRecentMediumLocation).fileName(),2987 pListener, pszSlotName);2988 pActionChooseRecentMedium->setCheckable(true);2989 pActionChooseRecentMedium->setChecked(!comCurrentMedium.isNull() && strRecentMediumLocation == strCurrentLocation);2990 pActionChooseRecentMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName,2991 comCurrentAttachment.GetPort(),2992 comCurrentAttachment.GetDevice(),2993 enmMediumType,2994 UIMediumTarget::UIMediumTargetType_WithLocation,2995 strRecentMediumLocation)));2996 pActionChooseRecentMedium->setToolTip(strRecentMediumLocation);2997 }2998 }2999 3000 /* Last action for optical/floppy attachments only: */3001 if (enmMediumType == UIMediumDeviceType_DVD || enmMediumType == UIMediumDeviceType_Floppy)3002 {3003 /* Insert separator: */3004 menu.addSeparator();3005 3006 /* Prepare unmount-current-medium action: */3007 QAction *pActionUnmountMedium = menu.addAction(QString(), pListener, pszSlotName);3008 pActionUnmountMedium->setEnabled(!comCurrentMedium.isNull());3009 pActionUnmountMedium->setData(QVariant::fromValue(UIMediumTarget(strControllerName, comCurrentAttachment.GetPort(),3010 comCurrentAttachment.GetDevice())));3011 pActionUnmountMedium->setText(QApplication::translate("UIMachineSettingsStorage", "Remove disk from virtual drive"));3012 if (enmMediumType == UIMediumDeviceType_DVD)3013 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/cd_unmount_16px.png", ":/cd_unmount_disabled_16px.png"));3014 else if (enmMediumType == UIMediumDeviceType_Floppy)3015 pActionUnmountMedium->setIcon(UIIconPool::iconSet(":/fd_unmount_16px.png", ":/fd_unmount_disabled_16px.png"));3016 }3017 }3018 3019 void UICommon::updateMachineStorage(const CMachine &comConstMachine, const UIMediumTarget &target)3020 {3021 /* Mount (by default): */3022 bool fMount = true;3023 /* Null medium (by default): */3024 CMedium comMedium;3025 /* With null ID (by default): */3026 QUuid uActualID;3027 3028 /* Current mount-target attributes: */3029 const CStorageController comCurrentController = comConstMachine.GetStorageControllerByName(target.name);3030 const KStorageBus enmCurrentStorageBus = comCurrentController.GetBus();3031 const CMediumAttachment comCurrentAttachment = comConstMachine.GetMediumAttachment(target.name, target.port, target.device);3032 const CMedium comCurrentMedium = comCurrentAttachment.GetMedium();3033 const QUuid uCurrentID = comCurrentMedium.isNull() ? QUuid() : comCurrentMedium.GetId();3034 const QString strCurrentLocation = comCurrentMedium.isNull() ? QString() : comCurrentMedium.GetLocation();3035 3036 /* Which additional info do we have? */3037 switch (target.type)3038 {3039 /* Do we have an exact ID or do we let the user open a medium? */3040 case UIMediumTarget::UIMediumTargetType_WithID:3041 case UIMediumTarget::UIMediumTargetType_WithFileDialog:3042 case UIMediumTarget::UIMediumTargetType_CreateAdHocVISO:3043 case UIMediumTarget::UIMediumTargetType_CreateFloppyDisk:3044 {3045 /* New mount-target attributes: */3046 QUuid uNewID;3047 3048 /* Invoke file-open dialog to choose medium ID: */3049 if (target.mediumType != UIMediumDeviceType_Invalid && target.data.isNull())3050 {3051 /* Keyboard can be captured by machine-view.3052 * So we should clear machine-view focus to let file-open dialog get it.3053 * That way the keyboard will be released too.. */3054 QWidget *pLastFocusedWidget = 0;3055 if (QApplication::focusWidget())3056 {3057 pLastFocusedWidget = QApplication::focusWidget();3058 pLastFocusedWidget->clearFocus();3059 }3060 /* Call for file-open dialog: */3061 const QString strMachineFolder(QFileInfo(comConstMachine.GetSettingsFilePath()).absolutePath());3062 QUuid uMediumID;3063 if (target.type == UIMediumTarget::UIMediumTargetType_WithID)3064 {3065 int iDialogReturn = openMediumSelectorDialog(windowManager().mainWindowShown(), target.mediumType, uMediumID,3066 strMachineFolder, comConstMachine.GetName(),3067 comConstMachine.GetOSTypeId(), true /*fEnableCreate */, comConstMachine.GetId());3068 if (iDialogReturn == UIMediumSelector::ReturnCode_LeftEmpty &&3069 (target.mediumType == UIMediumDeviceType_DVD || target.mediumType == UIMediumDeviceType_Floppy))3070 fMount = false;3071 }3072 else if (target.type == UIMediumTarget::UIMediumTargetType_WithFileDialog)3073 {3074 uMediumID = openMediumWithFileOpenDialog(target.mediumType, windowManager().mainWindowShown(),3075 strMachineFolder, false /* fUseLastFolder */);3076 }3077 else if(target.type == UIMediumTarget::UIMediumTargetType_CreateAdHocVISO)3078 uMediumID = createVisoMediumWithVisoCreator(windowManager().mainWindowShown(), strMachineFolder, comConstMachine.GetName());3079 3080 else if(target.type == UIMediumTarget::UIMediumTargetType_CreateFloppyDisk)3081 uMediumID = showCreateFloppyDiskDialog(windowManager().mainWindowShown(), strMachineFolder, comConstMachine.GetName());3082 3083 /* Return focus back: */3084 if (pLastFocusedWidget)3085 pLastFocusedWidget->setFocus();3086 /* Accept new medium ID: */3087 if (!uMediumID.isNull())3088 uNewID = uMediumID;3089 else3090 /* Else just exit in case left empty is not chosen in medium selector dialog: */3091 if (fMount)3092 return;3093 }3094 /* Use medium ID which was passed: */3095 else if (!target.data.isNull() && target.data != uCurrentID.toString())3096 uNewID = target.data;3097 3098 /* Should we mount or unmount? */3099 fMount = !uNewID.isNull();3100 3101 /* Prepare target medium: */3102 const UIMedium guiMedium = medium(uNewID);3103 comMedium = guiMedium.medium();3104 uActualID = fMount ? uNewID : uCurrentID;3105 break;3106 }3107 /* Do we have a recent location? */3108 case UIMediumTarget::UIMediumTargetType_WithLocation:3109 {3110 /* Open medium by location and get new medium ID if any: */3111 const QUuid uNewID = openMedium(target.mediumType, target.data);3112 /* Else just exit: */3113 if (uNewID.isNull())3114 return;3115 3116 /* Should we mount or unmount? */3117 fMount = uNewID != uCurrentID;3118 3119 /* Prepare target medium: */3120 const UIMedium guiMedium = fMount ? medium(uNewID) : UIMedium();3121 comMedium = fMount ? guiMedium.medium() : CMedium();3122 uActualID = fMount ? uNewID : uCurrentID;3123 break;3124 }3125 }3126 3127 /* Do not unmount hard-drives: */3128 if (target.mediumType == UIMediumDeviceType_HardDisk && !fMount)3129 return;3130 3131 /* Get editable machine & session: */3132 CMachine comMachine = comConstMachine;3133 CSession comSession = tryToOpenSessionFor(comMachine);3134 3135 /* Remount medium to the predefined port/device: */3136 bool fWasMounted = false;3137 /* Hard drive case: */3138 if (target.mediumType == UIMediumDeviceType_HardDisk)3139 {3140 /* Detaching: */3141 comMachine.DetachDevice(target.name, target.port, target.device);3142 fWasMounted = comMachine.isOk();3143 if (!fWasMounted)3144 msgCenter().cannotDetachDevice(comMachine, UIMediumDeviceType_HardDisk, strCurrentLocation,3145 StorageSlot(enmCurrentStorageBus, target.port, target.device));3146 else3147 {3148 /* Attaching: */3149 comMachine.AttachDevice(target.name, target.port, target.device, KDeviceType_HardDisk, comMedium);3150 fWasMounted = comMachine.isOk();3151 if (!fWasMounted)3152 msgCenter().cannotAttachDevice(comMachine, UIMediumDeviceType_HardDisk, strCurrentLocation,3153 StorageSlot(enmCurrentStorageBus, target.port, target.device));3154 }3155 }3156 /* Optical/floppy drive case: */3157 else3158 {3159 /* Remounting: */3160 comMachine.MountMedium(target.name, target.port, target.device, comMedium, false /* force? */);3161 fWasMounted = comMachine.isOk();3162 if (!fWasMounted)3163 {3164 /* Ask for force remounting: */3165 if (msgCenter().cannotRemountMedium(comMachine, medium(uActualID),3166 fMount, true /* retry? */))3167 {3168 /* Force remounting: */3169 comMachine.MountMedium(target.name, target.port, target.device, comMedium, true /* force? */);3170 fWasMounted = comMachine.isOk();3171 if (!fWasMounted)3172 msgCenter().cannotRemountMedium(comMachine, medium(uActualID),3173 fMount, false /* retry? */);3174 }3175 }3176 /* If mounting was successful: */3177 if (fWasMounted)3178 {3179 /* Disable First RUN Wizard: */3180 if (gEDataManager->machineFirstTimeStarted(comMachine.GetId()))3181 gEDataManager->setMachineFirstTimeStarted(false, comMachine.GetId());3182 }3183 }3184 3185 /* Save settings: */3186 if (fWasMounted)3187 {3188 comMachine.SaveSettings();3189 if (!comMachine.isOk())3190 msgCenter().cannotSaveMachineSettings(comMachine, windowManager().mainWindowShown());3191 }3192 3193 /* Close session to editable comMachine if necessary: */3194 if (!comSession.isNull())3195 comSession.UnlockMachine();3196 }3197 3198 QString UICommon::details(const CMedium &comMedium, bool fPredictDiff, bool fUseHtml /* = true */)3199 {3200 /* Search for corresponding UI medium: */3201 const QUuid uMediumID = comMedium.isNull() ? UIMedium::nullID() : comMedium.GetId();3202 UIMedium guiMedium = medium(uMediumID);3203 if (!comMedium.isNull() && guiMedium.isNull())3204 {3205 /* UI medium may be new and not among cached media, request enumeration: */3206 enumerateMedia(CMediumVector() << comMedium);3207 3208 /* Search for corresponding UI medium again: */3209 guiMedium = medium(uMediumID);3210 if (guiMedium.isNull())3211 {3212 /* Medium might be deleted already, return null string: */3213 return QString();3214 }3215 }3216 3217 /* For differencing hard-disk we have to request3218 * enumeration of whole tree based in it's root item: */3219 if ( comMedium.isNotNull()3220 && comMedium.GetDeviceType() == KDeviceType_HardDisk)3221 {3222 /* Traverse through parents to root to catch it: */3223 CMedium comRootMedium;3224 CMedium comParentMedium = comMedium.GetParent();3225 while (comParentMedium.isNotNull())3226 {3227 comRootMedium = comParentMedium;3228 comParentMedium = comParentMedium.GetParent();3229 }3230 /* Enumerate root if it's found and wasn't cached: */3231 if (comRootMedium.isNotNull())3232 {3233 const QUuid uRootId = comRootMedium.GetId();3234 if (medium(uRootId).isNull())3235 enumerateMedia(CMediumVector() << comRootMedium);3236 }3237 }3238 3239 /* Return UI medium details: */3240 return fUseHtml ? guiMedium.detailsHTML(true /* no diffs? */, fPredictDiff) :3241 guiMedium.details(true /* no diffs? */, fPredictDiff);3242 }3243 3244 void UICommon::updateRecentlyUsedMediumListAndFolder(UIMediumDeviceType enmMediumType, QString strMediumLocation)3245 {3246 /** Don't add the medium to extra data if its name is in exclude list, m_recentMediaExcludeList: */3247 foreach (QString strExcludeName, m_recentMediaExcludeList)3248 {3249 if (strMediumLocation.contains(strExcludeName))3250 return;3251 }3252 3253 /* Remember the path of the last chosen medium: */3254 switch (enmMediumType)3255 {3256 case UIMediumDeviceType_HardDisk: gEDataManager->setRecentFolderForHardDrives(QFileInfo(strMediumLocation).absolutePath()); break;3257 case UIMediumDeviceType_DVD: gEDataManager->setRecentFolderForOpticalDisks(QFileInfo(strMediumLocation).absolutePath()); break;3258 case UIMediumDeviceType_Floppy: gEDataManager->setRecentFolderForFloppyDisks(QFileInfo(strMediumLocation).absolutePath()); break;3259 default: break;3260 }3261 3262 /* Update recently used list: */3263 QStringList recentMediumList;3264 switch (enmMediumType)3265 {3266 case UIMediumDeviceType_HardDisk: recentMediumList = gEDataManager->recentListOfHardDrives(); break;3267 case UIMediumDeviceType_DVD: recentMediumList = gEDataManager->recentListOfOpticalDisks(); break;3268 case UIMediumDeviceType_Floppy: recentMediumList = gEDataManager->recentListOfFloppyDisks(); break;3269 default: break;3270 }3271 if (recentMediumList.contains(strMediumLocation))3272 recentMediumList.removeAll(strMediumLocation);3273 recentMediumList.prepend(strMediumLocation);3274 while(recentMediumList.size() > 5)3275 recentMediumList.removeLast();3276 switch (enmMediumType)3277 {3278 case UIMediumDeviceType_HardDisk: gEDataManager->setRecentListOfHardDrives(recentMediumList); break;3279 case UIMediumDeviceType_DVD: gEDataManager->setRecentListOfOpticalDisks(recentMediumList); break;3280 case UIMediumDeviceType_Floppy: gEDataManager->setRecentListOfFloppyDisks(recentMediumList); break;3281 default: break;3282 }3283 }3284 3285 QString UICommon::defaultFolderPathForType(UIMediumDeviceType enmMediumType)3286 {3287 QString strLastFolder;3288 switch (enmMediumType)3289 {3290 case UIMediumDeviceType_HardDisk:3291 strLastFolder = gEDataManager->recentFolderForHardDrives();3292 if (strLastFolder.isEmpty())3293 strLastFolder = gEDataManager->recentFolderForOpticalDisks();3294 if (strLastFolder.isEmpty())3295 strLastFolder = gEDataManager->recentFolderForFloppyDisks();3296 break;3297 case UIMediumDeviceType_DVD:3298 strLastFolder = gEDataManager->recentFolderForOpticalDisks();3299 if (strLastFolder.isEmpty())3300 strLastFolder = gEDataManager->recentFolderForFloppyDisks();3301 if (strLastFolder.isEmpty())3302 strLastFolder = gEDataManager->recentFolderForHardDrives();3303 break;3304 case UIMediumDeviceType_Floppy:3305 strLastFolder = gEDataManager->recentFolderForFloppyDisks();3306 if (strLastFolder.isEmpty())3307 strLastFolder = gEDataManager->recentFolderForOpticalDisks();3308 if (strLastFolder.isEmpty())3309 strLastFolder = gEDataManager->recentFolderForHardDrives();3310 break;3311 default:3312 break;3313 }3314 3315 if (strLastFolder.isEmpty())3316 return virtualBox().GetSystemProperties().GetDefaultMachineFolder();3317 3318 return strLastFolder;3319 }3320 3321 #ifdef RT_OS_LINUX3322 /* static */3323 void UICommon::checkForWrongUSBMounted()3324 {3325 /* Make sure '/proc/mounts' exists and can be opened: */3326 QFile file("/proc/mounts");3327 if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text))3328 return;3329 3330 /* Fetch contents: */3331 QStringList contents;3332 for (;;)3333 {3334 QByteArray line = file.readLine();3335 if (line.isEmpty())3336 break;3337 contents << line;3338 }3339 /* Grep contents for usbfs presence: */3340 QStringList grep1(contents.filter("/sys/bus/usb/drivers"));3341 QStringList grep2(grep1.filter("usbfs"));3342 if (grep2.isEmpty())3343 return;3344 3345 /* Show corresponding warning: */3346 msgCenter().warnAboutWrongUSBMounted();3347 }3348 #endif /* RT_OS_LINUX */3349 3350 /* static */3351 QString UICommon::details(const CUSBDevice &comDevice)3352 {3353 QString strDetails;3354 if (comDevice.isNull())3355 strDetails = tr("Unknown device", "USB device details");3356 else3357 {3358 QVector<QString> devInfoVector = comDevice.GetDeviceInfo();3359 QString strManufacturer;3360 QString strProduct;3361 3362 if (devInfoVector.size() >= 1)3363 strManufacturer = devInfoVector[0].trimmed();3364 if (devInfoVector.size() >= 2)3365 strProduct = devInfoVector[1].trimmed();3366 3367 if (strManufacturer.isEmpty() && strProduct.isEmpty())3368 {3369 strDetails =3370 tr("Unknown device %1:%2", "USB device details")3371 .arg(QString().sprintf("%04hX", comDevice.GetVendorId()))3372 .arg(QString().sprintf("%04hX", comDevice.GetProductId()));3373 }3374 else3375 {3376 if (strProduct.toUpper().startsWith(strManufacturer.toUpper()))3377 strDetails = strProduct;3378 else3379 strDetails = strManufacturer + " " + strProduct;3380 }3381 ushort iRev = comDevice.GetRevision();3382 if (iRev != 0)3383 strDetails += QString().sprintf(" [%04hX]", iRev);3384 }3385 3386 return strDetails.trimmed();3387 }3388 3389 /* static */3390 QString UICommon::toolTip(const CUSBDevice &comDevice)3391 {3392 QString strTip =3393 tr("<nobr>Vendor ID: %1</nobr><br>"3394 "<nobr>Product ID: %2</nobr><br>"3395 "<nobr>Revision: %3</nobr>", "USB device tooltip")3396 .arg(QString().sprintf("%04hX", comDevice.GetVendorId()))3397 .arg(QString().sprintf("%04hX", comDevice.GetProductId()))3398 .arg(QString().sprintf("%04hX", comDevice.GetRevision()));3399 3400 const QString strSerial = comDevice.GetSerialNumber();3401 if (!strSerial.isEmpty())3402 strTip += QString(tr("<br><nobr>Serial No. %1</nobr>", "USB device tooltip"))3403 .arg(strSerial);3404 3405 /* Add the state field if it's a host USB device: */3406 CHostUSBDevice hostDev(comDevice);3407 if (!hostDev.isNull())3408 {3409 strTip += QString(tr("<br><nobr>State: %1</nobr>", "USB device tooltip"))3410 .arg(gpConverter->toString(hostDev.GetState()));3411 }3412 3413 return strTip;3414 }3415 3416 /* static */3417 QString UICommon::toolTip(const CUSBDeviceFilter &comFilter)3418 {3419 QString strTip;3420 3421 const QString strVendorId = comFilter.GetVendorId();3422 if (!strVendorId.isEmpty())3423 strTip += tr("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip")3424 .arg(strVendorId);3425 3426 const QString strProductId = comFilter.GetProductId();3427 if (!strProductId.isEmpty())3428 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Product ID: %2</nobr>", "USB filter tooltip")3429 .arg(strProductId);3430 3431 const QString strRevision = comFilter.GetRevision();3432 if (!strRevision.isEmpty())3433 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Revision: %3</nobr>", "USB filter tooltip")3434 .arg(strRevision);3435 3436 const QString strProduct = comFilter.GetProduct();3437 if (!strProduct.isEmpty())3438 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Product: %4</nobr>", "USB filter tooltip")3439 .arg(strProduct);3440 3441 const QString strManufacturer = comFilter.GetManufacturer();3442 if (!strManufacturer.isEmpty())3443 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip")3444 .arg(strManufacturer);3445 3446 const QString strSerial = comFilter.GetSerialNumber();3447 if (!strSerial.isEmpty())3448 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Serial No.: %1</nobr>", "USB filter tooltip")3449 .arg(strSerial);3450 3451 const QString strPort = comFilter.GetPort();3452 if (!strPort.isEmpty())3453 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>Port: %1</nobr>", "USB filter tooltip")3454 .arg(strPort);3455 3456 /* Add the state field if it's a host USB device: */3457 CHostUSBDevice hostDev(comFilter);3458 if (!hostDev.isNull())3459 {3460 strTip += strTip.isEmpty() ? "":"<br/>" + tr("<nobr>State: %1</nobr>", "USB filter tooltip")3461 .arg(gpConverter->toString(hostDev.GetState()));3462 }3463 3464 return strTip;3465 }3466 3467 /* static */3468 QString UICommon::toolTip(const CHostVideoInputDevice &comWebcam)3469 {3470 QStringList records;3471 3472 const QString strName = comWebcam.GetName();3473 if (!strName.isEmpty())3474 records << strName;3475 3476 const QString strPath = comWebcam.GetPath();3477 if (!strPath.isEmpty())3478 records << strPath;3479 3480 return records.join("<br>");3481 }3482 3483 void UICommon::doExtPackInstallation(QString const &strFilePath, QString const &strDigest,3484 QWidget *pParent, QString *pstrExtPackName) const3485 {3486 /* If the extension pack manager isn't available, skip any attempts to install: */3487 CExtPackManager extPackManager = virtualBox().GetExtensionPackManager();3488 if (extPackManager.isNull())3489 return;3490 /* Open the extpack tarball via IExtPackManager: */3491 CExtPackFile comExtPackFile;3492 if (strDigest.isEmpty())3493 comExtPackFile = extPackManager.OpenExtPackFile(strFilePath);3494 else3495 {3496 QString strFileAndHash = QString("%1::SHA-256=%2").arg(strFilePath).arg(strDigest);3497 comExtPackFile = extPackManager.OpenExtPackFile(strFileAndHash);3498 }3499 if (!extPackManager.isOk())3500 {3501 msgCenter().cannotOpenExtPack(strFilePath, extPackManager, pParent);3502 return;3503 }3504 3505 if (!comExtPackFile.GetUsable())3506 {3507 msgCenter().warnAboutBadExtPackFile(strFilePath, comExtPackFile, pParent);3508 return;3509 }3510 3511 const QString strPackName = comExtPackFile.GetName();3512 const QString strPackDescription = comExtPackFile.GetDescription();3513 const QString strPackVersion = QString("%1r%2%3").arg(comExtPackFile.GetVersion()).arg(comExtPackFile.GetRevision()).arg(comExtPackFile.GetEdition());3514 3515 /* Check if there is a version of the extension pack already3516 * installed on the system and let the user decide what to do about it. */3517 CExtPack comExtPackCur = extPackManager.Find(strPackName);3518 bool fReplaceIt = comExtPackCur.isOk();3519 if (fReplaceIt)3520 {3521 QString strPackVersionCur = QString("%1r%2%3").arg(comExtPackCur.GetVersion()).arg(comExtPackCur.GetRevision()).arg(comExtPackCur.GetEdition());3522 if (!msgCenter().confirmReplaceExtensionPack(strPackName, strPackVersion, strPackVersionCur, strPackDescription, pParent))3523 return;3524 }3525 /* If it's a new package just ask for general confirmation. */3526 else3527 {3528 if (!msgCenter().confirmInstallExtensionPack(strPackName, strPackVersion, strPackDescription, pParent))3529 return;3530 }3531 3532 /* Display the license dialog if required by the extension pack. */3533 if (comExtPackFile.GetShowLicense())3534 {3535 QString strLicense = comExtPackFile.GetLicense();3536 VBoxLicenseViewer licenseViewer(pParent);3537 if (licenseViewer.showLicenseFromString(strLicense) != QDialog::Accepted)3538 return;3539 }3540 3541 /* Install the selected package.3542 * Set the package name return value before doing3543 * this as the caller should do a refresh even on failure. */3544 QString strDisplayInfo;3545 #ifdef VBOX_WS_WIN3546 if (pParent)3547 strDisplayInfo.sprintf("hwnd=%#llx", (uint64_t)(uintptr_t)pParent->winId());3548 #endif3549 3550 /* Install extension pack: */3551 UINotificationProgressExtensionPackInstall *pNotification =3552 new UINotificationProgressExtensionPackInstall(comExtPackFile,3553 fReplaceIt,3554 strPackName,3555 strDisplayInfo);3556 connect(pNotification, &UINotificationProgressExtensionPackInstall::sigExtensionPackInstalled,3557 this, &UICommon::sigExtensionPackInstalled);3558 gpNotificationCenter->append(pNotification);3559 3560 /* Store the name: */3561 if (pstrExtPackName)3562 *pstrExtPackName = strPackName;3563 }3564 3565 #ifdef VBOX_WITH_3D_ACCELERATION3566 /* static */3567 bool UICommon::isWddmCompatibleOsType(const QString &strGuestOSTypeId)3568 {3569 return strGuestOSTypeId.startsWith("WindowsVista")3570 || strGuestOSTypeId.startsWith("Windows7")3571 || strGuestOSTypeId.startsWith("Windows8")3572 || strGuestOSTypeId.startsWith("Windows81")3573 || strGuestOSTypeId.startsWith("Windows10")3574 || strGuestOSTypeId.startsWith("Windows2008")3575 || strGuestOSTypeId.startsWith("Windows2012");3576 }3577 #endif /* VBOX_WITH_3D_ACCELERATION */3578 3579 /* static */3580 quint64 UICommon::requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors /* = 1 */)3581 {3582 /* We create a list of the size of all available host monitors. This list3583 * is sorted by value and by starting with the biggest one, we calculate3584 * the memory requirements for every guest screen. This is of course not3585 * correct, but as we can't predict on which host screens the user will3586 * open the guest windows, this is the best assumption we can do, cause it3587 * is the worst case. */3588 const int cHostScreens = gpDesktop->screenCount();3589 QVector<int> screenSize(qMax(cMonitors, cHostScreens), 0);3590 for (int i = 0; i < cHostScreens; ++i)3591 {3592 QRect r = gpDesktop->screenGeometry(i);3593 screenSize[i] = r.width() * r.height();3594 }3595 /* Now sort the vector: */3596 std::sort(screenSize.begin(), screenSize.end(), std::greater<int>());3597 /* For the case that there are more guest screens configured then host3598 * screens available, replace all zeros with the greatest value in the3599 * vector. */3600 for (int i = 0; i < screenSize.size(); ++i)3601 if (screenSize.at(i) == 0)3602 screenSize.replace(i, screenSize.at(0));3603 3604 quint64 uNeedBits = 0;3605 for (int i = 0; i < cMonitors; ++i)3606 {3607 /* Calculate summary required memory amount in bits: */3608 uNeedBits += (screenSize.at(i) * /* with x height */3609 32 + /* we will take the maximum possible bpp for now */3610 8 * _1M) + /* current cache per screen - may be changed in future */3611 8 * 4096; /* adapter info */3612 }3613 /* Translate value into megabytes with rounding to highest side: */3614 quint64 uNeedMBytes = uNeedBits % (8 * _1M)3615 ? uNeedBits / (8 * _1M) + 13616 : uNeedBits / (8 * _1M) /* convert to megabytes */;3617 3618 if (strGuestOSTypeId.startsWith("Windows"))3619 {3620 /* Windows guests need offscreen VRAM too for graphics acceleration features: */3621 #ifdef VBOX_WITH_3D_ACCELERATION3622 if (isWddmCompatibleOsType(strGuestOSTypeId))3623 {3624 /* WDDM mode, there are two surfaces for each screen: shadow & primary: */3625 uNeedMBytes *= 3;3626 }3627 else3628 #endif /* VBOX_WITH_3D_ACCELERATION */3629 {3630 uNeedMBytes *= 2;3631 }3632 }3633 3634 return uNeedMBytes * _1M;3635 }3636 3637 QIcon UICommon::vmUserIcon(const CMachine &comMachine) const3638 {3639 /* Prepare fallback icon: */3640 static QIcon nullIcon;3641 3642 /* Make sure general icon-pool initialized: */3643 AssertReturn(m_pIconPool, nullIcon);3644 3645 /* Redirect to general icon-pool: */3646 return m_pIconPool->userMachineIcon(comMachine);3647 }3648 3649 QPixmap UICommon::vmUserPixmap(const CMachine &comMachine, const QSize &size) const3650 {3651 /* Prepare fallback pixmap: */3652 static QPixmap nullPixmap;3653 3654 /* Make sure general icon-pool initialized: */3655 AssertReturn(m_pIconPool, nullPixmap);3656 3657 /* Redirect to general icon-pool: */3658 return m_pIconPool->userMachinePixmap(comMachine, size);3659 }3660 3661 QPixmap UICommon::vmUserPixmapDefault(const CMachine &comMachine, QSize *pLogicalSize /* = 0 */) const3662 {3663 /* Prepare fallback pixmap: */3664 static QPixmap nullPixmap;3665 3666 /* Make sure general icon-pool initialized: */3667 AssertReturn(m_pIconPool, nullPixmap);3668 3669 /* Redirect to general icon-pool: */3670 return m_pIconPool->userMachinePixmapDefault(comMachine, pLogicalSize);3671 }3672 3673 QIcon UICommon::vmGuestOSTypeIcon(const QString &strOSTypeID) const3674 {3675 /* Prepare fallback icon: */3676 static QIcon nullIcon;3677 3678 /* Make sure general icon-pool initialized: */3679 AssertReturn(m_pIconPool, nullIcon);3680 3681 /* Redirect to general icon-pool: */3682 return m_pIconPool->guestOSTypeIcon(strOSTypeID);3683 }3684 3685 QPixmap UICommon::vmGuestOSTypePixmap(const QString &strOSTypeID, const QSize &size) const3686 {3687 /* Prepare fallback pixmap: */3688 static QPixmap nullPixmap;3689 3690 /* Make sure general icon-pool initialized: */3691 AssertReturn(m_pIconPool, nullPixmap);3692 3693 /* Redirect to general icon-pool: */3694 return m_pIconPool->guestOSTypePixmap(strOSTypeID, size);3695 }3696 3697 QPixmap UICommon::vmGuestOSTypePixmapDefault(const QString &strOSTypeID, QSize *pLogicalSize /* = 0 */) const3698 {3699 /* Prepare fallback pixmap: */3700 static QPixmap nullPixmap;3701 3702 /* Make sure general icon-pool initialized: */3703 AssertReturn(m_pIconPool, nullPixmap);3704 3705 /* Redirect to general icon-pool: */3706 return m_pIconPool->guestOSTypePixmapDefault(strOSTypeID, pLogicalSize);3707 }3708 3709 /* static */3710 QPixmap UICommon::joinPixmaps(const QPixmap &pixmap1, const QPixmap &pixmap2)3711 {3712 if (pixmap1.isNull())3713 return pixmap2;3714 if (pixmap2.isNull())3715 return pixmap1;3716 3717 QPixmap result(pixmap1.width() + pixmap2.width() + 2,3718 qMax(pixmap1.height(), pixmap2.height()));3719 result.fill(Qt::transparent);3720 3721 QPainter painter(&result);3722 painter.drawPixmap(0, 0, pixmap1);3723 painter.drawPixmap(pixmap1.width() + 2, result.height() - pixmap2.height(), pixmap2);3724 painter.end();3725 3726 return result;3727 }3728 3729 /* static */3730 void UICommon::setHelpKeyword(QObject *pObject, const QString &strHelpKeyword)3731 {3732 if (pObject)3733 pObject->setProperty("helpkeyword", strHelpKeyword);3734 }3735 3736 /* static */3737 QString UICommon::helpKeyword(const QObject *pObject)3738 {3739 if (!pObject)3740 return QString();3741 return pObject->property("helpkeyword").toString();3742 }3743 3744 bool UICommon::openURL(const QString &strUrl) const3745 {3746 /** Service event. */3747 class ServiceEvent : public QEvent3748 {3749 public:3750 3751 /** Constructs service event on th basis of passed @a fResult. */3752 ServiceEvent(bool fResult)3753 : QEvent(QEvent::User)3754 , m_fResult(fResult)3755 {}3756 3757 /** Returns the result which event brings. */3758 bool result() const { return m_fResult; }3759 3760 private:3761 3762 /** Holds the result which event brings. */3763 bool m_fResult;3764 };3765 3766 /** Service client object. */3767 class ServiceClient : public QEventLoop3768 {3769 public:3770 3771 /** Constructs service client on the basis of passed @a fResult. */3772 ServiceClient()3773 : m_fResult(false)3774 {}3775 3776 /** Returns the result which event brings. */3777 bool result() const { return m_fResult; }3778 3779 private:3780 3781 /** Handles any Qt @a pEvent. */3782 bool event(QEvent *pEvent)3783 {3784 /* Handle service event: */3785 if (pEvent->type() == QEvent::User)3786 {3787 ServiceEvent *pServiceEvent = static_cast<ServiceEvent*>(pEvent);3788 m_fResult = pServiceEvent->result();3789 pServiceEvent->accept();3790 quit();3791 return true;3792 }3793 return false;3794 }3795 3796 bool m_fResult;3797 };3798 3799 /** Service server object. */3800 class ServiceServer : public QThread3801 {3802 public:3803 3804 /** Constructs service server on the basis of passed @a client and @a strUrl. */3805 ServiceServer(ServiceClient &client, const QString &strUrl)3806 : m_client(client), m_strUrl(strUrl) {}3807 3808 private:3809 3810 /** Executes thread task. */3811 void run()3812 {3813 QApplication::postEvent(&m_client, new ServiceEvent(QDesktopServices::openUrl(m_strUrl)));3814 }3815 3816 /** Holds the client reference. */3817 ServiceClient &m_client;3818 /** Holds the URL to be processed. */3819 const QString &m_strUrl;3820 };3821 3822 /* Create client & server: */3823 ServiceClient client;3824 ServiceServer server(client, strUrl);3825 server.start();3826 client.exec();3827 server.wait();3828 3829 /* Acquire client result: */3830 bool fResult = client.result();3831 3832 if (!fResult)3833 msgCenter().cannotOpenURL(strUrl);3834 3835 return fResult;3836 }3837 3838 void UICommon::sltGUILanguageChange(QString strLanguage)3839 {3840 /* Make sure medium-enumeration is not in progress! */3841 AssertReturnVoid(!isMediumEnumerationInProgress());3842 /* Load passed language: */3843 UITranslator::loadLanguage(strLanguage);3844 }3845 3846 void UICommon::sltHandleMediumCreated(const CMedium &comMedium)3847 {3848 /* Acquire device type: */3849 const KDeviceType enmDeviceType = comMedium.GetDeviceType();3850 if (!comMedium.isOk())3851 msgCenter().cannotAcquireMediumAttribute(comMedium);3852 else3853 {3854 /* Convert to medium type: */3855 const UIMediumDeviceType enmMediumType = mediumTypeToLocal(enmDeviceType);3856 3857 /* Make sure we cached created medium in GUI: */3858 createMedium(UIMedium(comMedium, enmMediumType, KMediumState_Created));3859 }3860 }3861 3862 void UICommon::sltHandleMachineCreated(const CMachine &comMachine)3863 {3864 /* Register created machine. */3865 CVirtualBox comVBox = virtualBox();3866 comVBox.RegisterMachine(comMachine);3867 if (!comVBox.isOk())3868 msgCenter().cannotRegisterMachine(comVBox, comMachine.GetName());3869 }3870 3871 void UICommon::sltHandleCloudMachineAdded(const QString &strProviderShortName,3872 const QString &strProfileName,3873 const CCloudMachine &comMachine)3874 {3875 /* Make sure we cached added cloud VM in GUI: */3876 notifyCloudMachineRegistered(strProviderShortName,3877 strProfileName,3878 comMachine);3879 }3880 3881 bool UICommon::eventFilter(QObject *pObject, QEvent *pEvent)3882 {3883 /** @todo Just use the QIWithRetranslateUI3 template wrapper. */3884 3885 if ( pEvent->type() == QEvent::LanguageChange3886 && pObject->isWidgetType()3887 && static_cast<QWidget*>(pObject)->isTopLevel())3888 {3889 /* Catch the language change event before any other widget gets it in3890 * order to invalidate cached string resources (like the details view3891 * templates) that may be used by other widgets. */3892 QWidgetList list = QApplication::topLevelWidgets();3893 if (list.first() == pObject)3894 {3895 /* Call this only once per every language change (see3896 * QApplication::installTranslator() for details): */3897 retranslateUi();3898 }3899 }3900 3901 /* Call to base-class: */3902 return QObject::eventFilter(pObject, pEvent);3903 }3904 3905 void UICommon::retranslateUi()3906 {3907 m_pixWarning = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxWarning).pixmap(16, 16);3908 Assert(!m_pixWarning.isNull());3909 3910 m_pixError = UIIconPool::defaultIcon(UIIconPool::UIDefaultIconType_MessageBoxCritical).pixmap(16, 16);3911 Assert(!m_pixError.isNull());3912 3913 /* Re-enumerate uimedium since they contain some translations too: */3914 if (m_fValid)3915 refreshMedia();3916 3917 #ifdef VBOX_WS_X113918 // WORKAROUND:3919 // As X11 do not have functionality for providing human readable key names,3920 // we keep a table of them, which must be updated when the language is changed.3921 UINativeHotKey::retranslateKeyNames();3922 #endif3923 }3924 3925 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS13926 void UICommon::sltHandleCommitDataRequest(QSessionManager &manager)3927 {3928 LogRel(("GUI: UICommon: Commit data request..\n"));3929 3930 /* Ask listener to commit data: */3931 emit sigAskToCommitData();3932 #ifdef VBOX_WS_WIN3933 m_fDataCommitted = true;3934 #endif3935 3936 /* Depending on UI type: */3937 switch (uiType())3938 {3939 /* For Runtime UI: */3940 case UIType_RuntimeUI:3941 {3942 /* Thin clients will be able to shutdown properly,3943 * but for fat clients: */3944 if (!isSeparateProcess())3945 {3946 // WORKAROUND:3947 // We can't save VM state in one go for fat clients, so we have to ask session manager to cancel shutdown.3948 // To next major release this should be removed in any case, since there will be no fat clients after all.3949 manager.cancel();3950 3951 #ifdef VBOX_WS_WIN3952 // WORKAROUND:3953 // In theory that's Qt5 who should allow us to provide canceling reason as well, but that functionality3954 // seems to be missed in Windows platform plugin, so we are making that ourselves.3955 ShutdownBlockReasonCreateAPI((HWND)windowManager().mainWindowShown()->winId(), L"VM is still running.");3956 #endif3957 }3958 3959 break;3960 }3961 default:3962 break;3963 }3964 }3965 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */3966 3967 void UICommon::sltHandleVBoxSVCAvailabilityChange(bool fAvailable)3968 {3969 /* Make sure the VBoxSVC availability changed: */3970 if (m_fVBoxSVCAvailable == fAvailable)3971 return;3972 3973 /* Cache the new VBoxSVC availability value: */3974 m_fVBoxSVCAvailable = fAvailable;3975 3976 /* If VBoxSVC is not available: */3977 if (!m_fVBoxSVCAvailable)3978 {3979 /* Mark wrappers invalid: */3980 m_fWrappersValid = false;3981 /* Re-fetch corresponding CVirtualBox to restart VBoxSVC: */3982 m_comVBox = m_comVBoxClient.GetVirtualBox();3983 if (!m_comVBoxClient.isOk())3984 {3985 // The proper behavior would be to show the message and to exit the app, e.g.:3986 // msgCenter().cannotAcquireVirtualBox(m_comVBoxClient);3987 // return QApplication::quit();3988 // But CVirtualBox is still NULL in current Main implementation,3989 // and this call do not restart anything, so we are waiting3990 // for subsequent event about VBoxSVC is available again.3991 }3992 }3993 /* If VBoxSVC is available: */3994 else3995 {3996 if (!m_fWrappersValid)3997 {3998 /* Re-fetch corresponding CVirtualBox: */3999 m_comVBox = m_comVBoxClient.GetVirtualBox();4000 if (!m_comVBoxClient.isOk())4001 {4002 msgCenter().cannotAcquireVirtualBox(m_comVBoxClient);4003 return QApplication::quit();4004 }4005 /* Re-init wrappers: */4006 comWrappersReinit();4007 4008 /* For Selector UI: */4009 if (uiType() == UIType_SelectorUI)4010 {4011 /* Recreate Main event listeners: */4012 UIVirtualBoxEventHandler::destroy();4013 UIVirtualBoxClientEventHandler::destroy();4014 UIExtraDataManager::destroy();4015 UIExtraDataManager::instance();4016 UIVirtualBoxEventHandler::instance();4017 UIVirtualBoxClientEventHandler::instance();4018 /* Ask UIStarter to restart UI: */4019 emit sigAskToRestartUI();4020 }4021 }4022 }4023 4024 /* Notify listeners about the VBoxSVC availability change: */4025 emit sigVBoxSVCAvailabilityChange();4026 }4027 4028 #ifdef VBOX_WS_WIN4029 /* static */4030 BOOL UICommon::ShutdownBlockReasonCreateAPI(HWND hWnd, LPCWSTR pwszReason)4031 {4032 BOOL fResult = FALSE;4033 typedef BOOL(WINAPI *PFNSHUTDOWNBLOCKREASONCREATE)(HWND hWnd, LPCWSTR pwszReason);4034 4035 PFNSHUTDOWNBLOCKREASONCREATE pfn = (PFNSHUTDOWNBLOCKREASONCREATE)GetProcAddress(4036 GetModuleHandle(L"User32.dll"), "ShutdownBlockReasonCreate");4037 _ASSERTE(pfn);4038 if (pfn)4039 fResult = pfn(hWnd, pwszReason);4040 return fResult;4041 }4042 #endif4043 4044 #ifdef VBOX_WITH_DEBUGGER_GUI4045 4046 # define UICOMMON_DBG_CFG_VAR_FALSE (0)4047 # define UICOMMON_DBG_CFG_VAR_TRUE (1)4048 # define UICOMMON_DBG_CFG_VAR_MASK (1)4049 # define UICOMMON_DBG_CFG_VAR_CMD_LINE RT_BIT(3)4050 # define UICOMMON_DBG_CFG_VAR_DONE RT_BIT(4)4051 4052 void UICommon::initDebuggerVar(int *piDbgCfgVar, const char *pszEnvVar, const char *pszExtraDataName, bool fDefault)4053 {4054 QString strEnvValue;4055 char szEnvValue[256];4056 int rc = RTEnvGetEx(RTENV_DEFAULT, pszEnvVar, szEnvValue, sizeof(szEnvValue), NULL);4057 if (RT_SUCCESS(rc))4058 {4059 strEnvValue = QString::fromUtf8(&szEnvValue[0]).toLower().trimmed();4060 if (strEnvValue.isEmpty())4061 strEnvValue = "yes";4062 }4063 else if (rc != VERR_ENV_VAR_NOT_FOUND)4064 strEnvValue = "veto";4065 4066 QString strExtraValue = m_comVBox.GetExtraData(pszExtraDataName).toLower().trimmed();4067 if (strExtraValue.isEmpty())4068 strExtraValue = QString();4069 4070 if ( strEnvValue.contains("veto") || strExtraValue.contains("veto"))4071 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_FALSE;4072 else if (strEnvValue.isNull() && strExtraValue.isNull())4073 *piDbgCfgVar = fDefault ? UICOMMON_DBG_CFG_VAR_TRUE : UICOMMON_DBG_CFG_VAR_FALSE;4074 else4075 {4076 QString *pStr = !strEnvValue.isEmpty() ? &strEnvValue : &strExtraValue;4077 if ( pStr->startsWith("y") // yes4078 || pStr->startsWith("e") // enabled4079 || pStr->startsWith("t") // true4080 || pStr->startsWith("on")4081 || pStr->toLongLong() != 0)4082 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_TRUE;4083 else if ( pStr->startsWith("n") // o4084 || pStr->startsWith("d") // disable4085 || pStr->startsWith("f") // false4086 || pStr->startsWith("off")4087 || pStr->contains("veto") /* paranoia */4088 || pStr->toLongLong() == 0)4089 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_FALSE;4090 else4091 {4092 LogFunc(("Ignoring unknown value '%s' for '%s'\n", pStr->toUtf8().constData(), pStr == &strEnvValue ? pszEnvVar : pszExtraDataName));4093 *piDbgCfgVar = fDefault ? UICOMMON_DBG_CFG_VAR_TRUE : UICOMMON_DBG_CFG_VAR_FALSE;4094 }4095 }4096 }4097 4098 void UICommon::setDebuggerVar(int *piDbgCfgVar, bool fState)4099 {4100 if (!(*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_DONE))4101 *piDbgCfgVar = (fState ? UICOMMON_DBG_CFG_VAR_TRUE : UICOMMON_DBG_CFG_VAR_FALSE)4102 | UICOMMON_DBG_CFG_VAR_CMD_LINE;4103 }4104 4105 bool UICommon::isDebuggerWorker(int *piDbgCfgVar, const char *pszExtraDataName) const4106 {4107 if (!(*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_DONE))4108 {4109 const QString str = gEDataManager->debugFlagValue(pszExtraDataName);4110 if (str.contains("veto"))4111 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_FALSE;4112 else if (str.isEmpty() || (*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_CMD_LINE))4113 *piDbgCfgVar |= UICOMMON_DBG_CFG_VAR_DONE;4114 else if ( str.startsWith("y") // yes4115 || str.startsWith("e") // enabled4116 || str.startsWith("t") // true4117 || str.startsWith("on")4118 || str.toLongLong() != 0)4119 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_TRUE;4120 else if ( str.startsWith("n") // no4121 || str.startsWith("d") // disable4122 || str.startsWith("f") // false4123 || str.toLongLong() == 0)4124 *piDbgCfgVar = UICOMMON_DBG_CFG_VAR_DONE | UICOMMON_DBG_CFG_VAR_FALSE;4125 else4126 *piDbgCfgVar |= UICOMMON_DBG_CFG_VAR_DONE;4127 }4128 4129 return (*piDbgCfgVar & UICOMMON_DBG_CFG_VAR_MASK) == UICOMMON_DBG_CFG_VAR_TRUE;4130 }4131 4132 #endif /* VBOX_WITH_DEBUGGER_GUI */4133 4134 void UICommon::comWrappersReinit()4135 {4136 /* Re-fetch corresponding objects/values: */4137 m_comHost = virtualBox().GetHost();4138 m_strHomeFolder = virtualBox().GetHomeFolder();4139 4140 /* Re-initialize guest OS Type list: */4141 m_guestOSFamilyIDs.clear();4142 m_guestOSTypes.clear();4143 const CGuestOSTypeVector guestOSTypes = m_comVBox.GetGuestOSTypes();4144 const int cGuestOSTypeCount = guestOSTypes.size();4145 AssertMsg(cGuestOSTypeCount > 0, ("Number of OS types must not be zero"));4146 if (cGuestOSTypeCount > 0)4147 {4148 /* Here we ASSUME the 'Other' types are always the first,4149 * so we remember them and will append them to the list when finished.4150 * We do a two pass, first adding the specific types, then the two 'Other' types. */4151 for (int j = 0; j < 2; ++j)4152 {4153 int cMax = j == 0 ? cGuestOSTypeCount : RT_MIN(2, cGuestOSTypeCount);4154 for (int i = j == 0 ? 2 : 0; i < cMax; ++i)4155 {4156 const CGuestOSType os = guestOSTypes.at(i);4157 const QString strFamilyID = os.GetFamilyId();4158 const QString strFamilyDescription = os.GetFamilyDescription();4159 if (!m_guestOSFamilyIDs.contains(strFamilyID))4160 {4161 m_guestOSFamilyIDs << strFamilyID;4162 m_guestOSFamilyDescriptions[strFamilyID] = strFamilyDescription;4163 m_guestOSTypes << QList<CGuestOSType>();4164 }4165 m_guestOSTypes[m_guestOSFamilyIDs.indexOf(strFamilyID)].append(os);4166 }4167 }4168 }4169 4170 /* Mark wrappers valid: */4171 m_fWrappersValid = true;4172 } -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UICursor.h
r90967 r91003 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIC ommon classdeclaration.3 * VBox Qt GUI - UICursor namespace declaration. 4 4 */ 5 5 … … 16 16 */ 17 17 18 #ifndef FEQT_INCLUDED_SRC_globals_UIC ommon_h19 #define FEQT_INCLUDED_SRC_globals_UIC ommon_h18 #ifndef FEQT_INCLUDED_SRC_globals_UICursor_h 19 #define FEQT_INCLUDED_SRC_globals_UICursor_h 20 20 #ifndef RT_WITHOUT_PRAGMA_ONCE 21 21 # pragma once 22 22 #endif 23 23 24 /* Qt includes: */25 #include <QFileIconProvider>26 #include <QMap>27 #include <QReadWriteLock>28 29 24 /* GUI includes: */ 30 #include "UIDefs.h"31 25 #include "UILibraryDefs.h" 32 #include "UIMediumDefs.h"33 #ifdef VBOX_WS_X1134 # include "VBoxX11Helper.h"35 #endif36 37 /* COM includes: */38 #include "CGuestOSType.h"39 #include "CHost.h"40 #include "CMedium.h"41 #include "CSession.h"42 #include "CVirtualBox.h"43 #include "CVirtualBoxClient.h"44 45 /* Other VBox includes: */46 #include "VBox/com/Guid.h"47 48 /* Other includes: */49 #ifdef VBOX_WS_X1150 # include <X11/Xdefs.h>51 #endif52 26 53 27 /* Forward declarations: */ 54 28 class QGraphicsWidget; 55 class QMenu; 56 class QSessionManager; 57 class QSpinBox; 58 class QToolButton; 59 class CCloudMachine; 60 class CHostVideoInputDevice; 61 class CMachine; 62 class CUSBDevice; 63 class UIIconPoolGeneral; 64 class UIMedium; 65 class UIMediumEnumerator; 66 class UIThreadPool; 29 class QWidget; 67 30 68 31 /** QObject subclass containing common GUI functionality. */ 69 class SHARED_LIBRARY_STUFF UICommon : public QObject 32 namespace UICursor 70 33 { 71 Q_OBJECT; 34 /** Does some checks on certain platforms before calling QWidget::setCursor(...). */ 35 SHARED_LIBRARY_STUFF void setCursor(QWidget *pWidget, const QCursor &cursor); 36 /** Does some checks on certain platforms before calling QGraphicsWidget::setCursor(...). */ 37 SHARED_LIBRARY_STUFF void setCursor(QGraphicsWidget *pWidget, const QCursor &cursor); 38 /** Does some checks on certain platforms before calling QWidget::unsetCursor(). */ 39 SHARED_LIBRARY_STUFF void unsetCursor(QWidget *pWidget); 40 /** Does some checks on certain platforms before calling QGraphicsWidget::unsetCursor(). */ 41 SHARED_LIBRARY_STUFF void unsetCursor(QGraphicsWidget *pWidget); 42 } 72 43 73 signals: 74 75 /** @name Common stuff. 76 * @{ */ 77 /** Asks #UIStarter listener to restart UI. */ 78 void sigAskToRestartUI(); 79 /** Asks #UIStarter listener to close UI. */ 80 void sigAskToCloseUI(); 81 82 /** Notifies listeners about the VBoxSVC availability change. */ 83 void sigVBoxSVCAvailabilityChange(); 84 85 /** Asks listeners to commit data. */ 86 void sigAskToCommitData(); 87 /** Asks listeners to detach COM. */ 88 void sigAskToDetachCOM(); 89 /** @} */ 90 91 /** @name COM: Extension Pack stuff. 92 * @{ */ 93 /** Notifies listeners about extension pack @a strName was installed. */ 94 void sigExtensionPackInstalled(const QString &strName); 95 /** @} */ 96 97 /** @name Cloud Virtual Machine stuff. 98 * @{ */ 99 /** Notifies listeners about cloud VM was unregistered. 100 * @param strProviderShortName Brings provider short name. 101 * @param strProfileName Brings profile name. 102 * @param uId Brings cloud VM id. */ 103 void sigCloudMachineUnregistered(const QString &strProviderShortName, 104 const QString &strProfileName, 105 const QUuid &uId); 106 /** Notifies listeners about cloud VM was registered. 107 * @param strProviderShortName Brings provider short name. 108 * @param strProfileName Brings profile name. 109 * @param comMachine Brings cloud VM. */ 110 void sigCloudMachineRegistered(const QString &strProviderShortName, 111 const QString &strProfileName, 112 const CCloudMachine &comMachine); 113 /** @} */ 114 115 /** @name COM: Virtual Media stuff. 116 * @{ */ 117 /** Notifies listeners about medium with certain @a uMediumID created. */ 118 void sigMediumCreated(const QUuid &uMediumID); 119 /** Notifies listeners about medium with certain @a uMediumID deleted. */ 120 void sigMediumDeleted(const QUuid &uMediumID); 121 122 /** Notifies listeners about medium-enumeration started. */ 123 void sigMediumEnumerationStarted(); 124 /** Notifies listeners about medium with certain @a uMediumID enumerated. */ 125 void sigMediumEnumerated(const QUuid &uMediumID); 126 /** Notifies listeners about medium-enumeration finished. */ 127 void sigMediumEnumerationFinished(); 128 /** @} */ 129 130 public: 131 132 /** UI types. */ 133 enum UIType 134 { 135 UIType_SelectorUI, 136 UIType_RuntimeUI 137 }; 138 139 /** VM launch modes. */ 140 enum LaunchMode 141 { 142 LaunchMode_Invalid, 143 LaunchMode_Default, 144 LaunchMode_Headless, 145 LaunchMode_Separate 146 }; 147 148 /** VM launch running options. */ 149 enum LaunchRunning 150 { 151 LaunchRunning_Default, /**< Default (depends on debug settings). */ 152 LaunchRunning_No, /**< Start the VM paused. */ 153 LaunchRunning_Yes /**< Start the VM running. */ 154 }; 155 156 /** Returns UICommon instance. */ 157 static UICommon *instance() { return s_pInstance; } 158 /** Creates UICommon instance of passed @a enmType. */ 159 static void create(UIType enmType); 160 /** Destroys UICommon instance. */ 161 static void destroy(); 162 163 /** @name General stuff. 164 * @{ */ 165 /** Returns the UI type. */ 166 UIType uiType() const { return m_enmType; } 167 168 /** Returns whether UICommon instance is properly initialized. */ 169 bool isValid() const { return m_fValid; } 170 /** Returns whether UICommon instance cleanup is in progress. */ 171 bool isCleaningUp() const { return m_fCleaningUp; } 172 /** @} */ 173 174 /** @name Versioning stuff. 175 * @{ */ 176 /** Returns Qt runtime version string. */ 177 static QString qtRTVersionString(); 178 /** Returns Qt runtime version. */ 179 static uint qtRTVersion(); 180 /** Returns Qt runtime major version. */ 181 static uint qtRTMajorVersion(); 182 /** Returns Qt runtime minor version. */ 183 static uint qtRTMinorVersion(); 184 /** Returns Qt runtime revision number. */ 185 static uint qtRTRevisionNumber(); 186 187 /** Returns Qt compiled version string. */ 188 static QString qtCTVersionString(); 189 /** Returns Qt compiled version. */ 190 static uint qtCTVersion(); 191 192 /** Returns VBox version string. */ 193 QString vboxVersionString() const; 194 /** Returns normalized VBox version string. */ 195 QString vboxVersionStringNormalized() const; 196 /** Returns whether VBox version string contains BETA word. */ 197 bool isBeta() const; 198 199 /** Returns whether branding is active. */ 200 bool brandingIsActive(bool fForce = false); 201 /** Returns value for certain branding @a strKey from custom.ini file. */ 202 QString brandingGetKey(QString strKey) const; 203 /** @} */ 204 205 /** @name Host OS stuff. 206 * @{ */ 207 #ifdef VBOX_WS_MAC 208 /** Mac OS X: Returns #MacOSXRelease determined by <i>uname</i> call. */ 209 static MacOSXRelease determineOsRelease(); 210 /** Mac OS X: Returns #MacOSXRelease determined during UICommon prepare routine. */ 211 MacOSXRelease osRelease() const { return m_enmMacOSVersion; } 212 #endif 213 214 #ifdef VBOX_WS_WIN 215 /** Loads the color theme. */ 216 static void loadColorTheme(); 217 #endif 218 219 #ifdef VBOX_WS_X11 220 /** X11: Returns whether the Window Manager we are running under is composition one. */ 221 bool isCompositingManagerRunning() const { return m_fCompositingManagerRunning; } 222 /** X11: Returns the type of the Window Manager we are running under. */ 223 X11WMType typeOfWindowManager() const { return m_enmWindowManagerType; } 224 #endif 225 /** @} */ 226 227 /** @name Process arguments stuff. 228 * @{ */ 229 /** Process application args. */ 230 bool processArgs(); 231 232 /** Returns whether there are unhandled URL arguments present. */ 233 bool argumentUrlsPresent() const; 234 /** Takes and returns the URL argument list while clearing the source. */ 235 QList<QUrl> takeArgumentUrls(); 236 237 /** Returns the --startvm option value (managed VM id). */ 238 QUuid managedVMUuid() const { return m_strManagedVMId; } 239 /** Returns the --separate option value (whether GUI process is separate from VM process). */ 240 bool isSeparateProcess() const { return m_fSeparateProcess; } 241 /** Returns the --no-startvm-errormsgbox option value (whether startup VM errors are disabled). */ 242 bool showStartVMErrors() const { return m_fShowStartVMErrors; } 243 244 /** Returns the --aggressive-caching / --no-aggressive-caching option value (whether medium-enumeration is required). */ 245 bool agressiveCaching() const { return m_fAgressiveCaching; } 246 247 /** Returns the --restore-current option value (whether we should restore current snapshot before VM started). */ 248 bool shouldRestoreCurrentSnapshot() const { return m_fRestoreCurrentSnapshot; } 249 /** Defines whether we should fRestore current snapshot before VM started. */ 250 void setShouldRestoreCurrentSnapshot(bool fRestore) { m_fRestoreCurrentSnapshot = fRestore; } 251 252 /** Returns the --fda option value (whether we have floppy image). */ 253 bool hasFloppyImageToMount() const { return !m_uFloppyImage.isNull(); } 254 /** Returns the --dvd | --cdrom option value (whether we have DVD image). */ 255 bool hasDvdImageToMount() const { return !m_uDvdImage.isNull(); } 256 /** Returns floppy image name. */ 257 QUuid getFloppyImage() const { return m_uFloppyImage; } 258 /** Returns DVD image name. */ 259 QUuid getDvdImage() const { return m_uDvdImage; } 260 261 /** Returns the --disable-patm option value. */ 262 bool isPatmDisabled() const { return m_fDisablePatm; } 263 /** Returns the --disable-csam option value. */ 264 bool isCsamDisabled() const { return m_fDisableCsam; } 265 /** Returns the --recompile-supervisor option value. */ 266 bool isSupervisorCodeExecedRecompiled() const { return m_fRecompileSupervisor; } 267 /** Returns the --recompile-user option value. */ 268 bool isUserCodeExecedRecompiled() const { return m_fRecompileUser; } 269 /** Returns the --execute-all-in-iem option value. */ 270 bool areWeToExecuteAllInIem() const { return m_fExecuteAllInIem; } 271 /** Returns whether --warp-factor option value is equal to 100. */ 272 bool isDefaultWarpPct() const { return m_uWarpPct == 100; } 273 /** Returns the --warp-factor option value. */ 274 uint32_t getWarpPct() const { return m_uWarpPct; } 275 276 #ifdef VBOX_WITH_DEBUGGER_GUI 277 /** Holds whether the debugger should be accessible. */ 278 bool isDebuggerEnabled() const; 279 /** Holds whether to show the debugger automatically with the console. */ 280 bool isDebuggerAutoShowEnabled() const; 281 /** Holds whether to show the command line window when m_fDbgAutoShow is set. */ 282 bool isDebuggerAutoShowCommandLineEnabled() const; 283 /** Holds whether to show the statistics window when m_fDbgAutoShow is set. */ 284 bool isDebuggerAutoShowStatisticsEnabled() const; 285 /** Returns the combined --statistics-expand values. */ 286 QString const getDebuggerStatisticsExpand() const { return m_strDbgStatisticsExpand; } 287 /** Returns the --statistics-filter value. */ 288 QString const getDebuggerStatisticsFilter() const { return m_strDbgStatisticsFilter; } 289 290 /** VBoxDbg module handle. */ 291 RTLDRMOD getDebuggerModule() const { return m_hVBoxDbg; } 292 #endif 293 294 /** Returns whether VM should start paused. */ 295 bool shouldStartPaused() const; 296 297 #ifdef VBOX_GUI_WITH_PIDFILE 298 /** Creates PID file. */ 299 void createPidfile(); 300 /** Deletes PID file. */ 301 void deletePidfile(); 302 #endif 303 /** @} */ 304 305 /** @name File-system stuff. 306 * @{ */ 307 /** Returns full help file name. */ 308 static QString helpFile(); 309 310 /** Returns documents path. */ 311 static QString documentsPath(); 312 313 /** Returns whether passed @a strFileName ends with one of allowed extension in the @a extensions list. */ 314 static bool hasAllowedExtension(const QString &strFileName, const QStringList &extensions); 315 316 /** Returns a file name (unique up to extension) wrt. @a strFullFolderPath folder content. Starts 317 * searching strBaseFileName and adds suffixes until a unique file name is found. */ 318 static QString findUniqueFileName(const QString &strFullFolderPath, const QString &strBaseFileName); 319 /** @} */ 320 321 /** @name Window/widget stuff. 322 * @{ */ 323 /** Search position for @a rectangle to make sure it is fully contained @a boundRegion. */ 324 static QRect normalizeGeometry(const QRect &rectangle, const QRegion &boundRegion, 325 bool fCanResize = true); 326 /** Ensures that the given rectangle @a rectangle is fully contained within the region @a boundRegion. */ 327 static QRect getNormalized(const QRect &rectangle, const QRegion &boundRegion, 328 bool fCanResize = true); 329 /** Returns the flipped (transposed) @a region. */ 330 static QRegion flip(const QRegion ®ion); 331 332 /** Aligns the center of @a pWidget with the center of @a pRelative. */ 333 static void centerWidget(QWidget *pWidget, QWidget *pRelative, bool fCanResize = true); 334 335 /** Assigns top-level @a pWidget geometry passed as QRect coordinates. 336 * @note Take into account that this request may fail on X11. */ 337 static void setTopLevelGeometry(QWidget *pWidget, int x, int y, int w, int h); 338 /** Assigns top-level @a pWidget geometry passed as @a rect. 339 * @note Take into account that this request may fail on X11. */ 340 static void setTopLevelGeometry(QWidget *pWidget, const QRect &rect); 341 342 /** Activates the specified window with given @a wId. Can @a fSwitchDesktop if requested. */ 343 static bool activateWindow(WId wId, bool fSwitchDesktop = true); 344 345 /** Does some checks on certain platforms before calling QWidget::setCursor(...). */ 346 static void setCursor(QWidget *pWidget, const QCursor &cursor); 347 static void setCursor(QGraphicsWidget *pWidget, const QCursor &cursor); 348 static void unsetCursor(QWidget *pWidget); 349 static void unsetCursor(QGraphicsWidget *pWidget); 350 351 #ifdef VBOX_WS_X11 352 /** X11: Test whether the current window manager supports full screen mode. */ 353 static bool supportsFullScreenMonitorsProtocolX11(); 354 /** X11: Performs mapping of the passed @a pWidget to host-screen with passed @a uScreenId. */ 355 static bool setFullScreenMonitorX11(QWidget *pWidget, ulong uScreenId); 356 357 /** X11: Returns a list of current _NET_WM_STATE flags for passed @a pWidget. */ 358 static QVector<Atom> flagsNetWmState(QWidget *pWidget); 359 /** X11: Check whether _NET_WM_STATE_FULLSCREEN flag is set for passed @a pWidget. */ 360 static bool isFullScreenFlagSet(QWidget *pWidget); 361 /** X11: Sets _NET_WM_STATE_FULLSCREEN flag for passed @a pWidget. */ 362 static void setFullScreenFlag(QWidget *pWidget); 363 /** X11: Sets _NET_WM_STATE_SKIP_TASKBAR flag for passed @a pWidget. */ 364 static void setSkipTaskBarFlag(QWidget *pWidget); 365 /** X11: Sets _NET_WM_STATE_SKIP_PAGER flag for passed @a pWidget. */ 366 static void setSkipPagerFlag(QWidget *pWidget); 367 368 /** Assigns WM_CLASS property for passed @a pWidget. */ 369 static void setWMClass(QWidget *pWidget, const QString &strNameString, const QString &strClassString); 370 /** Tell the WM we are well behaved wrt Xwayland keyboard-grabs. This will 371 * make the WM turn our grab into a Wayland shortcut inhibition request, 372 * so that e.g. alt+tab will get send to the VM instead of moving the 373 * focus away from the VM. */ 374 static void setXwaylandMayGrabKeyboardFlag(QWidget *pWidget); 375 #endif /* VBOX_WS_X11 */ 376 377 /** Assigns minimum @a pSpinBox to correspond to @a cCount digits. */ 378 static void setMinimumWidthAccordingSymbolCount(QSpinBox *pSpinBox, int cCount); 379 /** @} */ 380 381 /** @name COM stuff. 382 * @{ */ 383 /** Try to acquire COM cleanup protection token for reading. */ 384 bool comTokenTryLockForRead() { return m_comCleanupProtectionToken.tryLockForRead(); } 385 /** Unlock previously acquired COM cleanup protection token. */ 386 void comTokenUnlock() { return m_comCleanupProtectionToken.unlock(); } 387 388 /** Returns the copy of VirtualBox client wrapper. */ 389 CVirtualBoxClient virtualBoxClient() const { return m_comVBoxClient; } 390 /** Returns the copy of VirtualBox object wrapper. */ 391 CVirtualBox virtualBox() const { return m_comVBox; } 392 /** Returns the copy of VirtualBox host-object wrapper. */ 393 CHost host() const { return m_comHost; } 394 /** Returns the symbolic VirtualBox home-folder representation. */ 395 QString homeFolder() const { return m_strHomeFolder; } 396 397 /** Returns the VBoxSVC availability value. */ 398 bool isVBoxSVCAvailable() const { return m_fVBoxSVCAvailable; } 399 /** @} */ 400 401 /** @name COM: Guest OS Type. 402 * @{ */ 403 /** Returns the list of family IDs. */ 404 QList<QString> vmGuestOSFamilyIDs() const { return m_guestOSFamilyIDs; } 405 406 /** Returns a family description with passed @a strFamilyId. */ 407 QString vmGuestOSFamilyDescription(const QString &strFamilyId) const; 408 /** Returns a list of all guest OS types with passed @a strFamilyId. */ 409 QList<CGuestOSType> vmGuestOSTypeList(const QString &strFamilyId) const; 410 411 /** Returns the guest OS type for passed @a strTypeId. 412 * It is being serached through the list of family with passed @a strFamilyId if specified. */ 413 CGuestOSType vmGuestOSType(const QString &strTypeId, const QString &strFamilyId = QString()) const; 414 /** Returns a type description with passed @a strTypeId. */ 415 QString vmGuestOSTypeDescription(const QString &strTypeId) const; 416 417 /** Returns whether guest type with passed @a strOSTypeId is one of DOS types. */ 418 static bool isDOSType(const QString &strOSTypeId); 419 /** @} */ 420 421 /** @name COM: Virtual Machine stuff. 422 * @{ */ 423 /** Switches to certain @a comMachine. */ 424 static bool switchToMachine(CMachine &comMachine); 425 /** Launches certain @a comMachine in specified @a enmLaunchMode. */ 426 bool launchMachine(CMachine &comMachine, LaunchMode enmLaunchMode = LaunchMode_Default); 427 428 /** Opens session of certain @a enmLockType for VM with certain @a uId. */ 429 CSession openSession(const QUuid &uId, KLockType enmLockType = KLockType_Write); 430 /** Opens session of KLockType_Shared type for VM with certain @a uId. */ 431 CSession openExistingSession(const QUuid &uId) { return openSession(uId, KLockType_Shared); } 432 /** Tries to guess if new @a comSession needs to be opened for certain @a comMachine, 433 * if yes, new session of required type will be opened and machine will be updated, 434 * otherwise, no session will be created and machine will be left unchanged. */ 435 CSession tryToOpenSessionFor(CMachine &comMachine); 436 /** @} */ 437 438 /** @name Cloud Virtual Machine stuff. 439 * @{ */ 440 /** Notifies listeners about cloud VM was unregistered. 441 * @param strProviderShortName Brings provider short name. 442 * @param strProfileName Brings profile name. 443 * @param uId Brings cloud VM id. */ 444 void notifyCloudMachineUnregistered(const QString &strProviderShortName, 445 const QString &strProfileName, 446 const QUuid &uId); 447 /** Notifies listeners about cloud VM was registered. 448 * @param strProviderShortName Brings provider short name. 449 * @param strProfileName Brings profile name. 450 * @param comMachine Brings cloud VM. */ 451 void notifyCloudMachineRegistered(const QString &strProviderShortName, 452 const QString &strProfileName, 453 const CCloudMachine &comMachine); 454 /** @} */ 455 456 /** @name COM: Virtual Media stuff. 457 * @{ */ 458 /** Enumerates passed @a comMedia. */ 459 void enumerateMedia(const CMediumVector &comMedia = CMediumVector()); 460 /** Calls refresh for each medium which has been already enumerated. */ 461 void refreshMedia(); 462 /** Returns whether full medium-enumeration is requested. */ 463 bool isFullMediumEnumerationRequested() const; 464 /** Returns whether any medium-enumeration is in progress. */ 465 bool isMediumEnumerationInProgress() const; 466 /** Returns enumerated medium with certain @a uMediumID. */ 467 UIMedium medium(const QUuid &uMediumID) const; 468 /** Returns enumerated medium IDs. */ 469 QList<QUuid> mediumIDs() const; 470 /** Creates medium on the basis of passed @a guiMedium description. */ 471 void createMedium(const UIMedium &guiMedium); 472 473 /** Opens external medium by passed @a strMediumLocation. 474 * @param enmMediumType Brings the medium type. 475 * @param pParent Brings the dialog parent. 476 * @param strMediumLocation Brings the file path to load medium from. 477 * @param pParent Brings the dialog parent. */ 478 QUuid openMedium(UIMediumDeviceType enmMediumType, QString strMediumLocation, QWidget *pParent = 0); 479 480 /** Opens external medium using file-open dialog. 481 * @param enmMediumType Brings the medium type. 482 * @param pParent Brings the dialog parent. 483 * @param strDefaultFolder Brings the folder to browse for medium. 484 * @param fUseLastFolder Brings whether we should propose to use last used folder. */ 485 QUuid openMediumWithFileOpenDialog(UIMediumDeviceType enmMediumType, QWidget *pParent = 0, 486 const QString &strDefaultFolder = QString(), bool fUseLastFolder = false); 487 488 489 /** Creates and shows a UIMediumSelector dialog. 490 * @param parent Passes the parent of the dialog, 491 * @param enmMediumType Passes the medium type. 492 * @param strMachineName Passes the name of the machine, 493 * @param strMachineFolder Passes the machine folder, 494 * @param strMachineGuestOSTypeId Passes the type ID of machine's guest os, 495 * @param fEnableCreate Passes whether to show/enable create action in the medium selector dialog, 496 * @param uMachineID Passes the machine UUID, 497 * returns the return code of the UIMediumSelector::ReturnCode as int. In case of a medium selection 498 * UUID of the selected medium is stored in @param outUuid.*/ 499 int openMediumSelectorDialog(QWidget *pParent, UIMediumDeviceType enmMediumType, QUuid &outUuid, 500 const QString &strMachineFolder, const QString &strMachineName, 501 const QString &strMachineGuestOSTypeId, bool fEnableCreate, const QUuid &uMachineID = QUuid()); 502 503 /** Creates and shows a dialog (wizard) to create a medium of type @a enmMediumType. 504 * @param pParent Passes the parent of the dialog, 505 * @param enmMediumType Passes the medium type, 506 * @param strMachineName Passes the name of the machine, 507 * @param strMachineFolder Passes the machine folder, 508 * @param strMachineGuestOSTypeId Passes the type ID of machine's guest os, 509 * @param fEnableCreate Passes whether to show/enable create action in the medium selector dialog. */ 510 void openMediumCreatorDialog(QWidget *pParent, UIMediumDeviceType enmMediumType, 511 const QString &strMachineFolder = QString(), 512 const QString &strMachineName = QString(), 513 const QString &strMachineGuestOSTypeId = QString()); 514 515 /** Prepares storage menu according passed parameters. 516 * @param menu Brings the #QMenu to be prepared. 517 * @param pListener Brings the listener #QObject, this @a menu being prepared for. 518 * @param pszSlotName Brings the name of the SLOT in the @a pListener above, this menu will be handled with. 519 * @param comMachine Brings the #CMachine object, this @a menu being prepared for. 520 * @param strControllerName Brings the name of the #CStorageController in the @a machine above. 521 * @param storageSlot Brings the #StorageSlot of the storage controller with @a strControllerName above. */ 522 void prepareStorageMenu(QMenu &menu, 523 QObject *pListener, const char *pszSlotName, 524 const CMachine &comMachine, const QString &strControllerName, const StorageSlot &storageSlot); 525 /** Updates @a comConstMachine storage with data described by @a target. */ 526 void updateMachineStorage(const CMachine &comConstMachine, const UIMediumTarget &target); 527 528 /** Generates details for passed @a comMedium. 529 * @param fPredictDiff Brings whether medium will be marked differencing on attaching. 530 * @param fUseHtml Brings whether HTML subsets should be used in the generated output. */ 531 QString details(const CMedium &comMedium, bool fPredictDiff, bool fUseHtml = true); 532 533 /** Update extra data related to recently used/referred media. 534 * @param enmMediumType Passes the medium type. 535 * @param strMediumLocation Passes the medium location. */ 536 void updateRecentlyUsedMediumListAndFolder(UIMediumDeviceType enmMediumType, QString strMediumLocation); 537 538 /** Searches extra data for the recently used folder path which corresponds to @a enmMediumType. When that search fails 539 it looks for recent folder extra data for other medium types. As the last resort returns default vm folder path. 540 * @param enmMediumType Passes the medium type. */ 541 QString defaultFolderPathForType(UIMediumDeviceType enmMediumType); 542 /** @} */ 543 544 /** @name COM: USB stuff. 545 * @{ */ 546 #ifdef RT_OS_LINUX 547 /** Verifies that USB drivers are properly configured on Linux. */ 548 static void checkForWrongUSBMounted(); 549 #endif 550 551 /** Generates details for passed USB @a comDevice. */ 552 static QString details(const CUSBDevice &comDevice); 553 /** Generates tool-tip for passed USB @a comDevice. */ 554 static QString toolTip(const CUSBDevice &comDevice); 555 /** Generates tool-tip for passed USB @a comFilter. */ 556 static QString toolTip(const CUSBDeviceFilter &comFilter); 557 /** Generates tool-tip for passed USB @a comWebcam. */ 558 static QString toolTip(const CHostVideoInputDevice &comWebcam); 559 /** @} */ 560 561 /** @name COM: Extension Pack stuff. 562 * @{ */ 563 /** Initiates the extension pack installation process. 564 * @param strFilePath Brings the extension pack file path. 565 * @param strDigest Brings the extension pack file digest. 566 * @param pParent Brings the parent dialog reference. 567 * @param pstrExtPackName Brings the extension pack name. */ 568 void doExtPackInstallation(QString const &strFilePath, 569 QString const &strDigest, 570 QWidget *pParent, 571 QString *pstrExtPackName) const; 572 /** @} */ 573 574 /** @name Display stuff. 575 * @{ */ 576 #ifdef VBOX_WITH_3D_ACCELERATION 577 /** Returns whether guest OS type with passed @a strGuestOSTypeId is WDDM compatible. */ 578 static bool isWddmCompatibleOsType(const QString &strGuestOSTypeId); 579 #endif 580 /** Returns the required video memory in bytes for the current desktop 581 * resolution at maximum possible screen depth in bpp. */ 582 static quint64 requiredVideoMemory(const QString &strGuestOSTypeId, int cMonitors = 1); 583 /** @} */ 584 585 /** @name Thread stuff. 586 * @{ */ 587 /** Returns the thread-pool instance. */ 588 UIThreadPool *threadPool() const { return m_pThreadPool; } 589 /** Returns the thread-pool instance for cloud needs. */ 590 UIThreadPool *threadPoolCloud() const { return m_pThreadPoolCloud; } 591 /** @} */ 592 593 /** @name Icon/Pixmap stuff. 594 * @{ */ 595 /** Returns icon defined for a passed @a comMachine. */ 596 QIcon vmUserIcon(const CMachine &comMachine) const; 597 /** Returns pixmap of a passed @a size defined for a passed @a comMachine. */ 598 QPixmap vmUserPixmap(const CMachine &comMachine, const QSize &size) const; 599 /** Returns pixmap defined for a passed @a comMachine. 600 * In case if non-null @a pLogicalSize pointer provided, it will be updated properly. */ 601 QPixmap vmUserPixmapDefault(const CMachine &comMachine, QSize *pLogicalSize = 0) const; 602 603 /** Returns pixmap corresponding to passed @a strOSTypeID. */ 604 QIcon vmGuestOSTypeIcon(const QString &strOSTypeID) const; 605 /** Returns pixmap corresponding to passed @a strOSTypeID and @a size. */ 606 QPixmap vmGuestOSTypePixmap(const QString &strOSTypeID, const QSize &size) const; 607 /** Returns pixmap corresponding to passed @a strOSTypeID. 608 * In case if non-null @a pLogicalSize pointer provided, it will be updated properly. */ 609 QPixmap vmGuestOSTypePixmapDefault(const QString &strOSTypeID, QSize *pLogicalSize = 0) const; 610 611 /** Returns default icon of certain @a enmType. */ 612 QIcon icon(QFileIconProvider::IconType enmType) { return m_fileIconProvider.icon(enmType); } 613 /** Returns file icon fetched from passed file @a info. */ 614 QIcon icon(const QFileInfo &info) { return m_fileIconProvider.icon(info); } 615 616 /** Returns cached default warning pixmap. */ 617 QPixmap warningIcon() const { return m_pixWarning; } 618 /** Returns cached default error pixmap. */ 619 QPixmap errorIcon() const { return m_pixError; } 620 621 /** Joins two pixmaps horizontally with 2px space between them and returns the result. */ 622 static QPixmap joinPixmaps(const QPixmap &pixmap1, const QPixmap &pixmap2); 623 /** @} */ 624 625 /** @name Context sensitive help related functionality 626 * @{ */ 627 /** Sets the property for help keyword on a QObject 628 * @param pObject The object to set the help keyword property on 629 * @param strKeyword The values of the key word property. */ 630 static void setHelpKeyword(QObject *pObject, const QString &strHelpKeyword); 631 /** Returns the property for help keyword of a QObject. If no such property exists returns an empty QString. 632 * @param pWidget The object to get the help keyword property from. */ 633 static QString helpKeyword(const QObject *pWidget); 634 /** @} */ 635 636 public slots: 637 638 /** @name Process arguments stuff. 639 * @{ */ 640 /** Opens the specified URL using OS/Desktop capabilities. */ 641 bool openURL(const QString &strURL) const; 642 /** @} */ 643 644 /** @name Localization stuff. 645 * @{ */ 646 /** Handles language change to new @a strLanguage. */ 647 void sltGUILanguageChange(QString strLanguage); 648 /** @} */ 649 650 /** @name Media related stuff. 651 * @{ */ 652 /** Handles signal about medium was created. */ 653 void sltHandleMediumCreated(const CMedium &comMedium); 654 /** @} */ 655 656 /** @name Machine related stuff. 657 * @{ */ 658 /** Handles signal about machine was created. */ 659 void sltHandleMachineCreated(const CMachine &comMachine); 660 /** @} */ 661 662 /** @name Cloud Machine related stuff. 663 * @{ */ 664 /** Handles signal about cloud machine was added. */ 665 void sltHandleCloudMachineAdded(const QString &strProviderShortName, 666 const QString &strProfileName, 667 const CCloudMachine &comMachine); 668 /** @} */ 669 670 protected: 671 672 /** Preprocesses any Qt @a pEvent for passed @a pObject. */ 673 virtual bool eventFilter(QObject *pObject, QEvent *pEvent) /* override */; 674 675 /** Handles translation event. */ 676 virtual void retranslateUi() /* override */; 677 678 protected slots: 679 680 /** Calls for cleanup() functionality. */ 681 void sltCleanup() { cleanup(); } 682 683 #ifndef VBOX_GUI_WITH_CUSTOMIZATIONS1 684 /** @name Common stuff. 685 * @{ */ 686 /** Handles @a manager request for emergency session shutdown. */ 687 void sltHandleCommitDataRequest(QSessionManager &manager); 688 /** @} */ 689 #endif /* VBOX_GUI_WITH_CUSTOMIZATIONS1 */ 690 691 /** @name COM stuff. 692 * @{ */ 693 /** Handles the VBoxSVC availability change. */ 694 void sltHandleVBoxSVCAvailabilityChange(bool fAvailable); 695 /** @} */ 696 697 private: 698 699 /** Construcs global VirtualBox object of passed @a enmType. */ 700 UICommon(UIType enmType); 701 /** Destrucs global VirtualBox object. */ 702 virtual ~UICommon() /* override final */; 703 704 /** Prepares all. */ 705 void prepare(); 706 /** Cleanups all. */ 707 void cleanup(); 708 709 /** @name COM: Virtual Media create functions. 710 * @{ */ 711 712 /** Creates a VISO by using the VISO creator dialog. 713 * @param pParent Passes the dialog parent. 714 * @param strDefaultFolder Passes the folder to save the VISO file. 715 * @param strMachineName Passes the name of the machine, */ 716 QUuid createVisoMediumWithVisoCreator(QWidget *pParent, const QString &strDefaultFolder = QString(), const QString &strMachineName = QString()); 717 718 /** Creates and shows a dialog thru which user can create a new floppy disk a VISO using the file-open dialog. 719 * @param parent Passes the parent of the dialog, 720 * @param strDefaultFolder Passes the default folder, 721 * @param strMachineName Passes the name of the machine, 722 * returns the ID of the newly created medium if successful, a null QUuid otherwise.*/ 723 QUuid showCreateFloppyDiskDialog(QWidget *pParent, const QString &strDefaultFolder = QString(), 724 const QString &strMachineName = QString()); 725 726 /** Creates and shows a UIWizardNewVD wizard. 727 * @param pParent Passes the parent of the wizard, 728 * @param strMachineFolder Passes the machine folder, 729 * @param strMachineName Passes the name of the machine, 730 * @param strMachineGuestOSTypeId Passes the string of machine's guest OS type ID. */ 731 void createVDWithWizard(QWidget *pParent, 732 const QString &strMachineFolder = QString(), 733 const QString &strMachineName = QString(), 734 const QString &strMachineGuestOSTypeId = QString()); 735 /** @} */ 736 737 /** @name Common stuff. 738 * @{ */ 739 #ifdef VBOX_WS_WIN 740 /** Wraps WinAPI ShutdownBlockReasonCreate function. */ 741 static BOOL ShutdownBlockReasonCreateAPI(HWND hWnd, LPCWSTR pwszReason); 742 #endif 743 /** @} */ 744 745 /** @name Process arguments stuff. 746 * @{ */ 747 #ifdef VBOX_WITH_DEBUGGER_GUI 748 /** Initializes a debugger config variable. 749 * @param piDbgCfgVar Brings the debugger config variable to init. 750 * @param pszEnvVar Brings the environment variable name relating to this variable. 751 * @param pszExtraDataName Brings the extra data name relating to this variable. 752 * @param fDefault Brings the default value. */ 753 void initDebuggerVar(int *piDbgCfgVar, const char *pszEnvVar, const char *pszExtraDataName, bool fDefault = false); 754 /** Set a debugger config variable according according to start up argument. 755 * @param piDbgCfgVar Brings the debugger config variable to set. 756 * @param fState Brings the value from the command line. */ 757 void setDebuggerVar(int *piDbgCfgVar, bool fState); 758 /** Checks the state of a debugger config variable, updating it with the machine settings on the first invocation. 759 * @param piDbgCfgVar Brings the debugger config variable to consult. 760 * @param pszExtraDataName Brings the extra data name relating to this variable. */ 761 bool isDebuggerWorker(int *piDbgCfgVar, const char *pszExtraDataName) const; 762 #endif 763 /** @} */ 764 765 /** @name COM stuff. 766 * @{ */ 767 /** Re-initializes COM wrappers and containers. */ 768 void comWrappersReinit(); 769 /** @} */ 770 771 /** Holds the singleton UICommon instance. */ 772 static UICommon *s_pInstance; 773 774 /** @name General stuff. 775 * @{ */ 776 /** Holds the UI type. */ 777 UIType m_enmType; 778 779 /** Holds whether UICommon instance is properly initialized. */ 780 bool m_fValid; 781 /** Holds whether UICommon instance cleanup is in progress. */ 782 bool m_fCleaningUp; 783 #ifdef VBOX_WS_WIN 784 /** Holds whether overall GUI data is committed. */ 785 bool m_fDataCommitted; 786 #endif 787 /** @} */ 788 789 /** @name Versioning stuff. 790 * @{ */ 791 /** Holds the VBox branding config file path. */ 792 QString m_strBrandingConfigFilePath; 793 /** @} */ 794 795 /** @name Host OS stuff. 796 * @{ */ 797 #ifdef VBOX_WS_MAC 798 /** Mac OS X: Holds the #MacOSXRelease determined using <i>uname</i> call. */ 799 MacOSXRelease m_enmMacOSVersion; 800 #endif 801 802 #ifdef VBOX_WS_X11 803 /** X11: Holds the #X11WMType of the Window Manager we are running under. */ 804 X11WMType m_enmWindowManagerType; 805 /** X11: Holds whether the Window Manager we are running at is composition one. */ 806 bool m_fCompositingManagerRunning; 807 #endif 808 /** @} */ 809 810 /** @name Process arguments stuff. 811 * @{ */ 812 /** Holds the URL arguments list. */ 813 QList<QUrl> m_listArgUrls; 814 815 /** Holds the --startvm option value (managed VM id). */ 816 QUuid m_strManagedVMId; 817 /** Holds the --separate option value (whether GUI process is separate from VM process). */ 818 bool m_fSeparateProcess; 819 /** Holds the --no-startvm-errormsgbox option value (whether startup VM errors are disabled). */ 820 bool m_fShowStartVMErrors; 821 822 /** Holds the --aggressive-caching / --no-aggressive-caching option value (whether medium-enumeration is required). */ 823 bool m_fAgressiveCaching; 824 825 /** Holds the --restore-current option value. */ 826 bool m_fRestoreCurrentSnapshot; 827 828 /** Holds the --fda option value (floppy image). */ 829 QUuid m_uFloppyImage; 830 /** Holds the --dvd | --cdrom option value (DVD image). */ 831 QUuid m_uDvdImage; 832 833 /** Holds the --disable-patm option value. */ 834 bool m_fDisablePatm; 835 /** Holds the --disable-csam option value. */ 836 bool m_fDisableCsam; 837 /** Holds the --recompile-supervisor option value. */ 838 bool m_fRecompileSupervisor; 839 /** Holds the --recompile-user option value. */ 840 bool m_fRecompileUser; 841 /** Holds the --execute-all-in-iem option value. */ 842 bool m_fExecuteAllInIem; 843 /** Holds the --warp-factor option value. */ 844 uint32_t m_uWarpPct; 845 846 #ifdef VBOX_WITH_DEBUGGER_GUI 847 /** Holds whether the debugger should be accessible. */ 848 mutable int m_fDbgEnabled; 849 /** Holds whether to show the debugger automatically with the console. */ 850 mutable int m_fDbgAutoShow; 851 /** Holds whether to show the command line window when m_fDbgAutoShow is set. */ 852 mutable int m_fDbgAutoShowCommandLine; 853 /** Holds whether to show the statistics window when m_fDbgAutoShow is set. */ 854 mutable int m_fDbgAutoShowStatistics; 855 /** Pattern of statistics to expand when opening the viewer. */ 856 QString m_strDbgStatisticsExpand; 857 /** The statistics viewer filter. */ 858 QString m_strDbgStatisticsFilter; 859 860 /** VBoxDbg module handle. */ 861 RTLDRMOD m_hVBoxDbg; 862 863 /** Holds whether --start-running, --start-paused or nothing was given. */ 864 LaunchRunning m_enmLaunchRunning; 865 #endif 866 867 /** Holds the --settingspw option value or the content of --settingspwfile. */ 868 char m_astrSettingsPw[256]; 869 /** Holds the --settingspwfile option value. */ 870 bool m_fSettingsPwSet; 871 872 #ifdef VBOX_GUI_WITH_PIDFILE 873 /** Holds the --pidfile option value (application PID file path). */ 874 QString m_strPidFile; 875 #endif 876 /** @} */ 877 878 /** @name COM stuff. 879 * @{ */ 880 /** Holds the COM cleanup protection token. */ 881 QReadWriteLock m_comCleanupProtectionToken; 882 883 /** Holds the instance of VirtualBox client wrapper. */ 884 CVirtualBoxClient m_comVBoxClient; 885 /** Holds the copy of VirtualBox object wrapper. */ 886 CVirtualBox m_comVBox; 887 /** Holds the copy of VirtualBox host-object wrapper. */ 888 CHost m_comHost; 889 /** Holds the symbolic VirtualBox home-folder representation. */ 890 QString m_strHomeFolder; 891 892 /** Holds whether acquired COM wrappers are currently valid. */ 893 bool m_fWrappersValid; 894 /** Holds whether VBoxSVC is currently available. */ 895 bool m_fVBoxSVCAvailable; 896 897 /** Holds the guest OS family IDs. */ 898 QList<QString> m_guestOSFamilyIDs; 899 /** Holds the guest OS family descriptions. */ 900 QMap<QString, QString> m_guestOSFamilyDescriptions; 901 /** Holds the guest OS types for each family ID. */ 902 QList<QList<CGuestOSType> > m_guestOSTypes; 903 /** @} */ 904 905 /** @name Thread stuff. 906 * @{ */ 907 /** Holds the thread-pool instance. */ 908 UIThreadPool *m_pThreadPool; 909 /** Holds the thread-pool instance for cloud needs. */ 910 UIThreadPool *m_pThreadPoolCloud; 911 /** @} */ 912 913 /** @name Icon/Pixmap stuff. 914 * @{ */ 915 /** Holds the general icon-pool instance. */ 916 UIIconPoolGeneral *m_pIconPool; 917 918 /** Holds the global file icon provider instance. */ 919 QFileIconProvider m_fileIconProvider; 920 921 /** Holds the warning pixmap. */ 922 QPixmap m_pixWarning; 923 /** Holds the error pixmap. */ 924 QPixmap m_pixError; 925 /** @} */ 926 927 /** @name Media related stuff. 928 * @{ */ 929 /** Holds the medium enumerator cleanup protection token. */ 930 mutable QReadWriteLock m_meCleanupProtectionToken; 931 932 /** Holds the medium enumerator. */ 933 UIMediumEnumerator *m_pMediumEnumerator; 934 /** List of medium names that should not appears in the recently used media extra data. */ 935 QStringList m_recentMediaExcludeList; 936 /** @} */ 937 938 #if defined(VBOX_WS_WIN) 939 /** @name ATL stuff. 940 * @{ */ 941 /** Holds the ATL module instance (for use with UICommon shared library only). 942 * @note Required internally by ATL (constructor records instance in global variable). */ 943 ATL::CComModule _Module; 944 /** @} */ 945 #endif 946 947 /** Allows for shortcut access. */ 948 friend UICommon &uiCommon(); 949 }; 950 951 /** Singleton UICommon 'official' name. */ 952 inline UICommon &uiCommon() { return *UICommon::instance(); } 953 954 #endif /* !FEQT_INCLUDED_SRC_globals_UICommon_h */ 44 #endif /* !FEQT_INCLUDED_SRC_globals_UICursor_h */ -
trunk/src/VBox/Frontends/VirtualBox/src/helpbrowser/UIHelpViewer.cpp
r90872 r91003 42 42 /* GUI includes: */ 43 43 #include "QIToolButton.h" 44 #include "UICursor.h" 44 45 #include "UIHelpViewer.h" 45 46 #include "UIHelpBrowserWidget.h" … … 239 240 { 240 241 if (pEvent->type() == QEvent::Enter) 241 m_pDragMoveLabel->setCursor(Qt::CrossCursor);242 UICursor::setCursor(m_pDragMoveLabel, Qt::CrossCursor); 242 243 else if (pEvent->type() == QEvent::Leave) 243 244 { 244 245 if (parentWidget()) 245 m_pDragMoveLabel->setCursor(parentWidget()->cursor());246 UICursor::setCursor(m_pDragMoveLabel, parentWidget()->cursor()); 246 247 } 247 248 else if (pEvent->type() == QEvent::MouseMove) … … 253 254 emit sigDragging(pMouseEvent->globalPos() - m_previousMousePosition); 254 255 m_previousMousePosition = pMouseEvent->globalPos(); 255 m_pDragMoveLabel->setCursor(Qt::ClosedHandCursor);256 UICursor::setCursor(m_pDragMoveLabel, Qt::ClosedHandCursor); 256 257 } 257 258 } … … 259 260 { 260 261 m_previousMousePosition = QPoint(-1, -1); 261 m_pDragMoveLabel->setCursor(Qt::CrossCursor);262 UICursor::setCursor(m_pDragMoveLabel, Qt::CrossCursor); 262 263 } 263 264 } … … 667 668 { 668 669 m_fCursorChanged = true; 669 viewport()->setCursor(m_handCursor);670 UICursor::setCursor(viewport(), m_handCursor); 670 671 emit sigMouseOverImage(cursor.charFormat().toImageFormat().name()); 671 672 } 672 673 if (m_fCursorChanged && !cursor.charFormat().isImageFormat()) 673 674 { 674 viewport()->setCursor(m_defaultCursor);675 UICursor::setCursor(viewport(), m_defaultCursor); 675 676 m_fCursorChanged = false; 676 677 } … … 988 989 if (m_pOverlayBlurEffect) 989 990 m_pOverlayBlurEffect->setEnabled(true); 990 viewport()->setCursor(m_defaultCursor);991 UICursor::setCursor(viewport(), m_defaultCursor); 991 992 m_fCursorChanged = false; 992 993 toggleFindInPageWidget(false); -
trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElement.cpp
r90758 r91003 35 35 #include "UICloudMachineSettingsDialogPage.h" 36 36 #include "UICloudNetworkingStuff.h" 37 #include "UICommon.h"38 37 #include "UIConverter.h" 38 #include "UICursor.h" 39 39 #include "UIDetailsElement.h" 40 40 #include "UIDetailsGenerator.h" … … 842 842 { 843 843 if (m_fNameHovered) 844 UIC ommon::setCursor(this, Qt::PointingHandCursor);844 UICursor::setCursor(this, Qt::PointingHandCursor); 845 845 else 846 UIC ommon::unsetCursor(this);846 UICursor::unsetCursor(this); 847 847 update(); 848 848 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
r90701 r91003 25 25 26 26 /* GUI includes: */ 27 #include "UIC ommon.h"27 #include "UICursor.h" 28 28 #include "UIDesktopWidgetWatchdog.h" 29 29 #include "UIExtraDataManager.h" … … 462 462 QList<ulong> screenIds = m_viewports.keys(); 463 463 for (int i = 0; i < screenIds.size(); ++i) 464 UIC ommon::setCursor(m_viewports[screenIds[i]], Qt::BlankCursor);464 UICursor::setCursor(m_viewports[screenIds[i]], Qt::BlankCursor); 465 465 } 466 466 … … 476 476 QList<ulong> screenIds = m_viewports.keys(); 477 477 for (int i = 0; i < screenIds.size(); ++i) 478 UIC ommon::setCursor(m_viewports[screenIds[i]], m_views[screenIds[i]]->cursor());478 UICursor::setCursor(m_viewports[screenIds[i]], m_views[screenIds[i]]->cursor()); 479 479 } 480 480 … … 489 489 QList<ulong> screenIds = m_viewports.keys(); 490 490 for (int i = 0; i < screenIds.size(); ++i) 491 UIC ommon::unsetCursor(m_viewports[screenIds[i]]);491 UICursor::unsetCursor(m_viewports[screenIds[i]]); 492 492 } 493 493 } -
trunk/src/VBox/Frontends/VirtualBox/src/snapshots/UISnapshotDetailsWidget.cpp
r90967 r91003 36 36 #include "UICommon.h" 37 37 #include "UIConverter.h" 38 #include "UICursor.h" 38 39 #include "UIDesktopWidgetWatchdog.h" 39 40 #include "UIIconPool.h" … … 463 464 setWindowModality(Qt::ApplicationModal); 464 465 /* With the pointing-hand cursor: */ 465 UIC ommon::setCursor(this, Qt::PointingHandCursor);466 UICursor::setCursor(this, Qt::PointingHandCursor); 466 467 /* And it's being deleted when closed: */ 467 468 setAttribute(Qt::WA_DeleteOnClose); -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.cpp
r87718 r91003 26 26 /* GUI includes: */ 27 27 #include "UICommon.h" 28 #include "UICursor.h" 28 29 #include "UIPopupStack.h" 29 30 #include "UIPopupStackViewport.h" … … 247 248 { 248 249 /* Configure scroll-area: */ 249 UIC ommon::setCursor(m_pScrollArea, Qt::ArrowCursor);250 UICursor::setCursor(m_pScrollArea, Qt::ArrowCursor); 250 251 m_pScrollArea->setWidgetResizable(true); 251 252 m_pScrollArea->setFrameStyle(QFrame::NoFrame | QFrame::Plain); … … 259 260 { 260 261 /* Configure scroll-viewport: */ 261 UIC ommon::setCursor(m_pScrollViewport, Qt::ArrowCursor);262 UICursor::setCursor(m_pScrollViewport, Qt::ArrowCursor); 262 263 /* Connect scroll-viewport: */ 263 264 connect(this, &UIPopupStack::sigProposeStackViewportSize, -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.cpp
r88445 r91003 25 25 26 26 /* GUI includes: */ 27 #include "UICursor.h" 27 28 #include "UIGraphicsTextPane.h" 28 29 #include "UIRichTextString.h" 29 #include "UICommon.h"30 30 31 31 /* Other VBox includes: */ … … 383 383 /* Update mouse-cursor: */ 384 384 if (m_strHoveredAnchor.isNull()) 385 UIC ommon::unsetCursor(this);385 UICursor::unsetCursor(this); 386 386 else 387 UIC ommon::setCursor(this, Qt::PointingHandCursor);387 UICursor::setCursor(this, Qt::PointingHandCursor); 388 388 389 389 /* Update text-layout: */ -
trunk/src/VBox/Frontends/VirtualBox/src/wizards/editors/UIUserNamePasswordEditor.cpp
r90642 r91003 27 27 #include "QIRichTextLabel.h" 28 28 #include "QIToolButton.h" 29 #include "UIC ommon.h"29 #include "UICursor.h" 30 30 #include "UIIconPool.h" 31 31 #include "UIUserNamePasswordEditor.h" … … 148 148 m_pTextVisibilityButton->setIconSize(QSize(10, 10)); 149 149 m_pTextVisibilityButton->setFocusPolicy(Qt::ClickFocus); 150 m_pTextVisibilityButton->setCursor(Qt::ArrowCursor);150 UICursor::setCursor(m_pTextVisibilityButton, Qt::ArrowCursor); 151 151 m_pTextVisibilityButton->show(); 152 152 connect(m_pTextVisibilityButton, &QToolButton::clicked, this, &UIPasswordLineEdit::sltHandleTextVisibilityChange);
Note:
See TracChangeset
for help on using the changeset viewer.