Changeset 35940 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Feb 11, 2011 11:58:32 AM (14 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 4 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r35808 r35940 574 574 VirtualBox_SOURCES.win += \ 575 575 src/platform/win/VirtualBox.rc \ 576 src/platform/win/UIDesktopServices_win.cpp 576 src/platform/win/UIDesktopServices_win.cpp \ 577 src/platform/win/VBoxUtils-win.cpp 577 578 578 579 VirtualBox_DEFS.darwin += VBOX_DARWIN_USE_NATIVE_CONTROLS -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
r35906 r35940 843 843 return result; 844 844 } 845 846 #ifdef Q_WS_WIN847 /* Enumerate visible top-most windows: */848 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM /* lParam */)849 {850 /* Ignore NULL HWNDs: */851 if (!hWnd)852 return TRUE;853 854 /* Ignore hidden windows: */855 if (!IsWindowVisible(hWnd))856 return TRUE;857 858 /* Get window style: */859 LONG uStyle = GetWindowLong(hWnd, GWL_STYLE);860 /* Ignore minimized windows: */861 if (uStyle & WS_MINIMIZE)862 return TRUE;863 864 /* Get extended window style: */865 LONG uExtendedStyle = GetWindowLong(hWnd, GWL_EXSTYLE);866 /* Ignore non-top-most windows: */867 if (!(uExtendedStyle & WS_EX_TOPMOST))868 return TRUE;869 870 /* Get that window rectangle: */871 RECT rect;872 GetWindowRect(hWnd, &rect);873 VBoxGlobal::m_sTopMostRects << QRect(QPoint(rect.left, rect.top), QPoint(rect.right - 1, rect.bottom - 1));874 875 /* Proceed to the next window: */876 return TRUE;877 }878 879 /* static */880 QList<QRect> VBoxGlobal::m_sTopMostRects = QList<QRect>();881 882 /* static */883 const QRegion VBoxGlobal::areaCoveredByTopMostWindows()884 {885 /* Prepare the top-most region: */886 QRegion topMostRegion;887 /* Initialize the list of the top-most rectangles: */888 m_sTopMostRects.clear();889 /* Populate the list of top-most rectangles: */890 EnumWindows((WNDENUMPROC)EnumWindowsProc, 0);891 /* Update the top-most region with top-most rectangles: */892 for (int iRectIndex = 0; iRectIndex < m_sTopMostRects.size(); ++iRectIndex)893 topMostRegion += m_sTopMostRects[iRectIndex];894 /* Return top-most region: */895 return topMostRegion;896 }897 #endif /* Q_WS_WIN */898 845 899 846 /** -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h
r35906 r35940 178 178 const QRect availableGeometry(int iScreen = 0) const; 179 179 180 #ifdef Q_WS_WIN181 static QList<QRect> m_sTopMostRects;182 static const QRegion areaCoveredByTopMostWindows();183 #endif /* Q_WS_WIN */184 185 180 #ifdef VBOX_WITH_DEBUGGER_GUI 186 181 bool isDebuggerEnabled(CMachine &aMachine); -
trunk/src/VBox/Frontends/VirtualBox/src/platform/win/VBoxUtils-win.cpp
r35939 r35940 3 3 * 4 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * VBoxGlobal class implementation5 * Utility classes and functions for handling Win specific tasks 6 6 */ 7 7 8 8 /* 9 * Copyright (C) 20 06-2010Oracle Corporation9 * Copyright (C) 2010-2011 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 18 18 */ 19 19 20 #include "VBoxGlobal.h" 21 #include <VBox/vd.h> 22 #include <VBox/version.h> 20 /* Includes: */ 21 #include "VBoxUtils-win.h" 23 22 24 #include "VBoxDefs.h" 25 #include "VBoxSelectorWnd.h" 26 #include "VBoxProblemReporter.h" 27 #include "QIMessageBox.h" 28 #include "QIDialogButtonBox.h" 29 #include "UIIconPool.h" 30 #include "UIExtraDataEventHandler.h" 31 #include "QIFileDialog.h" 32 33 #include "UIMachine.h" 34 #include "UISession.h" 35 #ifdef VBOX_WITH_REGISTRATION 36 # include "UIRegistrationWzd.h" 37 #endif 38 #include "VBoxUpdateDlg.h" 39 #ifdef VBOX_WITH_VIDEOHWACCEL 40 # include "VBoxFBOverlay.h" 41 #endif /* VBOX_WITH_VIDEOHWACCEL */ 42 43 #ifdef Q_WS_MAC 44 # include "UIMachineWindowFullscreen.h" 45 # include "UIMachineWindowSeamless.h" 46 #endif /* Q_WS_MAC */ 47 48 /* Qt includes */ 49 #include <QProgressDialog> 50 #include <QLibraryInfo> 51 #include <QFileDialog> 52 #include <QToolTip> 53 #include <QTranslator> 54 #include <QDesktopWidget> 55 #include <QDesktopServices> 56 #include <QMutex> 57 #include <QToolButton> 58 #include <QProcess> 59 #include <QThread> 60 #include <QPainter> 61 #include <QSettings> 62 #include <QTimer> 63 #include <QDir> 64 #include <QHelpEvent> 65 #include <QLocale> 66 67 #ifdef VBOX_GUI_WITH_PIDFILE 68 # include <QTextStream> 69 #endif /* VBOX_GUI_WITH_PIDFILE */ 70 71 #include <math.h> 72 73 #ifdef Q_WS_X11 74 # include "UIHotKeyEditor.h" 75 # ifndef VBOX_OSE 76 # include "VBoxLicenseViewer.h" 77 # endif /* VBOX_OSE */ 78 # include <QTextBrowser> 79 # include <QScrollBar> 80 # include <QX11Info> 81 # include "VBoxX11Helper.h" 82 #endif 83 84 #ifdef Q_WS_MAC 85 # include "VBoxUtils-darwin.h" 86 #endif /* Q_WS_MAC */ 87 88 #if defined (Q_WS_WIN) 89 #include "shlobj.h" 90 #include <QEventLoop> 91 #endif 92 93 #if defined (Q_WS_X11) 94 #undef BOOL /* typedef CARD8 BOOL in Xmd.h conflicts with #define BOOL PRBool 95 * in COMDefs.h. A better fix would be to isolate X11-specific 96 * stuff by placing XX* helpers below to a separate source file. */ 97 #include <X11/X.h> 98 #include <X11/Xmd.h> 99 #include <X11/Xlib.h> 100 #include <X11/Xatom.h> 101 #include <X11/extensions/Xinerama.h> 102 #define BOOL PRBool 103 #endif 104 105 #include <VBox/sup.h> 106 #include <VBox/com/Guid.h> 107 108 #include <iprt/asm.h> 109 #include <iprt/err.h> 110 #include <iprt/param.h> 111 #include <iprt/path.h> 112 #include <iprt/env.h> 113 #include <iprt/file.h> 114 #include <iprt/ldr.h> 115 #include <iprt/system.h> 116 #include <iprt/stream.h> 117 118 #ifdef VBOX_GUI_WITH_SYSTRAY 119 #include <iprt/process.h> 120 121 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 122 #define HOSTSUFF_EXE ".exe" 123 #else /* !RT_OS_WINDOWS */ 124 #define HOSTSUFF_EXE "" 125 #endif /* !RT_OS_WINDOWS */ 126 #endif 127 128 #if defined (Q_WS_X11) 129 #include <iprt/mem.h> 130 #endif 131 132 //#define VBOX_WITH_FULL_DETAILS_REPORT /* hidden for now */ 133 134 //#warning "port me: check this" 135 /// @todo bird: Use (U)INT_PTR, (U)LONG_PTR, DWORD_PTR, or (u)intptr_t. 136 #if defined(Q_OS_WIN64) 137 typedef __int64 Q_LONG; /* word up to 64 bit signed */ 138 typedef unsigned __int64 Q_ULONG; /* word up to 64 bit unsigned */ 139 #else 140 typedef long Q_LONG; /* word up to 64 bit signed */ 141 typedef unsigned long Q_ULONG; /* word up to 64 bit unsigned */ 142 #endif 143 144 // VBoxMediaEnumEvent 145 ///////////////////////////////////////////////////////////////////////////// 146 147 class VBoxMediaEnumEvent : public QEvent 23 /* Namespace for native window sub-system functions: */ 24 namespace NativeWindowSubsystem 148 25 { 149 public: 150 151 /** Constructs a regular enum event */ 152 VBoxMediaEnumEvent (const VBoxMedium &aMedium, 153 VBoxMediaList::iterator &aIterator) 154 : QEvent ((QEvent::Type) VBoxDefs::MediaEnumEventType) 155 , mMedium (aMedium), mIterator (aIterator), mLast (false) 156 {} 157 /** Constructs the last enum event */ 158 VBoxMediaEnumEvent (VBoxMediaList::iterator &aIterator) 159 : QEvent ((QEvent::Type) VBoxDefs::MediaEnumEventType) 160 , mIterator (aIterator), mLast (true) 161 {} 162 163 /** Last enumerated medium (not valid when #last is true) */ 164 const VBoxMedium mMedium; 165 /** Opaque iterator provided by the event sender (guaranteed to be 166 * the same variable for all media in the single enumeration procedure) */ 167 VBoxMediaList::iterator &mIterator; 168 /** Whether this is the last event for the given enumeration or not */ 169 const bool mLast; 170 }; 171 172 // VBoxGlobal 173 //////////////////////////////////////////////////////////////////////////////// 174 175 static bool sVBoxGlobalInited = false; 176 static bool sVBoxGlobalInCleanup = false; 177 178 /** @internal 179 * 180 * Special routine to do VBoxGlobal cleanup when the application is being 181 * terminated. It is called before some essential Qt functionality (for 182 * instance, QThread) becomes unavailable, allowing us to use it from 183 * VBoxGlobal::cleanup() if necessary. 184 */ 185 static void vboxGlobalCleanup() 186 { 187 Assert (!sVBoxGlobalInCleanup); 188 sVBoxGlobalInCleanup = true; 189 vboxGlobal().cleanup(); 26 /* Enumerates visible always-on-top (top-most) windows: */ 27 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam); 28 /* Contain visible top-most-window rectangles: */ 29 QList<QRect> topMostRects; 190 30 } 191 31 192 /** @internal 193 * 194 * Determines the rendering mode from the argument. Sets the appropriate 195 * default rendering mode if the argument is NULL. 196 */ 197 static VBoxDefs::RenderMode vboxGetRenderMode (const char *aModeStr) 198 { 199 VBoxDefs::RenderMode mode = VBoxDefs::InvalidRenderMode; 200 201 #if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D) 202 mode = VBoxDefs::Quartz2DMode; 203 # ifdef RT_ARCH_X86 204 /* Quartz2DMode doesn't refresh correctly on 32-bit Snow Leopard, use image mode. */ 205 // char szRelease[80]; 206 // if ( RT_SUCCESS (RTSystemQueryOSInfo (RTSYSOSINFO_RELEASE, szRelease, sizeof (szRelease))) 207 // && !strncmp (szRelease, "10.", 3)) 208 // mode = VBoxDefs::QImageMode; 209 # endif 210 #elif (defined (Q_WS_WIN32) || defined (Q_WS_PM) || defined (Q_WS_X11)) && defined (VBOX_GUI_USE_QIMAGE) 211 mode = VBoxDefs::QImageMode; 212 #elif defined (Q_WS_X11) && defined (VBOX_GUI_USE_SDL) 213 mode = VBoxDefs::SDLMode; 214 #elif defined (VBOX_GUI_USE_QIMAGE) 215 mode = VBoxDefs::QImageMode; 216 #else 217 # error "Cannot determine the default render mode!" 218 #endif 219 220 if (aModeStr) 221 { 222 if (0) ; 223 #if defined (VBOX_GUI_USE_QIMAGE) 224 else if (::strcmp (aModeStr, "image") == 0) 225 mode = VBoxDefs::QImageMode; 226 #endif 227 #if defined (VBOX_GUI_USE_SDL) 228 else if (::strcmp (aModeStr, "sdl") == 0) 229 mode = VBoxDefs::SDLMode; 230 #endif 231 #if defined (VBOX_GUI_USE_DDRAW) 232 else if (::strcmp (aModeStr, "ddraw") == 0) 233 mode = VBoxDefs::DDRAWMode; 234 #endif 235 #if defined (VBOX_GUI_USE_QUARTZ2D) 236 else if (::strcmp (aModeStr, "quartz2d") == 0) 237 mode = VBoxDefs::Quartz2DMode; 238 #endif 239 #if defined (VBOX_GUI_USE_QGLFB) 240 else if (::strcmp (aModeStr, "qgl") == 0) 241 mode = VBoxDefs::QGLMode; 242 #endif 243 //#if defined (VBOX_GUI_USE_QGL) 244 // else if (::strcmp (aModeStr, "qgloverlay") == 0) 245 // mode = VBoxDefs::QGLOverlayMode; 246 //#endif 247 248 } 249 250 return mode; 251 } 252 253 /** @class VBoxGlobal 254 * 255 * The VBoxGlobal class encapsulates the global VirtualBox data. 256 * 257 * There is only one instance of this class per VirtualBox application, 258 * the reference to it is returned by the static instance() method, or by 259 * the global vboxGlobal() function, that is just an inlined shortcut. 260 */ 261 262 VBoxGlobal::VBoxGlobal() 263 : mValid (false) 264 , mSelectorWnd (NULL) 265 , m_pVirtualMachine(0) 266 , mMainWindow (NULL) 267 #ifdef VBOX_WITH_REGISTRATION 268 , mRegDlg (NULL) 269 #endif 270 , mUpdDlg (NULL) 271 #ifdef VBOX_GUI_WITH_SYSTRAY 272 , mIsTrayMenu (false) 273 , mIncreasedWindowCounter (false) 274 #endif 275 , mMediaEnumThread (NULL) 276 , mIsKWinManaged (false) 277 , mVerString ("1.0") 278 { 279 } 280 281 // 282 // Public members 283 ///////////////////////////////////////////////////////////////////////////// 284 285 /** 286 * Returns a reference to the global VirtualBox data, managed by this class. 287 * 288 * The main() function of the VBox GUI must call this function soon after 289 * creating a QApplication instance but before opening any of the main windows 290 * (to let the VBoxGlobal initialization procedure use various Qt facilities), 291 * and continue execution only when the isValid() method of the returned 292 * instancereturns true, i.e. do something like: 293 * 294 * @code 295 * if ( !VBoxGlobal::instance().isValid() ) 296 * return 1; 297 * @endcode 298 * or 299 * @code 300 * if ( !vboxGlobal().isValid() ) 301 * return 1; 302 * @endcode 303 * 304 * @note Some VBoxGlobal methods can be used on a partially constructed 305 * VBoxGlobal instance, i.e. from constructors and methods called 306 * from the VBoxGlobal::init() method, which obtain the instance 307 * using this instance() call or the ::vboxGlobal() function. Currently, such 308 * methods are: 309 * #vmStateText, #vmTypeIcon, #vmTypeText, #vmTypeTextList, #vmTypeFromText. 310 * 311 * @see ::vboxGlobal 312 */ 313 VBoxGlobal &VBoxGlobal::instance() 314 { 315 static VBoxGlobal vboxGlobal_instance; 316 317 if (!sVBoxGlobalInited) 318 { 319 /* check that a QApplication instance is created */ 320 if (qApp) 321 { 322 sVBoxGlobalInited = true; 323 vboxGlobal_instance.init(); 324 /* add our cleanup handler to the list of Qt post routines */ 325 qAddPostRoutine (vboxGlobalCleanup); 326 } 327 else 328 AssertMsgFailed (("Must construct a QApplication first!")); 329 } 330 return vboxGlobal_instance; 331 } 332 333 VBoxGlobal::~VBoxGlobal() 334 { 335 qDeleteAll (mOsTypeIcons); 336 qDeleteAll (mVMStateIcons); 337 qDeleteAll (mVMStateColors); 338 } 339 340 /* static */ 341 QString VBoxGlobal::qtRTVersionString() 342 { 343 return QString::fromLatin1 (qVersion()); 344 } 345 346 /* static */ 347 uint VBoxGlobal::qtRTVersion() 348 { 349 QString rt_ver_str = VBoxGlobal::qtRTVersionString(); 350 return (rt_ver_str.section ('.', 0, 0).toInt() << 16) + 351 (rt_ver_str.section ('.', 1, 1).toInt() << 8) + 352 rt_ver_str.section ('.', 2, 2).toInt(); 353 } 354 355 /* static */ 356 QString VBoxGlobal::qtCTVersionString() 357 { 358 return QString::fromLatin1 (QT_VERSION_STR); 359 } 360 361 /* static */ 362 uint VBoxGlobal::qtCTVersion() 363 { 364 QString ct_ver_str = VBoxGlobal::qtCTVersionString(); 365 return (ct_ver_str.section ('.', 0, 0).toInt() << 16) + 366 (ct_ver_str.section ('.', 1, 1).toInt() << 8) + 367 ct_ver_str.section ('.', 2, 2).toInt(); 368 } 369 370 bool VBoxGlobal::isBeta() const 371 { 372 return mVBox.GetVersion().contains("BETA", Qt::CaseInsensitive); 373 } 374 375 /** 376 * Sets the new global settings and saves them to the VirtualBox server. 377 */ 378 bool VBoxGlobal::setSettings (VBoxGlobalSettings &gs) 379 { 380 gs.save (mVBox); 381 382 if (!mVBox.isOk()) 383 { 384 vboxProblem().cannotSaveGlobalConfig (mVBox); 385 return false; 386 } 387 388 /* We don't assign gs to our gset member here, because VBoxCallback 389 * will update gset as necessary when new settings are successfully 390 * sent to the VirtualBox server by gs.save(). */ 391 392 return true; 393 } 394 395 /** 396 * Returns a reference to the main VBox VM Selector window. 397 * The reference is valid until application termination. 398 * 399 * There is only one such a window per VirtualBox application. 400 */ 401 VBoxSelectorWnd &VBoxGlobal::selectorWnd() 402 { 403 AssertMsg (!vboxGlobal().isVMConsoleProcess(), 404 ("Must NOT be a VM console process")); 405 Assert (mValid); 406 407 if (!mSelectorWnd) 408 { 409 /* 410 * We pass the address of mSelectorWnd to the constructor to let it be 411 * initialized right after the constructor is called. It is necessary 412 * to avoid recursion, since this method may be (and will be) called 413 * from the below constructor or from constructors/methods it calls. 414 */ 415 VBoxSelectorWnd *w = new VBoxSelectorWnd (&mSelectorWnd, 0); 416 Assert (w == mSelectorWnd); 417 NOREF(w); 418 } 419 420 return *mSelectorWnd; 421 } 422 423 424 QWidget *VBoxGlobal::vmWindow() 425 { 426 if (isVMConsoleProcess()) 427 { 428 if (m_pVirtualMachine) 429 return m_pVirtualMachine->mainWindow(); 430 } 431 return NULL; 432 } 433 434 bool VBoxGlobal::createVirtualMachine(const CSession &session) 435 { 436 if (!m_pVirtualMachine && !session.isNull()) 437 { 438 UIMachine *pVirtualMachine = new UIMachine(&m_pVirtualMachine, session); 439 Assert(pVirtualMachine == m_pVirtualMachine); 440 NOREF(pVirtualMachine); 441 return true; 442 } 443 return false; 444 } 445 446 UIMachine* VBoxGlobal::virtualMachine() 447 { 448 return m_pVirtualMachine; 449 } 450 451 #ifdef VBOX_GUI_WITH_PIDFILE 452 void VBoxGlobal::createPidfile() 453 { 454 if (!m_strPidfile.isEmpty()) 455 { 456 qint64 pid = qApp->applicationPid(); 457 QFile file(m_strPidfile); 458 if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) 459 { 460 QTextStream out(&file); 461 out << pid << endl; 462 } 463 else 464 LogRel(("Failed to create pid file %s\n", m_strPidfile.toUtf8().constData())); 465 } 466 } 467 468 void VBoxGlobal::deletePidfile() 469 { 470 if ( !m_strPidfile.isEmpty() 471 && QFile::exists(m_strPidfile)) 472 QFile::remove(m_strPidfile); 473 } 474 #endif 475 476 bool VBoxGlobal::brandingIsActive (bool aForce /* = false*/) 477 { 478 if (aForce) 479 return true; 480 481 if (mBrandingConfig.isEmpty()) 482 { 483 mBrandingConfig = QDir(QApplication::applicationDirPath()).absolutePath(); 484 mBrandingConfig += "/custom/custom.ini"; 485 } 486 return QFile::exists (mBrandingConfig); 487 } 488 489 /** 490 * Gets a value from the custom .ini file 491 */ 492 QString VBoxGlobal::brandingGetKey (QString aKey) 493 { 494 QSettings s(mBrandingConfig, QSettings::IniFormat); 495 return s.value(QString("%1").arg(aKey)).toString(); 496 } 497 498 #ifdef VBOX_GUI_WITH_SYSTRAY 499 500 /** 501 * Returns true if the current instance a systray menu only (started with 502 * "-systray" parameter). 503 */ 504 bool VBoxGlobal::isTrayMenu() const 505 { 506 return mIsTrayMenu; 507 } 508 509 void VBoxGlobal::setTrayMenu(bool aIsTrayMenu) 510 { 511 mIsTrayMenu = aIsTrayMenu; 512 } 513 514 /** 515 * Spawns a new selector window (process). 516 */ 517 void VBoxGlobal::trayIconShowSelector() 518 { 519 /* Get the path to the executable. */ 520 char path[RTPATH_MAX]; 521 RTPathAppPrivateArch(path, RTPATH_MAX); 522 size_t sz = strlen(path); 523 path[sz++] = RTPATH_DELIMITER; 524 path[sz] = 0; 525 char *cmd = path + sz; 526 sz = RTPATH_MAX - sz; 527 528 int rc = 0; 529 const char VirtualBox_exe[] = "VirtualBox" HOSTSUFF_EXE; 530 Assert(sz >= sizeof(VirtualBox_exe)); 531 strcpy(cmd, VirtualBox_exe); 532 const char * args[] = {path, 0 }; 533 rc = RTProcCreate(path, args, RTENV_DEFAULT, RTPROC_FLAGS_DETACHED, NULL); 534 if (RT_FAILURE(rc)) 535 LogRel(("Systray: Failed to start new selector window! Path=%s, rc=%Rrc\n", path, rc)); 536 } 537 538 /** 539 * Tries to install the tray icon using the current instance (singleton). 540 * Returns true if this instance is the tray icon, false if not. 541 */ 542 bool VBoxGlobal::trayIconInstall() 543 { 544 int rc = 0; 545 QString strTrayWinID = mVBox.GetExtraData(VBoxDefs::GUI_TrayIconWinID); 546 if (false == strTrayWinID.isEmpty()) 547 { 548 /* Check if current tray icon is alive by writing some bogus value. */ 549 mVBox.SetExtraData(VBoxDefs::GUI_TrayIconWinID, "0"); 550 if (mVBox.isOk()) 551 { 552 /* Current tray icon died - clean up. */ 553 mVBox.SetExtraData(VBoxDefs::GUI_TrayIconWinID, NULL); 554 strTrayWinID.clear(); 555 } 556 } 557 558 /* Is there already a tray icon or is tray icon not active? */ 559 if ( (mIsTrayMenu == false) 560 && (vboxGlobal().settings().trayIconEnabled()) 561 && (QSystemTrayIcon::isSystemTrayAvailable()) 562 && (strTrayWinID.isEmpty())) 563 { 564 /* Get the path to the executable. */ 565 char path[RTPATH_MAX]; 566 RTPathAppPrivateArch(path, RTPATH_MAX); 567 size_t sz = strlen(path); 568 path[sz++] = RTPATH_DELIMITER; 569 path[sz] = 0; 570 char *cmd = path + sz; 571 sz = RTPATH_MAX - sz; 572 573 const char VirtualBox_exe[] = "VirtualBox" HOSTSUFF_EXE; 574 Assert(sz >= sizeof(VirtualBox_exe)); 575 strcpy(cmd, VirtualBox_exe); 576 const char * args[] = {path, "-systray", 0 }; 577 rc = RTProcCreate(path, args, RTENV_DEFAULT, RTPROC_FLAGS_DETACHED, NULL); 578 if (RT_FAILURE(rc)) 579 { 580 LogRel(("Systray: Failed to start systray window! Path=%s, rc=%Rrc\n", path, rc)); 581 return false; 582 } 583 } 584 585 if (mIsTrayMenu) 586 { 587 // Use this selector for displaying the tray icon 588 mVBox.SetExtraData(VBoxDefs::GUI_TrayIconWinID, 589 QString("%1").arg((qulonglong)vboxGlobal().mainWindow()->winId())); 590 591 /* The first process which can grab this "mutex" will win -> 592 * It will be the tray icon menu then. */ 593 if (mVBox.isOk()) 594 { 595 emit sigTrayIconShow(true); 596 return true; 597 } 598 } 599 600 return false; 601 } 602 603 #endif 604 605 #ifdef Q_WS_X11 606 QList<QRect> XGetDesktopList() 607 { 608 /* Prepare empty resulting list: */ 609 QList<QRect> result; 610 611 /* Get current display: */ 612 Display* pDisplay = QX11Info::display(); 613 614 /* If it's a Xinerama desktop: */ 615 if (XineramaIsActive(pDisplay)) 616 { 617 /* Reading Xinerama data: */ 618 int iScreens = 0; 619 XineramaScreenInfo *pScreensData = XineramaQueryScreens(pDisplay, &iScreens); 620 621 /* Fill resulting list: */ 622 for (int i = 0; i < iScreens; ++ i) 623 result << QRect(pScreensData[i].x_org, pScreensData[i].y_org, 624 pScreensData[i].width, pScreensData[i].height); 625 626 /* Free screens data: */ 627 XFree(pScreensData); 628 } 629 630 /* Return resulting list: */ 631 return result; 632 } 633 634 QList<Window> XGetWindowIDList() 635 { 636 /* Get current display: */ 637 Display *pDisplay = QX11Info::display(); 638 639 /* Get virtual desktop window: */ 640 Window window = QX11Info::appRootWindow(); 641 642 /* Get 'client list' atom: */ 643 Atom propNameAtom = XInternAtom(pDisplay, "_NET_CLIENT_LIST", True /* only if exists */); 644 645 /* Prepare empty resulting list: */ 646 QList<Window> result; 647 648 /* If atom does not exists return empty list: */ 649 if (propNameAtom == None) 650 return result; 651 652 /* Get atom value: */ 653 Atom realAtomType = None; 654 int iRealFormat = 0; 655 unsigned long uItemsCount = 0; 656 unsigned long uBytesAfter = 0; 657 unsigned char *pData = 0; 658 int rc = XGetWindowProperty(pDisplay, window, propNameAtom, 659 0, 0x7fffffff /*LONG_MAX*/, False /* delete */, 660 XA_WINDOW, &realAtomType, &iRealFormat, 661 &uItemsCount, &uBytesAfter, &pData); 662 663 /* If get property is failed return empty list: */ 664 if (rc != Success) 665 return result; 666 667 /* Fill resulting list with win ids: */ 668 Window *pWindowData = reinterpret_cast<Window*>(pData); 669 for (ulong i = 0; i < uItemsCount; ++ i) 670 result << pWindowData[i]; 671 672 /* Releasing resources: */ 673 XFree(pData); 674 675 /* Return resulting list: */ 676 return result; 677 } 678 679 QList<ulong> XGetStrut(Window window) 680 { 681 /* Get current display: */ 682 Display *pDisplay = QX11Info::display(); 683 684 /* Get 'strut' atom: */ 685 Atom propNameAtom = XInternAtom(pDisplay, "_NET_WM_STRUT_PARTIAL", True /* only if exists */); 686 687 /* Prepare empty resulting list: */ 688 QList<ulong> result; 689 690 /* If atom does not exists return empty list: */ 691 if (propNameAtom == None) 692 return result; 693 694 /* Get atom value: */ 695 Atom realAtomType = None; 696 int iRealFormat = 0; 697 ulong uItemsCount = 0; 698 ulong uBytesAfter = 0; 699 unsigned char *pData = 0; 700 int rc = XGetWindowProperty(pDisplay, window, propNameAtom, 701 0, LONG_MAX, False /* delete */, 702 XA_CARDINAL, &realAtomType, &iRealFormat, 703 &uItemsCount, &uBytesAfter, &pData); 704 705 /* If get property is failed return empty list: */ 706 if (rc != Success) 707 return result; 708 709 /* Fill resulting list with strut shifts: */ 710 ulong *pStrutsData = reinterpret_cast<ulong*>(pData); 711 for (ulong i = 0; i < uItemsCount; ++ i) 712 result << pStrutsData[i]; 713 714 /* Releasing resources: */ 715 XFree(pData); 716 717 /* Return resulting list: */ 718 return result; 719 } 720 #endif /* ifdef Q_WS_X11 */ 721 722 const QRect VBoxGlobal::availableGeometry(int iScreen) const 723 { 724 /* Prepare empty result: */ 725 QRect result; 726 727 #ifdef Q_WS_X11 728 729 /* Get current display: */ 730 Display* pDisplay = QX11Info::display(); 731 732 /* Get current application desktop: */ 733 QDesktopWidget *pDesktopWidget = QApplication::desktop(); 734 735 /* If it's a virtual desktop: */ 736 if (pDesktopWidget->isVirtualDesktop()) 737 { 738 /* If it's a Xinerama desktop: */ 739 if (XineramaIsActive(pDisplay)) 740 { 741 /* Get desktops list: */ 742 QList<QRect> desktops = XGetDesktopList(); 743 744 /* Combine to get full virtual region: */ 745 QRegion virtualRegion; 746 foreach (QRect desktop, desktops) 747 virtualRegion += desktop; 748 virtualRegion = virtualRegion.boundingRect(); 749 750 /* Remember initial virtual desktop: */ 751 QRect virtualDesktop = virtualRegion.boundingRect(); 752 //AssertMsgFailed(("LOG... Virtual desktop is: %dx%dx%dx%d\n", virtualDesktop.x(), virtualDesktop.y(), 753 // virtualDesktop.width(), virtualDesktop.height())); 754 755 /* Set available geometry to screen geometry initially: */ 756 result = desktops[iScreen]; 757 758 /* Feat available geometry of virtual desktop to respect all the struts: */ 759 QList<Window> list = XGetWindowIDList(); 760 for (int i = 0; i < list.size(); ++ i) 761 { 762 /* Get window: */ 763 Window wid = list[i]; 764 QList<ulong> struts = XGetStrut(wid); 765 766 /* If window has strut: */ 767 if (struts.size()) 768 { 769 ulong uLeftShift = struts[0]; 770 ulong uLeftFromY = struts[4]; 771 ulong uLeftToY = struts[5]; 772 773 ulong uRightShift = struts[1]; 774 ulong uRightFromY = struts[6]; 775 ulong uRightToY = struts[7]; 776 777 ulong uTopShift = struts[2]; 778 ulong uTopFromX = struts[8]; 779 ulong uTopToX = struts[9]; 780 781 ulong uBottomShift = struts[3]; 782 ulong uBottomFromX = struts[10]; 783 ulong uBottomToX = struts[11]; 784 785 if (uLeftShift) 786 { 787 QRect sr(QPoint(0, uLeftFromY), 788 QSize(uLeftShift, uLeftToY - uLeftFromY + 1)); 789 790 //AssertMsgFailed(("LOG... Subtract left strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height())); 791 virtualRegion -= sr; 792 } 793 794 if (uRightShift) 795 { 796 QRect sr(QPoint(virtualDesktop.x() + virtualDesktop.width() - uRightShift, uRightFromY), 797 QSize(virtualDesktop.x() + virtualDesktop.width(), uRightToY - uRightFromY + 1)); 798 799 //AssertMsgFailed(("LOG... Subtract right strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height())); 800 virtualRegion -= sr; 801 } 802 803 if (uTopShift) 804 { 805 QRect sr(QPoint(uTopFromX, 0), 806 QSize(uTopToX - uTopFromX + 1, uTopShift)); 807 808 //AssertMsgFailed(("LOG... Subtract top strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height())); 809 virtualRegion -= sr; 810 } 811 812 if (uBottomShift) 813 { 814 QRect sr(QPoint(uBottomFromX, virtualDesktop.y() + virtualDesktop.height() - uBottomShift), 815 QSize(uBottomToX - uBottomFromX + 1, uBottomShift)); 816 817 //AssertMsgFailed(("LOG... Subtract bottom strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height())); 818 virtualRegion -= sr; 819 } 820 } 821 } 822 823 /* Get final available geometry: */ 824 result = (virtualRegion & result).boundingRect(); 825 } 826 } 827 828 /* If result is still NULL: */ 829 if (result.isNull()) 830 { 831 /* Use QT default functionality: */ 832 result = pDesktopWidget->availableGeometry(iScreen); 833 } 834 835 //AssertMsgFailed(("LOG... Final geometry: %dx%dx%dx%d\n", result.x(), result.y(), result.width(), result.height())); 836 837 #else /* ifdef Q_WS_X11 */ 838 839 result = QApplication::desktop()->availableGeometry(iScreen); 840 841 #endif /* ifndef Q_WS_X11 */ 842 843 return result; 844 } 845 846 #ifdef Q_WS_WIN 847 /* Enumerate visible top-most windows: */ 848 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM /* lParam */) 32 /* Enumerates visible always-on-top (top-most) windows: */ 33 BOOL CALLBACK NativeWindowSubsystem::EnumWindowsProc(HWND hWnd, LPARAM /* lParam */) 849 34 { 850 35 /* Ignore NULL HWNDs: */ … … 871 56 RECT rect; 872 57 GetWindowRect(hWnd, &rect); 873 VBoxGlobal::m_sTopMostRects << QRect(QPoint(rect.left, rect.top), QPoint(rect.right - 1, rect.bottom - 1));58 topMostRects << QRect(QPoint(rect.left, rect.top), QPoint(rect.right - 1, rect.bottom - 1)); 874 59 875 60 /* Proceed to the next window: */ … … 877 62 } 878 63 879 /* static */ 880 QList<QRect> VBoxGlobal::m_sTopMostRects = QList<QRect>(); 881 882 /* static */ 883 const QRegion VBoxGlobal::areaCoveredByTopMostWindows() 64 /* Returns area covered by visible always-on-top (top-most) windows: */ 65 const QRegion NativeWindowSubsystem::areaCoveredByTopMostWindows() 884 66 { 885 67 /* Prepare the top-most region: */ 886 68 QRegion topMostRegion; 887 69 /* Initialize the list of the top-most rectangles: */ 888 m_sTopMostRects.clear();70 topMostRects.clear(); 889 71 /* Populate the list of top-most rectangles: */ 890 72 EnumWindows((WNDENUMPROC)EnumWindowsProc, 0); 891 73 /* Update the top-most region with top-most rectangles: */ 892 for (int iRectIndex = 0; iRectIndex < m_sTopMostRects.size(); ++iRectIndex)893 topMostRegion += m_sTopMostRects[iRectIndex];74 for (int iRectIndex = 0; iRectIndex < topMostRects.size(); ++iRectIndex) 75 topMostRegion += topMostRects[iRectIndex]; 894 76 /* Return top-most region: */ 895 77 return topMostRegion; 896 78 } 897 #endif /* Q_WS_WIN */898 79 899 /**900 * Returns the list of few guest OS types, queried from901 * IVirtualBox corresponding to every family id.902 */903 QList <CGuestOSType> VBoxGlobal::vmGuestOSFamilyList() const904 {905 QList <CGuestOSType> result;906 for (int i = 0 ; i < mFamilyIDs.size(); ++ i)907 result << mTypes [i][0];908 return result;909 }910 911 /**912 * Returns the list of all guest OS types, queried from913 * IVirtualBox corresponding to passed family id.914 */915 QList <CGuestOSType> VBoxGlobal::vmGuestOSTypeList (const QString &aFamilyId) const916 {917 AssertMsg (mFamilyIDs.contains (aFamilyId), ("Family ID incorrect: '%s'.", aFamilyId.toLatin1().constData()));918 return mFamilyIDs.contains (aFamilyId) ?919 mTypes [mFamilyIDs.indexOf (aFamilyId)] : QList <CGuestOSType>();920 }921 922 /**923 * Returns the icon corresponding to the given guest OS type id.924 */925 QPixmap VBoxGlobal::vmGuestOSTypeIcon (const QString &aTypeId) const926 {927 static const QPixmap none;928 QPixmap *p = mOsTypeIcons.value (aTypeId);929 AssertMsg (p, ("Icon for type '%s' must be defined.", aTypeId.toLatin1().constData()));930 return p ? *p : none;931 }932 933 /**934 * Returns the guest OS type object corresponding to the given type id of list935 * containing OS types related to OS family determined by family id attribute.936 * If the index is invalid a null object is returned.937 */938 CGuestOSType VBoxGlobal::vmGuestOSType (const QString &aTypeId,939 const QString &aFamilyId /* = QString::null */) const940 {941 QList <CGuestOSType> list;942 if (mFamilyIDs.contains (aFamilyId))943 {944 list = mTypes [mFamilyIDs.indexOf (aFamilyId)];945 }946 else947 {948 for (int i = 0; i < mFamilyIDs.size(); ++ i)949 list += mTypes [i];950 }951 for (int j = 0; j < list.size(); ++ j)952 if (!list [j].GetId().compare (aTypeId))953 return list [j];954 AssertMsgFailed (("Type ID incorrect: '%s'.", aTypeId.toLatin1().constData()));955 return CGuestOSType();956 }957 958 /**959 * Returns the description corresponding to the given guest OS type id.960 */961 QString VBoxGlobal::vmGuestOSTypeDescription (const QString &aTypeId) const962 {963 for (int i = 0; i < mFamilyIDs.size(); ++ i)964 {965 QList <CGuestOSType> list (mTypes [i]);966 for ( int j = 0; j < list.size(); ++ j)967 if (!list [j].GetId().compare (aTypeId))968 return list [j].GetDescription();969 }970 return QString::null;971 }972 973 /**974 * Returns a string representation of the given channel number on the given storage bus.975 * Complementary to #toStorageChannel (KStorageBus, const QString &) const.976 */977 QString VBoxGlobal::toString (KStorageBus aBus, LONG aChannel) const978 {979 QString channel;980 981 switch (aBus)982 {983 case KStorageBus_IDE:984 {985 if (aChannel == 0 || aChannel == 1)986 {987 channel = mStorageBusChannels [aChannel];988 break;989 }990 AssertMsgFailed (("Invalid IDE channel %d\n", aChannel));991 break;992 }993 case KStorageBus_SATA:994 case KStorageBus_SCSI:995 {996 channel = mStorageBusChannels [2].arg (aChannel);997 break;998 }999 case KStorageBus_Floppy:1000 {1001 AssertMsgFailed (("Floppy have no channels, only devices\n"));1002 break;1003 }1004 default:1005 {1006 AssertMsgFailed (("Invalid bus type %d\n", aBus));1007 break;1008 }1009 }1010 1011 Assert (!channel.isNull());1012 return channel;1013 }1014 1015 /**1016 * Returns a channel number on the given storage bus corresponding to the given string representation.1017 * Complementary to #toString (KStorageBus, LONG) const.1018 */1019 LONG VBoxGlobal::toStorageChannel (KStorageBus aBus, const QString &aChannel) const1020 {1021 LONG channel = 0;1022 1023 switch (aBus)1024 {1025 case KStorageBus_IDE:1026 {1027 QLongStringHash::const_iterator it = qFind (mStorageBusChannels.begin(), mStorageBusChannels.end(), aChannel);1028 AssertMsgBreak (it != mStorageBusChannels.end(), ("No value for {%s}\n", aChannel.toLatin1().constData()));1029 channel = it.key();1030 break;1031 }1032 case KStorageBus_SATA:1033 case KStorageBus_SCSI:1034 {1035 QString tpl = mStorageBusChannels [2].arg ("");1036 if (aChannel.startsWith (tpl))1037 {1038 channel = aChannel.right (aChannel.length() - tpl.length()).toLong();1039 break;1040 }1041 AssertMsgFailed (("Invalid channel {%s}\n", aChannel.toLatin1().constData()));1042 break;1043 }1044 case KStorageBus_Floppy:1045 {1046 channel = 0;1047 break;1048 }1049 default:1050 {1051 AssertMsgFailed (("Invalid bus type %d\n", aBus));1052 break;1053 }1054 }1055 1056 return channel;1057 }1058 1059 /**1060 * Returns a string representation of the given device number of the given channel on the given storage bus.1061 * Complementary to #toStorageDevice (KStorageBus, LONG, const QString &) const.1062 */1063 QString VBoxGlobal::toString (KStorageBus aBus, LONG aChannel, LONG aDevice) const1064 {1065 NOREF (aChannel);1066 1067 QString device;1068 1069 switch (aBus)1070 {1071 case KStorageBus_IDE:1072 {1073 if (aDevice == 0 || aDevice == 1)1074 {1075 device = mStorageBusDevices [aDevice];1076 break;1077 }1078 AssertMsgFailed (("Invalid device %d\n", aDevice));1079 break;1080 }1081 case KStorageBus_SATA:1082 case KStorageBus_SCSI:1083 {1084 AssertMsgFailed (("SATA & SCSI have no devices, only channels\n"));1085 break;1086 }1087 case KStorageBus_Floppy:1088 {1089 AssertMsgBreak (aChannel == 0, ("Invalid channel %d\n", aChannel));1090 device = mStorageBusDevices [2].arg (aDevice);1091 break;1092 }1093 default:1094 {1095 AssertMsgFailed (("Invalid bus type %d\n", aBus));1096 break;1097 }1098 }1099 1100 Assert (!device.isNull());1101 return device;1102 }1103 1104 /**1105 * Returns a device number of the given channel on the given storage bus corresponding to the given string representation.1106 * Complementary to #toString (KStorageBus, LONG, LONG) const.1107 */1108 LONG VBoxGlobal::toStorageDevice (KStorageBus aBus, LONG aChannel, const QString &aDevice) const1109 {1110 NOREF (aChannel);1111 1112 LONG device = 0;1113 1114 switch (aBus)1115 {1116 case KStorageBus_IDE:1117 {1118 QLongStringHash::const_iterator it = qFind (mStorageBusDevices.begin(), mStorageBusDevices.end(), aDevice);1119 AssertMsgBreak (it != mStorageBusDevices.end(), ("No value for {%s}", aDevice.toLatin1().constData()));1120 device = it.key();1121 break;1122 }1123 case KStorageBus_SATA:1124 case KStorageBus_SCSI:1125 {1126 device = 0;1127 break;1128 }1129 case KStorageBus_Floppy:1130 {1131 AssertMsgBreak (aChannel == 0, ("Invalid channel %d\n", aChannel));1132 QString tpl = mStorageBusDevices [2].arg ("");1133 if (aDevice.startsWith (tpl))1134 {1135 device = aDevice.right (aDevice.length() - tpl.length()).toLong();1136 break;1137 }1138 AssertMsgFailed (("Invalid device {%s}\n", aDevice.toLatin1().constData()));1139 break;1140 }1141 default:1142 {1143 AssertMsgFailed (("Invalid bus type %d\n", aBus));1144 break;1145 }1146 }1147 1148 return device;1149 }1150 1151 /**1152 * Returns a full string representation of the given device of the given channel on the given storage bus.1153 * This method does not uses any separate string tags related to bus, channel, device, it has own1154 * separately translated string tags allowing to translate a full slot name into human readable format1155 * to be consistent with i18n.1156 * Complementary to #toStorageSlot (const QString &) const.1157 */1158 QString VBoxGlobal::toString (StorageSlot aSlot) const1159 {1160 switch (aSlot.bus)1161 {1162 case KStorageBus_IDE:1163 case KStorageBus_SATA:1164 case KStorageBus_SCSI:1165 case KStorageBus_SAS:1166 case KStorageBus_Floppy:1167 break;1168 1169 default:1170 {1171 AssertMsgFailed (("Invalid bus type %d\n", aSlot.bus));1172 break;1173 }1174 }1175 1176 int maxPort = virtualBox().GetSystemProperties().GetMaxPortCountForStorageBus (aSlot.bus);1177 int maxDevice = virtualBox().GetSystemProperties().GetMaxDevicesPerPortForStorageBus (aSlot.bus);1178 if (aSlot.port < 0 || aSlot.port > maxPort)1179 AssertMsgFailed (("Invalid port %d\n", aSlot.port));1180 if (aSlot.device < 0 || aSlot.device > maxDevice)1181 AssertMsgFailed (("Invalid device %d\n", aSlot.device));1182 1183 QString result;1184 switch (aSlot.bus)1185 {1186 case KStorageBus_IDE:1187 {1188 result = mSlotTemplates [aSlot.port * maxDevice + aSlot.device];1189 break;1190 }1191 case KStorageBus_SATA:1192 {1193 result = mSlotTemplates [4].arg (aSlot.port);1194 break;1195 }1196 case KStorageBus_SCSI:1197 {1198 result = mSlotTemplates [5].arg (aSlot.port);1199 break;1200 }1201 case KStorageBus_SAS:1202 {1203 result = mSlotTemplates [6].arg (aSlot.port);1204 break;1205 }1206 case KStorageBus_Floppy:1207 {1208 result = mSlotTemplates [7].arg (aSlot.device);1209 break;1210 }1211 default:1212 {1213 AssertMsgFailed (("Invalid bus type %d\n", aSlot.bus));1214 break;1215 }1216 }1217 return result;1218 }1219 1220 /**1221 * Returns a StorageSlot based on the given device of the given channel on the given storage bus.1222 * Complementary to #toFullString (StorageSlot) const.1223 */1224 StorageSlot VBoxGlobal::toStorageSlot (const QString &aSlot) const1225 {1226 int index = -1;1227 QRegExp regExp;1228 for (int i = 0; i < mSlotTemplates.size(); ++ i)1229 {1230 regExp = QRegExp (i >= 0 && i <= 3 ? mSlotTemplates [i] : mSlotTemplates [i].arg ("(\\d+)"));1231 if (regExp.indexIn (aSlot) != -1)1232 {1233 index = i;1234 break;1235 }1236 }1237 1238 StorageSlot result;1239 switch (index)1240 {1241 case 0:1242 case 1:1243 case 2:1244 case 3:1245 {1246 result.bus = KStorageBus_IDE;1247 int maxPort = virtualBox().GetSystemProperties().GetMaxPortCountForStorageBus (result.bus);1248 result.port = index / maxPort;1249 result.device = index % maxPort;1250 break;1251 }1252 case 4:1253 {1254 result.bus = KStorageBus_SATA;1255 int maxPort = virtualBox().GetSystemProperties().GetMaxPortCountForStorageBus (result.bus);1256 result.port = regExp.cap (1).toInt();1257 if (result.port < 0 || result.port > maxPort)1258 AssertMsgFailed (("Invalid port %d\n", result.port));1259 break;1260 }1261 case 5:1262 {1263 result.bus = KStorageBus_SCSI;1264 int maxPort = virtualBox().GetSystemProperties().GetMaxPortCountForStorageBus (result.bus);1265 result.port = regExp.cap (1).toInt();1266 if (result.port < 0 || result.port > maxPort)1267 AssertMsgFailed (("Invalid port %d\n", result.port));1268 break;1269 }1270 case 6:1271 {1272 result.bus = KStorageBus_SAS;1273 int maxPort = virtualBox().GetSystemProperties().GetMaxPortCountForStorageBus (result.bus);1274 result.port = regExp.cap (1).toInt();1275 if (result.port < 0 || result.port > maxPort)1276 AssertMsgFailed (("Invalid port %d\n", result.port));1277 break;1278 }1279 case 7:1280 {1281 result.bus = KStorageBus_Floppy;1282 int maxDevice = virtualBox().GetSystemProperties().GetMaxDevicesPerPortForStorageBus (result.bus);1283 result.device = regExp.cap (1).toInt();1284 if (result.device < 0 || result.device > maxDevice)1285 AssertMsgFailed (("Invalid device %d\n", result.device));1286 break;1287 }1288 default:1289 break;1290 }1291 return result;1292 }1293 1294 /**1295 * Returns the list of all device types (VirtualBox::DeviceType COM enum).1296 */1297 QStringList VBoxGlobal::deviceTypeStrings() const1298 {1299 static QStringList list;1300 if (list.empty())1301 for (QULongStringHash::const_iterator it = mDeviceTypes.begin();1302 it != mDeviceTypes.end(); ++ it)1303 list += it.value();1304 return list;1305 }1306 1307 struct PortConfig1308 {1309 const char *name;1310 const ulong IRQ;1311 const ulong IOBase;1312 };1313 1314 static const PortConfig kComKnownPorts[] =1315 {1316 { "COM1", 4, 0x3F8 },1317 { "COM2", 3, 0x2F8 },1318 { "COM3", 4, 0x3E8 },1319 { "COM4", 3, 0x2E8 },1320 /* must not contain an element with IRQ=0 and IOBase=0 used to cause1321 * toCOMPortName() to return the "User-defined" string for these values. */1322 };1323 1324 static const PortConfig kLptKnownPorts[] =1325 {1326 { "LPT1", 7, 0x3BC },1327 { "LPT2", 5, 0x378 },1328 { "LPT3", 5, 0x278 },1329 /* must not contain an element with IRQ=0 and IOBase=0 used to cause1330 * toLPTPortName() to return the "User-defined" string for these values. */1331 };1332 1333 /**1334 * Returns the list of the standard COM port names (i.e. "COMx").1335 */1336 QStringList VBoxGlobal::COMPortNames() const1337 {1338 QStringList list;1339 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i)1340 list << kComKnownPorts [i].name;1341 1342 return list;1343 }1344 1345 /**1346 * Returns the list of the standard LPT port names (i.e. "LPTx").1347 */1348 QStringList VBoxGlobal::LPTPortNames() const1349 {1350 QStringList list;1351 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i)1352 list << kLptKnownPorts [i].name;1353 1354 return list;1355 }1356 1357 /**1358 * Returns the name of the standard COM port corresponding to the given1359 * parameters, or "User-defined" (which is also returned when both1360 * @a aIRQ and @a aIOBase are 0).1361 */1362 QString VBoxGlobal::toCOMPortName (ulong aIRQ, ulong aIOBase) const1363 {1364 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i)1365 if (kComKnownPorts [i].IRQ == aIRQ &&1366 kComKnownPorts [i].IOBase == aIOBase)1367 return kComKnownPorts [i].name;1368 1369 return mUserDefinedPortName;1370 }1371 1372 /**1373 * Returns the name of the standard LPT port corresponding to the given1374 * parameters, or "User-defined" (which is also returned when both1375 * @a aIRQ and @a aIOBase are 0).1376 */1377 QString VBoxGlobal::toLPTPortName (ulong aIRQ, ulong aIOBase) const1378 {1379 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i)1380 if (kLptKnownPorts [i].IRQ == aIRQ &&1381 kLptKnownPorts [i].IOBase == aIOBase)1382 return kLptKnownPorts [i].name;1383 1384 return mUserDefinedPortName;1385 }1386 1387 /**1388 * Returns port parameters corresponding to the given standard COM name.1389 * Returns @c true on success, or @c false if the given port name is not one1390 * of the standard names (i.e. "COMx").1391 */1392 bool VBoxGlobal::toCOMPortNumbers (const QString &aName, ulong &aIRQ,1393 ulong &aIOBase) const1394 {1395 for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i)1396 if (strcmp (kComKnownPorts [i].name, aName.toUtf8().data()) == 0)1397 {1398 aIRQ = kComKnownPorts [i].IRQ;1399 aIOBase = kComKnownPorts [i].IOBase;1400 return true;1401 }1402 1403 return false;1404 }1405 1406 /**1407 * Returns port parameters corresponding to the given standard LPT name.1408 * Returns @c true on success, or @c false if the given port name is not one1409 * of the standard names (i.e. "LPTx").1410 */1411 bool VBoxGlobal::toLPTPortNumbers (const QString &aName, ulong &aIRQ,1412 ulong &aIOBase) const1413 {1414 for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i)1415 if (strcmp (kLptKnownPorts [i].name, aName.toUtf8().data()) == 0)1416 {1417 aIRQ = kLptKnownPorts [i].IRQ;1418 aIOBase = kLptKnownPorts [i].IOBase;1419 return true;1420 }1421 1422 return false;1423 }1424 1425 /**1426 * Searches for the given hard disk in the list of known media descriptors and1427 * calls VBoxMedium::details() on the found descriptor.1428 *1429 * If the requested hard disk is not found (for example, it's a new hard disk1430 * for a new VM created outside our UI), then media enumeration is requested and1431 * the search is repeated. We assume that the second attempt always succeeds and1432 * assert otherwise.1433 *1434 * @note Technically, the second attempt may fail if, for example, the new hard1435 * passed to this method disk gets removed before #startEnumeratingMedia()1436 * succeeds. This (unexpected object uninitialization) is a generic1437 * problem though and needs to be addressed using exceptions (see also the1438 * @todo in VBoxMedium::details()).1439 */1440 QString VBoxGlobal::details (const CMedium &aMedium, bool aPredictDiff)1441 {1442 CMedium cmedium (aMedium);1443 VBoxMedium medium;1444 1445 if (!findMedium (cmedium, medium))1446 {1447 /* Medium may be new and not already in the media list, request refresh */1448 startEnumeratingMedia();1449 if (!findMedium (cmedium, medium))1450 /* Medium might be deleted already, return null string */1451 return QString();1452 }1453 1454 return medium.detailsHTML (true /* aNoDiffs */, aPredictDiff);1455 }1456 1457 /**1458 * Returns the details of the given USB device as a single-line string.1459 */1460 QString VBoxGlobal::details (const CUSBDevice &aDevice) const1461 {1462 QString sDetails;1463 if (aDevice.isNull())1464 sDetails = tr("Unknown device", "USB device details");1465 else1466 {1467 QString m = aDevice.GetManufacturer().trimmed();1468 QString p = aDevice.GetProduct().trimmed();1469 1470 if (m.isEmpty() && p.isEmpty())1471 {1472 sDetails =1473 tr ("Unknown device %1:%2", "USB device details")1474 .arg (QString().sprintf ("%04hX", aDevice.GetVendorId()))1475 .arg (QString().sprintf ("%04hX", aDevice.GetProductId()));1476 }1477 else1478 {1479 if (p.toUpper().startsWith (m.toUpper()))1480 sDetails = p;1481 else1482 sDetails = m + " " + p;1483 }1484 ushort r = aDevice.GetRevision();1485 if (r != 0)1486 sDetails += QString().sprintf (" [%04hX]", r);1487 }1488 1489 return sDetails.trimmed();1490 }1491 1492 /**1493 * Returns the multi-line description of the given USB device.1494 */1495 QString VBoxGlobal::toolTip (const CUSBDevice &aDevice) const1496 {1497 QString tip =1498 tr ("<nobr>Vendor ID: %1</nobr><br>"1499 "<nobr>Product ID: %2</nobr><br>"1500 "<nobr>Revision: %3</nobr>", "USB device tooltip")1501 .arg (QString().sprintf ("%04hX", aDevice.GetVendorId()))1502 .arg (QString().sprintf ("%04hX", aDevice.GetProductId()))1503 .arg (QString().sprintf ("%04hX", aDevice.GetRevision()));1504 1505 QString ser = aDevice.GetSerialNumber();1506 if (!ser.isEmpty())1507 tip += QString (tr ("<br><nobr>Serial No. %1</nobr>", "USB device tooltip"))1508 .arg (ser);1509 1510 /* add the state field if it's a host USB device */1511 CHostUSBDevice hostDev (aDevice);1512 if (!hostDev.isNull())1513 {1514 tip += QString (tr ("<br><nobr>State: %1</nobr>", "USB device tooltip"))1515 .arg (vboxGlobal().toString (hostDev.GetState()));1516 }1517 1518 return tip;1519 }1520 1521 /**1522 * Returns the multi-line description of the given USB filter1523 */1524 QString VBoxGlobal::toolTip (const CUSBDeviceFilter &aFilter) const1525 {1526 QString tip;1527 1528 QString vendorId = aFilter.GetVendorId();1529 if (!vendorId.isEmpty())1530 tip += tr ("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip")1531 .arg (vendorId);1532 1533 QString productId = aFilter.GetProductId();1534 if (!productId.isEmpty())1535 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product ID: %2</nobr>", "USB filter tooltip")1536 .arg (productId);1537 1538 QString revision = aFilter.GetRevision();1539 if (!revision.isEmpty())1540 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Revision: %3</nobr>", "USB filter tooltip")1541 .arg (revision);1542 1543 QString product = aFilter.GetProduct();1544 if (!product.isEmpty())1545 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product: %4</nobr>", "USB filter tooltip")1546 .arg (product);1547 1548 QString manufacturer = aFilter.GetManufacturer();1549 if (!manufacturer.isEmpty())1550 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip")1551 .arg (manufacturer);1552 1553 QString serial = aFilter.GetSerialNumber();1554 if (!serial.isEmpty())1555 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Serial No.: %1</nobr>", "USB filter tooltip")1556 .arg (serial);1557 1558 QString port = aFilter.GetPort();1559 if (!port.isEmpty())1560 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Port: %1</nobr>", "USB filter tooltip")1561 .arg (port);1562 1563 /* add the state field if it's a host USB device */1564 CHostUSBDevice hostDev (aFilter);1565 if (!hostDev.isNull())1566 {1567 tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>State: %1</nobr>", "USB filter tooltip")1568 .arg (vboxGlobal().toString (hostDev.GetState()));1569 }1570 1571 return tip;1572 }1573 1574 /**1575 * Returns a details report on a given VM represented as a HTML table.1576 *1577 * @param aMachine Machine to create a report for.1578 * @param aWithLinks @c true if section titles should be hypertext links.1579 */1580 QString VBoxGlobal::detailsReport (const CMachine &aMachine, bool aWithLinks)1581 {1582 /* Details templates */1583 static const char *sTableTpl =1584 "<table border=0 cellspacing=1 cellpadding=0>%1</table>";1585 static const char *sSectionHrefTpl =1586 "<tr><td width=22 rowspan=%1 align=left><img src='%2'></td>"1587 "<td colspan=3><b><a href='%3'><nobr>%4</nobr></a></b></td></tr>"1588 "%5"1589 "<tr><td colspan=3><font size=1> </font></td></tr>";1590 static const char *sSectionBoldTpl =1591 "<tr><td width=22 rowspan=%1 align=left><img src='%2'></td>"1592 "<td colspan=3><!-- %3 --><b><nobr>%4</nobr></b></td></tr>"1593 "%5"1594 "<tr><td colspan=3><font size=1> </font></td></tr>";1595 static const char *sSectionItemTpl1 =1596 "<tr><td width=40%><nobr><i>%1</i></nobr></td><td/><td/></tr>";1597 static const char *sSectionItemTpl2 =1598 "<tr><td width=40%><nobr>%1:</nobr></td><td/><td>%2</td></tr>";1599 static const char *sSectionItemTpl3 =1600 "<tr><td width=40%><nobr>%1</nobr></td><td/><td/></tr>";1601 1602 const QString §ionTpl = aWithLinks ? sSectionHrefTpl : sSectionBoldTpl;1603 1604 /* Compose details report */1605 QString report;1606 1607 /* General */1608 {1609 QString item = QString (sSectionItemTpl2).arg (tr ("Name", "details report"),1610 aMachine.GetName())1611 + QString (sSectionItemTpl2).arg (tr ("OS Type", "details report"),1612 vmGuestOSTypeDescription (aMachine.GetOSTypeId()));1613 1614 report += sectionTpl1615 .arg (2 + 2) /* rows */1616 .arg (":/machine_16px.png", /* icon */1617 "#general", /* link */1618 tr ("General", "details report"), /* title */1619 item); /* items */1620 }1621 1622 /* System */1623 {1624 /* BIOS Settings holder */1625 CBIOSSettings biosSettings = aMachine.GetBIOSSettings();1626 1627 /* System details row count: */1628 int iRowCount = 2; /* Memory & CPU details rows initially. */1629 1630 /* Boot order */1631 QString bootOrder;1632 for (ulong i = 1; i <= mVBox.GetSystemProperties().GetMaxBootPosition(); ++ i)1633 {1634 KDeviceType device = aMachine.GetBootOrder (i);1635 if (device == KDeviceType_Null)1636 continue;1637 if (!bootOrder.isEmpty())1638 bootOrder += ", ";1639 bootOrder += toString (device);1640 }1641 if (bootOrder.isEmpty())1642 bootOrder = toString (KDeviceType_Null);1643 1644 iRowCount += 1; /* Boot-order row. */1645 1646 #ifdef VBOX_WITH_FULL_DETAILS_REPORT1647 /* ACPI */1648 QString acpi = biosSettings.GetACPIEnabled()1649 ? tr ("Enabled", "details report (ACPI)")1650 : tr ("Disabled", "details report (ACPI)");1651 1652 /* IO APIC */1653 QString ioapic = biosSettings.GetIOAPICEnabled()1654 ? tr ("Enabled", "details report (IO APIC)")1655 : tr ("Disabled", "details report (IO APIC)");1656 1657 /* PAE/NX */1658 QString pae = aMachine.GetCpuProperty(KCpuPropertyType_PAE)1659 ? tr ("Enabled", "details report (PAE/NX)")1660 : tr ("Disabled", "details report (PAE/NX)");1661 1662 iRowCount += 3; /* Full report rows. */1663 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */1664 1665 /* VT-x/AMD-V */1666 QString virt = aMachine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled)1667 ? tr ("Enabled", "details report (VT-x/AMD-V)")1668 : tr ("Disabled", "details report (VT-x/AMD-V)");1669 1670 /* Nested Paging */1671 QString nested = aMachine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging)1672 ? tr ("Enabled", "details report (Nested Paging)")1673 : tr ("Disabled", "details report (Nested Paging)");1674 1675 /* VT-x/AMD-V availability: */1676 bool fVTxAMDVSupported = virtualBox().GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx);1677 1678 if (fVTxAMDVSupported)1679 iRowCount += 2; /* VT-x/AMD-V items. */1680 1681 QString item = QString (sSectionItemTpl2).arg (tr ("Base Memory", "details report"),1682 tr ("<nobr>%1 MB</nobr>", "details report"))1683 .arg (aMachine.GetMemorySize())1684 + QString (sSectionItemTpl2).arg (tr ("Processor(s)", "details report"),1685 tr ("<nobr>%1</nobr>", "details report"))1686 .arg (aMachine.GetCPUCount())1687 + QString (sSectionItemTpl2).arg (tr ("Boot Order", "details report"), bootOrder)1688 #ifdef VBOX_WITH_FULL_DETAILS_REPORT1689 + QString (sSectionItemTpl2).arg (tr ("ACPI", "details report"), acpi)1690 + QString (sSectionItemTpl2).arg (tr ("IO APIC", "details report"), ioapic)1691 + QString (sSectionItemTpl2).arg (tr ("PAE/NX", "details report"), pae)1692 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */1693 ;1694 1695 if (fVTxAMDVSupported)1696 item += QString (sSectionItemTpl2).arg (tr ("VT-x/AMD-V", "details report"), virt)1697 + QString (sSectionItemTpl2).arg (tr ("Nested Paging", "details report"), nested);1698 1699 report += sectionTpl1700 .arg (2 + iRowCount) /* rows */1701 .arg (":/chipset_16px.png", /* icon */1702 "#system", /* link */1703 tr ("System", "details report"), /* title */1704 item); /* items */1705 }1706 1707 /* Display */1708 {1709 /* Rows including section header and footer */1710 int rows = 2;1711 1712 /* Video tab */1713 QString item = QString(sSectionItemTpl2)1714 .arg(tr ("Video Memory", "details report"),1715 tr ("<nobr>%1 MB</nobr>", "details report"))1716 .arg(aMachine.GetVRAMSize());1717 ++rows;1718 1719 int cGuestScreens = aMachine.GetMonitorCount();1720 if (cGuestScreens > 1)1721 {1722 item += QString(sSectionItemTpl2)1723 .arg(tr("Screens", "details report"))1724 .arg(cGuestScreens);1725 ++rows;1726 }1727 1728 QString acc3d = aMachine.GetAccelerate3DEnabled()1729 ? tr ("Enabled", "details report (3D Acceleration)")1730 : tr ("Disabled", "details report (3D Acceleration)");1731 1732 item += QString(sSectionItemTpl2)1733 .arg(tr("3D Acceleration", "details report"), acc3d);1734 ++rows;1735 1736 #ifdef VBOX_WITH_VIDEOHWACCEL1737 QString acc2dVideo = aMachine.GetAccelerate2DVideoEnabled()1738 ? tr ("Enabled", "details report (2D Video Acceleration)")1739 : tr ("Disabled", "details report (2D Video Acceleration)");1740 1741 item += QString (sSectionItemTpl2)1742 .arg (tr ("2D Video Acceleration", "details report"), acc2dVideo);1743 ++ rows;1744 #endif1745 1746 /* VRDP tab */1747 CVRDEServer srv = aMachine.GetVRDEServer();1748 if (!srv.isNull())1749 {1750 if (srv.GetEnabled())1751 item += QString (sSectionItemTpl2)1752 .arg (tr ("Remote Desktop Server Port", "details report (VRDE Server)"))1753 .arg (srv.GetVRDEProperty("TCP/Ports"));1754 else1755 item += QString (sSectionItemTpl2)1756 .arg (tr ("Remote Desktop Server", "details report (VRDE Server)"))1757 .arg (tr ("Disabled", "details report (VRDE Server)"));1758 ++ rows;1759 }1760 1761 report += sectionTpl1762 .arg (rows) /* rows */1763 .arg (":/vrdp_16px.png", /* icon */1764 "#display", /* link */1765 tr ("Display", "details report"), /* title */1766 item); /* items */1767 }1768 1769 /* Storage */1770 {1771 /* Rows including section header and footer */1772 int rows = 2;1773 1774 QString item;1775 1776 /* Iterate over the all machine controllers: */1777 CStorageControllerVector controllers = aMachine.GetStorageControllers();1778 for (int i = 0; i < controllers.size(); ++i)1779 {1780 /* Get current controller: */1781 const CStorageController &controller = controllers[i];1782 /* Add controller information: */1783 item += QString(sSectionItemTpl3).arg(controller.GetName());1784 ++ rows;1785 1786 /* Populate sorted map with attachments information: */1787 QMap<StorageSlot,QString> attachmentsMap;1788 CMediumAttachmentVector attachments = aMachine.GetMediumAttachmentsOfController(controller.GetName());1789 for (int j = 0; j < attachments.size(); ++j)1790 {1791 /* Get current attachment: */1792 const CMediumAttachment &attachment = attachments[j];1793 /* Prepare current storage slot: */1794 StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice());1795 /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */1796 QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString();1797 if (!strDeviceType.isNull())1798 strDeviceType.prepend(' ');1799 /* Prepare current medium object: */1800 const CMedium &medium = attachment.GetMedium();1801 /* Prepare information about current medium & attachment: */1802 QString strAttachmentInfo = !attachment.isOk() ? QString() :1803 QString(sSectionItemTpl2)1804 .arg(QString(" ") +1805 toString(StorageSlot(controller.GetBus(),1806 attachment.GetPort(),1807 attachment.GetDevice())) + strDeviceType)1808 .arg(details(medium, false));1809 /* Insert that attachment into map: */1810 if (!strAttachmentInfo.isNull())1811 attachmentsMap.insert(attachmentSlot, strAttachmentInfo);1812 }1813 1814 /* Iterate over the sorted map with attachments information: */1815 QMapIterator<StorageSlot,QString> it(attachmentsMap);1816 while (it.hasNext())1817 {1818 /* Add controller information: */1819 it.next();1820 item += it.value();1821 ++rows;1822 }1823 }1824 1825 if (item.isNull())1826 {1827 item = QString (sSectionItemTpl1)1828 .arg (tr ("Not Attached", "details report (Storage)"));1829 ++ rows;1830 }1831 1832 report += sectionTpl1833 .arg (rows) /* rows */1834 .arg (":/attachment_16px.png", /* icon */1835 "#storage", /* link */1836 tr ("Storage", "details report"), /* title */1837 item); /* items */1838 }1839 1840 /* Audio */1841 {1842 QString item;1843 1844 CAudioAdapter audio = aMachine.GetAudioAdapter();1845 int rows = audio.GetEnabled() ? 3 : 2;1846 if (audio.GetEnabled())1847 item = QString (sSectionItemTpl2)1848 .arg (tr ("Host Driver", "details report (audio)"),1849 toString (audio.GetAudioDriver())) +1850 QString (sSectionItemTpl2)1851 .arg (tr ("Controller", "details report (audio)"),1852 toString (audio.GetAudioController()));1853 else1854 item = QString (sSectionItemTpl1)1855 .arg (tr ("Disabled", "details report (audio)"));1856 1857 report += sectionTpl1858 .arg (rows + 1) /* rows */1859 .arg (":/sound_16px.png", /* icon */1860 "#audio", /* link */1861 tr ("Audio", "details report"), /* title */1862 item); /* items */1863 }1864 1865 /* Network */1866 {1867 QString item;1868 1869 ulong count = mVBox.GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);1870 int rows = 2; /* including section header and footer */1871 for (ulong slot = 0; slot < count; slot ++)1872 {1873 CNetworkAdapter adapter = aMachine.GetNetworkAdapter (slot);1874 if (adapter.GetEnabled())1875 {1876 KNetworkAttachmentType type = adapter.GetAttachmentType();1877 QString attType = toString (adapter.GetAdapterType())1878 .replace (QRegExp ("\\s\\(.+\\)"), " (%1)");1879 /* don't use the adapter type string for types that have1880 * an additional symbolic network/interface name field, use1881 * this name instead */1882 if (type == KNetworkAttachmentType_Bridged)1883 attType = attType.arg (tr ("Bridged adapter, %1",1884 "details report (network)").arg (adapter.GetHostInterface()));1885 else if (type == KNetworkAttachmentType_Internal)1886 attType = attType.arg (tr ("Internal network, '%1'",1887 "details report (network)").arg (adapter.GetInternalNetwork()));1888 else if (type == KNetworkAttachmentType_HostOnly)1889 attType = attType.arg (tr ("Host-only adapter, '%1'",1890 "details report (network)").arg (adapter.GetHostInterface()));1891 #ifdef VBOX_WITH_VDE1892 else if (type == KNetworkAttachmentType_VDE)1893 attType = attType.arg (tr ("VDE network, '%1'",1894 "details report (network)").arg (adapter.GetVDENetwork()));1895 #endif1896 else1897 attType = attType.arg (vboxGlobal().toString (type));1898 1899 item += QString (sSectionItemTpl2)1900 .arg (tr ("Adapter %1", "details report (network)")1901 .arg (adapter.GetSlot() + 1))1902 .arg (attType);1903 ++ rows;1904 }1905 }1906 if (item.isNull())1907 {1908 item = QString (sSectionItemTpl1)1909 .arg (tr ("Disabled", "details report (network)"));1910 ++ rows;1911 }1912 1913 report += sectionTpl1914 .arg (rows) /* rows */1915 .arg (":/nw_16px.png", /* icon */1916 "#network", /* link */1917 tr ("Network", "details report"), /* title */1918 item); /* items */1919 }1920 1921 /* Serial Ports */1922 {1923 QString item;1924 1925 ulong count = mVBox.GetSystemProperties().GetSerialPortCount();1926 int rows = 2; /* including section header and footer */1927 for (ulong slot = 0; slot < count; slot ++)1928 {1929 CSerialPort port = aMachine.GetSerialPort (slot);1930 if (port.GetEnabled())1931 {1932 KPortMode mode = port.GetHostMode();1933 QString data =1934 toCOMPortName (port.GetIRQ(), port.GetIOBase()) + ", ";1935 if (mode == KPortMode_HostPipe ||1936 mode == KPortMode_HostDevice ||1937 mode == KPortMode_RawFile)1938 data += QString ("%1 (<nobr>%2</nobr>)")1939 .arg (vboxGlobal().toString (mode))1940 .arg (QDir::toNativeSeparators (port.GetPath()));1941 else1942 data += toString (mode);1943 1944 item += QString (sSectionItemTpl2)1945 .arg (tr ("Port %1", "details report (serial ports)")1946 .arg (port.GetSlot() + 1))1947 .arg (data);1948 ++ rows;1949 }1950 }1951 if (item.isNull())1952 {1953 item = QString (sSectionItemTpl1)1954 .arg (tr ("Disabled", "details report (serial ports)"));1955 ++ rows;1956 }1957 1958 report += sectionTpl1959 .arg (rows) /* rows */1960 .arg (":/serial_port_16px.png", /* icon */1961 "#serialPorts", /* link */1962 tr ("Serial Ports", "details report"), /* title */1963 item); /* items */1964 }1965 1966 /* Parallel Ports */1967 {1968 QString item;1969 1970 ulong count = mVBox.GetSystemProperties().GetParallelPortCount();1971 int rows = 2; /* including section header and footer */1972 for (ulong slot = 0; slot < count; slot ++)1973 {1974 CParallelPort port = aMachine.GetParallelPort (slot);1975 if (port.GetEnabled())1976 {1977 QString data =1978 toLPTPortName (port.GetIRQ(), port.GetIOBase()) +1979 QString (" (<nobr>%1</nobr>)")1980 .arg (QDir::toNativeSeparators (port.GetPath()));1981 1982 item += QString (sSectionItemTpl2)1983 .arg (tr ("Port %1", "details report (parallel ports)")1984 .arg (port.GetSlot() + 1))1985 .arg (data);1986 ++ rows;1987 }1988 }1989 if (item.isNull())1990 {1991 item = QString (sSectionItemTpl1)1992 .arg (tr ("Disabled", "details report (parallel ports)"));1993 ++ rows;1994 }1995 1996 /* Temporary disabled */1997 QString dummy = sectionTpl /* report += sectionTpl */1998 .arg (rows) /* rows */1999 .arg (":/parallel_port_16px.png", /* icon */2000 "#parallelPorts", /* link */2001 tr ("Parallel Ports", "details report"), /* title */2002 item); /* items */2003 }2004 2005 /* USB */2006 {2007 QString item;2008 2009 CUSBController ctl = aMachine.GetUSBController();2010 if ( !ctl.isNull()2011 && ctl.GetProxyAvailable())2012 {2013 /* the USB controller may be unavailable (i.e. in VirtualBox OSE) */2014 2015 if (ctl.GetEnabled())2016 {2017 CUSBDeviceFilterVector coll = ctl.GetDeviceFilters();2018 uint active = 0;2019 for (int i = 0; i < coll.size(); ++i)2020 if (coll[i].GetActive())2021 active ++;2022 2023 item = QString (sSectionItemTpl2)2024 .arg (tr ("Device Filters", "details report (USB)"),2025 tr ("%1 (%2 active)", "details report (USB)")2026 .arg (coll.size()).arg (active));2027 }2028 else2029 item = QString (sSectionItemTpl1)2030 .arg (tr ("Disabled", "details report (USB)"));2031 2032 report += sectionTpl2033 .arg (2 + 1) /* rows */2034 .arg (":/usb_16px.png", /* icon */2035 "#usb", /* link */2036 tr ("USB", "details report"), /* title */2037 item); /* items */2038 }2039 }2040 2041 /* Shared Folders */2042 {2043 QString item;2044 2045 ulong count = aMachine.GetSharedFolders().size();2046 if (count > 0)2047 {2048 item = QString (sSectionItemTpl2)2049 .arg (tr ("Shared Folders", "details report (shared folders)"))2050 .arg (count);2051 }2052 else2053 item = QString (sSectionItemTpl1)2054 .arg (tr ("None", "details report (shared folders)"));2055 2056 report += sectionTpl2057 .arg (2 + 1) /* rows */2058 .arg (":/shared_folder_16px.png", /* icon */2059 "#sfolders", /* link */2060 tr ("Shared Folders", "details report"), /* title */2061 item); /* items */2062 }2063 2064 return QString (sTableTpl). arg (report);2065 }2066 2067 QString VBoxGlobal::platformInfo()2068 {2069 QString platform;2070 2071 #if defined (Q_OS_WIN)2072 platform = "win";2073 #elif defined (Q_OS_LINUX)2074 platform = "linux";2075 #elif defined (Q_OS_MACX)2076 platform = "macosx";2077 #elif defined (Q_OS_OS2)2078 platform = "os2";2079 #elif defined (Q_OS_FREEBSD)2080 platform = "freebsd";2081 #elif defined (Q_OS_SOLARIS)2082 platform = "solaris";2083 #else2084 platform = "unknown";2085 #endif2086 2087 /* The format is <system>.<bitness> */2088 platform += QString (".%1").arg (ARCH_BITS);2089 2090 /* Add more system information */2091 #if defined (Q_OS_WIN)2092 OSVERSIONINFO versionInfo;2093 ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));2094 versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);2095 GetVersionEx (&versionInfo);2096 int major = versionInfo.dwMajorVersion;2097 int minor = versionInfo.dwMinorVersion;2098 int build = versionInfo.dwBuildNumber;2099 QString sp = QString::fromUtf16 ((ushort*)versionInfo.szCSDVersion);2100 2101 QString distrib;2102 if (major == 6)2103 distrib = QString ("Windows Vista %1");2104 else if (major == 5)2105 {2106 if (minor == 2)2107 distrib = QString ("Windows Server 2003 %1");2108 else if (minor == 1)2109 distrib = QString ("Windows XP %1");2110 else if (minor == 0)2111 distrib = QString ("Windows 2000 %1");2112 else2113 distrib = QString ("Unknown %1");2114 }2115 else if (major == 4)2116 {2117 if (minor == 90)2118 distrib = QString ("Windows Me %1");2119 else if (minor == 10)2120 distrib = QString ("Windows 98 %1");2121 else if (minor == 0)2122 distrib = QString ("Windows 95 %1");2123 else2124 distrib = QString ("Unknown %1");2125 }2126 else /** @todo Windows Server 2008 == vista? Probably not... */2127 distrib = QString ("Unknown %1");2128 distrib = distrib.arg (sp);2129 QString version = QString ("%1.%2").arg (major).arg (minor);2130 QString kernel = QString ("%1").arg (build);2131 platform += QString (" [Distribution: %1 | Version: %2 | Build: %3]")2132 .arg (distrib).arg (version).arg (kernel);2133 #elif defined (Q_OS_LINUX)2134 /* Get script path */2135 char szAppPrivPath [RTPATH_MAX];2136 int rc = RTPathAppPrivateNoArch (szAppPrivPath, sizeof (szAppPrivPath)); NOREF(rc);2137 AssertRC (rc);2138 /* Run script */2139 QByteArray result =2140 Process::singleShot (QString (szAppPrivPath) + "/VBoxSysInfo.sh");2141 if (!result.isNull())2142 platform += QString (" [%1]").arg (QString (result).trimmed());2143 #else2144 /* Use RTSystemQueryOSInfo. */2145 char szTmp[256];2146 QStringList components;2147 int vrc = RTSystemQueryOSInfo (RTSYSOSINFO_PRODUCT, szTmp, sizeof (szTmp));2148 if ((RT_SUCCESS (vrc) || vrc == VERR_BUFFER_OVERFLOW) && szTmp[0] != '\0')2149 components << QString ("Product: %1").arg (szTmp);2150 vrc = RTSystemQueryOSInfo (RTSYSOSINFO_RELEASE, szTmp, sizeof (szTmp));2151 if ((RT_SUCCESS (vrc) || vrc == VERR_BUFFER_OVERFLOW) && szTmp[0] != '\0')2152 components << QString ("Release: %1").arg (szTmp);2153 vrc = RTSystemQueryOSInfo (RTSYSOSINFO_VERSION, szTmp, sizeof (szTmp));2154 if ((RT_SUCCESS (vrc) || vrc == VERR_BUFFER_OVERFLOW) && szTmp[0] != '\0')2155 components << QString ("Version: %1").arg (szTmp);2156 vrc = RTSystemQueryOSInfo (RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof (szTmp));2157 if ((RT_SUCCESS (vrc) || vrc == VERR_BUFFER_OVERFLOW) && szTmp[0] != '\0')2158 components << QString ("SP: %1").arg (szTmp);2159 if (!components.isEmpty())2160 platform += QString (" [%1]").arg (components.join (" | "));2161 #endif2162 2163 return platform;2164 }2165 2166 #if defined(Q_WS_X11) && !defined(VBOX_OSE)2167 double VBoxGlobal::findLicenseFile (const QStringList &aFilesList, QRegExp aPattern, QString &aLicenseFile) const2168 {2169 double maxVersionNumber = 0;2170 aLicenseFile = "";2171 for (int index = 0; index < aFilesList.count(); ++ index)2172 {2173 aPattern.indexIn (aFilesList [index]);2174 QString version = aPattern.cap (1);2175 if (maxVersionNumber < version.toDouble())2176 {2177 maxVersionNumber = version.toDouble();2178 aLicenseFile = aFilesList [index];2179 }2180 }2181 return maxVersionNumber;2182 }2183 2184 bool VBoxGlobal::showVirtualBoxLicense()2185 {2186 /* get the apps doc path */2187 int size = 256;2188 char *buffer = (char*) RTMemTmpAlloc (size);2189 RTPathAppDocs (buffer, size);2190 QString path (buffer);2191 RTMemTmpFree (buffer);2192 QDir docDir (path);2193 docDir.setFilter (QDir::Files);2194 docDir.setNameFilters (QStringList ("License-*.html"));2195 2196 /* Make sure that the language is in two letter code.2197 * Note: if languageId() returns an empty string lang.name() will2198 * return "C" which is an valid language code. */2199 QLocale lang (VBoxGlobal::languageId());2200 2201 QStringList filesList = docDir.entryList();2202 QString licenseFile;2203 /* First try to find a localized version of the license file. */2204 double versionNumber = findLicenseFile (filesList, QRegExp (QString ("License-([\\d\\.]+)-%1.html").arg (lang.name())), licenseFile);2205 /* If there wasn't a localized version of the currently selected language,2206 * search for the generic one. */2207 if (versionNumber == 0)2208 versionNumber = findLicenseFile (filesList, QRegExp ("License-([\\d\\.]+).html"), licenseFile);2209 /* Check the version again. */2210 if (!versionNumber)2211 {2212 vboxProblem().cannotFindLicenseFiles (path);2213 return false;2214 }2215 2216 /* compose the latest license file full path */2217 QString latestVersion = QString::number (versionNumber);2218 QString latestFilePath = docDir.absoluteFilePath (licenseFile);2219 2220 /* check for the agreed license version */2221 QStringList strList = virtualBox().GetExtraData (VBoxDefs::GUI_LicenseKey).split(",");2222 for (int i=0; i < strList.size(); ++i)2223 if (strList.at(i) == latestVersion)2224 return true;2225 2226 VBoxLicenseViewer licenseDialog;2227 bool result = licenseDialog.showLicenseFromFile(latestFilePath) == QDialog::Accepted;2228 if (result)2229 virtualBox().SetExtraData (VBoxDefs::GUI_LicenseKey, (strList << latestVersion).join(","));2230 return result;2231 }2232 #endif /* defined(Q_WS_X11) && !defined(VBOX_OSE) */2233 2234 /**2235 * Opens a direct session for a machine with the given ID.2236 * This method does user-friendly error handling (display error messages, etc.).2237 * and returns a null CSession object in case of any error.2238 * If this method succeeds, don't forget to close the returned session when2239 * it is no more necessary.2240 *2241 * @param aId Machine ID.2242 * @param aExisting @c true to open an existing session with the machine2243 * which is already running, @c false to open a new direct2244 * session.2245 */2246 CSession VBoxGlobal::openSession(const QString &aId, bool aExisting /* = false */)2247 {2248 CSession session;2249 session.createInstance(CLSID_Session);2250 if (session.isNull())2251 {2252 vboxProblem().cannotOpenSession (session);2253 return session;2254 }2255 2256 CMachine foundMachine = CVirtualBox(mVBox).FindMachine(aId);2257 if (!foundMachine.isNull())2258 {2259 foundMachine.LockMachine(session,2260 (aExisting) ? KLockType_Shared : KLockType_Write);2261 if (session.GetType() == KSessionType_Shared)2262 {2263 CMachine machine = session.GetMachine();2264 /* Make sure that the language is in two letter code.2265 * Note: if languageId() returns an empty string lang.name() will2266 * return "C" which is an valid language code. */2267 QLocale lang(VBoxGlobal::languageId());2268 machine.SetGuestPropertyValue ("/VirtualBox/HostInfo/GUI/LanguageID", lang.name());2269 }2270 }2271 2272 if (!mVBox.isOk())2273 {2274 vboxProblem().cannotOpenSession(mVBox, foundMachine);2275 session.detach();2276 }2277 2278 return session;2279 }2280 2281 /**2282 * Starts a machine with the given ID.2283 */2284 bool VBoxGlobal::startMachine(const QString &strId)2285 {2286 AssertReturn(mValid, false);2287 2288 CSession session = vboxGlobal().openSession(strId);2289 if (session.isNull())2290 return false;2291 2292 return createVirtualMachine(session);2293 }2294 2295 /**2296 * Appends the NULL medium to the media list.2297 * For using with VBoxGlobal::startEnumeratingMedia() only.2298 */2299 static void addNullMediumToList (VBoxMediaList &aList, VBoxMediaList::iterator aWhere)2300 {2301 VBoxMedium medium;2302 aList.insert (aWhere, medium);2303 }2304 2305 /**2306 * Appends the given list of mediums to the media list.2307 * For using with VBoxGlobal::startEnumeratingMedia() only.2308 */2309 static void addMediumsToList (const CMediumVector &aVector,2310 VBoxMediaList &aList,2311 VBoxMediaList::iterator aWhere,2312 VBoxDefs::MediumType aType,2313 VBoxMedium *aParent = 0)2314 {2315 VBoxMediaList::iterator first = aWhere;2316 2317 for (CMediumVector::ConstIterator it = aVector.begin(); it != aVector.end(); ++ it)2318 {2319 CMedium cmedium (*it);2320 VBoxMedium medium (cmedium, aType, aParent);2321 2322 /* Search for a proper alphabetic position */2323 VBoxMediaList::iterator jt = first;2324 for (; jt != aWhere; ++ jt)2325 if ((*jt).name().localeAwareCompare (medium.name()) > 0)2326 break;2327 2328 aList.insert (jt, medium);2329 2330 /* Adjust the first item if inserted before it */2331 if (jt == first)2332 -- first;2333 }2334 }2335 2336 /**2337 * Appends the given list of hard disks and all their children to the media list.2338 * For using with VBoxGlobal::startEnumeratingMedia() only.2339 */2340 static void addHardDisksToList (const CMediumVector &aVector,2341 VBoxMediaList &aList,2342 VBoxMediaList::iterator aWhere,2343 VBoxMedium *aParent = 0)2344 {2345 VBoxMediaList::iterator first = aWhere;2346 2347 /* First pass: Add siblings sorted */2348 for (CMediumVector::ConstIterator it = aVector.begin(); it != aVector.end(); ++ it)2349 {2350 CMedium cmedium (*it);2351 VBoxMedium medium (cmedium, VBoxDefs::MediumType_HardDisk, aParent);2352 2353 /* Search for a proper alphabetic position */2354 VBoxMediaList::iterator jt = first;2355 for (; jt != aWhere; ++ jt)2356 if ((*jt).name().localeAwareCompare (medium.name()) > 0)2357 break;2358 2359 aList.insert (jt, medium);2360 2361 /* Adjust the first item if inserted before it */2362 if (jt == first)2363 -- first;2364 }2365 2366 /* Second pass: Add children */2367 for (VBoxMediaList::iterator it = first; it != aWhere;)2368 {2369 CMediumVector children = (*it).medium().GetChildren();2370 VBoxMedium *parent = &(*it);2371 2372 ++ it; /* go to the next sibling before inserting children */2373 addHardDisksToList (children, aList, it, parent);2374 }2375 }2376 2377 /**2378 * Starts a thread that asynchronously enumerates all currently registered2379 * media.2380 *2381 * Before the enumeration is started, the current media list (a list returned by2382 * #currentMediaList()) is populated with all registered media and the2383 * #mediumEnumStarted() signal is emitted. The enumeration thread then walks this2384 * list, checks for media accessibility and emits #mediumEnumerated() signals of2385 * each checked medium. When all media are checked, the enumeration thread is2386 * stopped and the #mediumEnumFinished() signal is emitted.2387 *2388 * If the enumeration is already in progress, no new thread is started.2389 *2390 * The media list returned by #currentMediaList() is always sorted2391 * alphabetically by the location attribute and comes in the following order:2392 * <ol>2393 * <li>All hard disks. If a hard disk has children, these children2394 * (alphabetically sorted) immediately follow their parent and therefore2395 * appear before its next sibling hard disk.</li>2396 * <li>All CD/DVD images.</li>2397 * <li>All Floppy images.</li>2398 * </ol>2399 *2400 * Note that #mediumEnumerated() signals are emitted in the same order as2401 * described above.2402 *2403 * @sa #currentMediaList()2404 * @sa #isMediaEnumerationStarted()2405 */2406 void VBoxGlobal::startEnumeratingMedia()2407 {2408 AssertReturnVoid (mValid);2409 2410 /* check if already started but not yet finished */2411 if (mMediaEnumThread != NULL)2412 return;2413 2414 /* ignore the request during application termination */2415 if (sVBoxGlobalInCleanup)2416 return;2417 2418 /* composes a list of all currently known media & their children */2419 mMediaList.clear();2420 addNullMediumToList (mMediaList, mMediaList.end());2421 addHardDisksToList (mVBox.GetHardDisks(), mMediaList, mMediaList.end());2422 addMediumsToList (mVBox.GetHost().GetDVDDrives(), mMediaList, mMediaList.end(), VBoxDefs::MediumType_DVD);2423 addMediumsToList (mVBox.GetDVDImages(), mMediaList, mMediaList.end(), VBoxDefs::MediumType_DVD);2424 addMediumsToList (mVBox.GetHost().GetFloppyDrives(), mMediaList, mMediaList.end(), VBoxDefs::MediumType_Floppy);2425 addMediumsToList (mVBox.GetFloppyImages(), mMediaList, mMediaList.end(), VBoxDefs::MediumType_Floppy);2426 2427 /* enumeration thread class */2428 class MediaEnumThread : public QThread2429 {2430 public:2431 2432 MediaEnumThread (VBoxMediaList &aList)2433 : mVector (aList.size())2434 , mSavedIt (aList.begin())2435 {2436 int i = 0;2437 for (VBoxMediaList::const_iterator it = aList.begin();2438 it != aList.end(); ++ it)2439 mVector [i ++] = *it;2440 }2441 2442 virtual void run()2443 {2444 LogFlow (("MediaEnumThread started.\n"));2445 COMBase::InitializeCOM(false);2446 2447 CVirtualBox mVBox = vboxGlobal().virtualBox();2448 QObject *self = &vboxGlobal();2449 2450 /* Enumerate the list */2451 for (int i = 0; i < mVector.size() && !sVBoxGlobalInCleanup; ++ i)2452 {2453 mVector [i].blockAndQueryState();2454 QApplication::2455 postEvent (self,2456 new VBoxMediaEnumEvent (mVector [i], mSavedIt));2457 }2458 2459 /* Post the end-of-enumeration event */2460 if (!sVBoxGlobalInCleanup)2461 QApplication::postEvent (self, new VBoxMediaEnumEvent (mSavedIt));2462 2463 COMBase::CleanupCOM();2464 LogFlow (("MediaEnumThread finished.\n"));2465 }2466 2467 private:2468 2469 QVector <VBoxMedium> mVector;2470 VBoxMediaList::iterator mSavedIt;2471 };2472 2473 mMediaEnumThread = new MediaEnumThread (mMediaList);2474 AssertReturnVoid (mMediaEnumThread);2475 2476 /* emit mediumEnumStarted() after we set mMediaEnumThread to != NULL2477 * to cause isMediaEnumerationStarted() to return TRUE from slots */2478 emit mediumEnumStarted();2479 2480 mMediaEnumThread->start();2481 }2482 2483 VBoxDefs::MediumType VBoxGlobal::mediumTypeToLocal(KDeviceType globalType)2484 {2485 switch (globalType)2486 {2487 case KDeviceType_HardDisk:2488 return VBoxDefs::MediumType_HardDisk;2489 case KDeviceType_DVD:2490 return VBoxDefs::MediumType_DVD;2491 case KDeviceType_Floppy:2492 return VBoxDefs::MediumType_Floppy;2493 default:2494 break;2495 }2496 return VBoxDefs::MediumType_Invalid;2497 }2498 2499 KDeviceType VBoxGlobal::mediumTypeToGlobal(VBoxDefs::MediumType localType)2500 {2501 switch (localType)2502 {2503 case VBoxDefs::MediumType_HardDisk:2504 return KDeviceType_HardDisk;2505 case VBoxDefs::MediumType_DVD:2506 return KDeviceType_DVD;2507 case VBoxDefs::MediumType_Floppy:2508 return KDeviceType_Floppy;2509 default:2510 break;2511 }2512 return KDeviceType_Null;2513 }2514 2515 /**2516 * Adds a new medium to the current media list and emits the #mediumAdded()2517 * signal.2518 *2519 * @sa #currentMediaList()2520 */2521 void VBoxGlobal::addMedium (const VBoxMedium &aMedium)2522 {2523 /* Note that we maintain the same order here as #startEnumeratingMedia() */2524 2525 VBoxMediaList::iterator it = mMediaList.begin();2526 2527 if (aMedium.type() == VBoxDefs::MediumType_HardDisk)2528 {2529 VBoxMediaList::iterator itParent = mMediaList.end();2530 2531 for (; it != mMediaList.end(); ++ it)2532 {2533 /* skip null medium that come first */2534 if ((*it).isNull()) continue;2535 2536 if ((*it).type() != VBoxDefs::MediumType_HardDisk)2537 break;2538 2539 if (aMedium.parent() != NULL && itParent == mMediaList.end())2540 {2541 if (&*it == aMedium.parent())2542 itParent = it;2543 }2544 else2545 {2546 /* break if met a parent's sibling (will insert before it) */2547 if (aMedium.parent() != NULL &&2548 (*it).parent() == (*itParent).parent())2549 break;2550 2551 /* compare to aMedium's siblings */2552 if ((*it).parent() == aMedium.parent() &&2553 (*it).name().localeAwareCompare (aMedium.name()) > 0)2554 break;2555 }2556 }2557 2558 AssertReturnVoid (aMedium.parent() == NULL || itParent != mMediaList.end());2559 }2560 else2561 {2562 for (; it != mMediaList.end(); ++ it)2563 {2564 /* skip null medium that come first */2565 if ((*it).isNull()) continue;2566 2567 /* skip HardDisks that come first */2568 if ((*it).type() == VBoxDefs::MediumType_HardDisk)2569 continue;2570 2571 /* skip DVD when inserting Floppy */2572 if (aMedium.type() == VBoxDefs::MediumType_Floppy &&2573 (*it).type() == VBoxDefs::MediumType_DVD)2574 continue;2575 2576 if ((*it).name().localeAwareCompare (aMedium.name()) > 0 ||2577 (aMedium.type() == VBoxDefs::MediumType_DVD &&2578 (*it).type() == VBoxDefs::MediumType_Floppy))2579 break;2580 }2581 }2582 2583 it = mMediaList.insert (it, aMedium);2584 2585 emit mediumAdded (*it);2586 }2587 2588 /**2589 * Updates the medium in the current media list and emits the #mediumUpdated()2590 * signal.2591 *2592 * @sa #currentMediaList()2593 */2594 void VBoxGlobal::updateMedium (const VBoxMedium &aMedium)2595 {2596 VBoxMediaList::Iterator it;2597 for (it = mMediaList.begin(); it != mMediaList.end(); ++ it)2598 if ((*it).id() == aMedium.id())2599 break;2600 2601 AssertReturnVoid (it != mMediaList.end());2602 2603 if (&*it != &aMedium)2604 *it = aMedium;2605 2606 emit mediumUpdated (*it);2607 }2608 2609 /**2610 * Removes the medium from the current media list and emits the #mediumRemoved()2611 * signal.2612 *2613 * @sa #currentMediaList()2614 */2615 void VBoxGlobal::removeMedium (VBoxDefs::MediumType aType, const QString &aId)2616 {2617 VBoxMediaList::Iterator it;2618 for (it = mMediaList.begin(); it != mMediaList.end(); ++ it)2619 if ((*it).id() == aId)2620 break;2621 2622 AssertReturnVoid (it != mMediaList.end());2623 2624 #if DEBUG2625 /* sanity: must be no children */2626 {2627 VBoxMediaList::Iterator jt = it;2628 ++ jt;2629 AssertReturnVoid (jt == mMediaList.end() || (*jt).parent() != &*it);2630 }2631 #endif2632 2633 VBoxMedium *pParent = (*it).parent();2634 2635 /* remove the medium from the list to keep it in sync with the server "for2636 * free" when the medium is deleted from one of our UIs */2637 mMediaList.erase (it);2638 2639 emit mediumRemoved (aType, aId);2640 2641 /* also emit the parent update signal because some attributes like2642 * isReadOnly() may have been changed after child removal */2643 if (pParent != NULL)2644 {2645 pParent->refresh();2646 emit mediumUpdated (*pParent);2647 }2648 }2649 2650 /**2651 * Searches for a VBoxMedum object representing the given COM medium object.2652 *2653 * @return true if found and false otherwise.2654 */2655 bool VBoxGlobal::findMedium (const CMedium &aObj, VBoxMedium &aMedium) const2656 {2657 for (VBoxMediaList::ConstIterator it = mMediaList.begin(); it != mMediaList.end(); ++ it)2658 {2659 if (((*it).medium().isNull() && aObj.isNull()) ||2660 (!(*it).medium().isNull() && !aObj.isNull() && (*it).medium().GetId() == aObj.GetId()))2661 {2662 aMedium = (*it);2663 return true;2664 }2665 }2666 return false;2667 }2668 2669 /**2670 * Searches for a VBoxMedum object with the given medium id attribute.2671 *2672 * @return VBoxMedum if found which is invalid otherwise.2673 */2674 VBoxMedium VBoxGlobal::findMedium (const QString &aMediumId) const2675 {2676 for (VBoxMediaList::ConstIterator it = mMediaList.begin(); it != mMediaList.end(); ++ it)2677 if ((*it).id() == aMediumId)2678 return *it;2679 return VBoxMedium();2680 }2681 2682 /* Open some external medium using file open dialog2683 * and temporary cache (enumerate) it in GUI inner mediums cache: */2684 QString VBoxGlobal::openMediumWithFileOpenDialog(VBoxDefs::MediumType mediumType, QWidget *pParent,2685 const QString &strDefaultFolder /* = QString() */,2686 bool fUseLastFolder /* = false */)2687 {2688 /* Initialize variables: */2689 QList < QPair <QString, QString> > filters;2690 QStringList backends;2691 QStringList prefixes;2692 QString strFilter;2693 QString strTitle;2694 QString allType;2695 QString strLastFolder;2696 switch (mediumType)2697 {2698 case VBoxDefs::MediumType_HardDisk:2699 {2700 filters = vboxGlobal().HDDBackends();2701 strTitle = tr ("Choose a virtual hard disk file");2702 allType = tr ("hard disk");2703 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderHD);2704 if (strLastFolder.isEmpty())2705 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderCD);2706 if (strLastFolder.isEmpty())2707 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderFD);2708 break;2709 }2710 case VBoxDefs::MediumType_DVD:2711 {2712 filters = vboxGlobal().DVDBackends();2713 strTitle = tr ("Choose a virtual CD/DVD disk file");2714 allType = tr ("CD/DVD-ROM disk");2715 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderCD);2716 if (strLastFolder.isEmpty())2717 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderHD);2718 if (strLastFolder.isEmpty())2719 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderFD);2720 break;2721 }2722 case VBoxDefs::MediumType_Floppy:2723 {2724 filters = vboxGlobal().FloppyBackends();2725 strTitle = tr ("Choose a virtual floppy disk file");2726 allType = tr ("floppy disk");2727 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderFD);2728 if (strLastFolder.isEmpty())2729 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderCD);2730 if (strLastFolder.isEmpty())2731 strLastFolder = virtualBox().GetExtraData(VBoxDefs::GUI_RecentFolderHD);2732 break;2733 }2734 default:2735 break;2736 }2737 QString strHomeFolder = fUseLastFolder && !strLastFolder.isEmpty() ? strLastFolder :2738 strDefaultFolder.isEmpty() ? vboxGlobal().virtualBox().GetHomeFolder() : strDefaultFolder;2739 2740 /* Prepare filters and backends: */2741 for (int i = 0; i < filters.count(); ++i)2742 {2743 /* Get iterated filter: */2744 QPair <QString, QString> item = filters.at(i);2745 /* Create one backend filter string: */2746 backends << QString("%1 (%2)").arg(item.first).arg(item.second);2747 /* Save the suffix's for the "All" entry: */2748 prefixes << item.second;2749 }2750 if (!prefixes.isEmpty())2751 backends.insert(0, tr("All %1 images (%2)").arg(allType).arg(prefixes.join(" ").trimmed()));2752 backends << tr("All files (*)");2753 strFilter = backends.join(";;").trimmed();2754 2755 /* Create open file dialog: */2756 QStringList files = QIFileDialog::getOpenFileNames(strHomeFolder, strFilter, pParent, strTitle, 0, true, true);2757 2758 /* If dialog has some result: */2759 if (!files.empty() && !files[0].isEmpty())2760 return openMedium(mediumType, files[0], pParent);2761 2762 return QString();2763 }2764 2765 QString VBoxGlobal::openMedium(VBoxDefs::MediumType mediumType, QString strMediumLocation, QWidget *pParent /* = 0*/)2766 {2767 /* Convert to native separators: */2768 strMediumLocation = QDir::toNativeSeparators(strMediumLocation);2769 2770 /* Initialize variables: */2771 CVirtualBox vbox = vboxGlobal().virtualBox();2772 2773 /* Remember the path of the last chosen medium: */2774 QString strRecentFolderKey = mediumType == VBoxDefs::MediumType_HardDisk ? VBoxDefs::GUI_RecentFolderHD :2775 mediumType == VBoxDefs::MediumType_DVD ? VBoxDefs::GUI_RecentFolderCD :2776 mediumType == VBoxDefs::MediumType_Floppy ? VBoxDefs::GUI_RecentFolderFD :2777 QString();2778 vbox.SetExtraData(strRecentFolderKey, QFileInfo(strMediumLocation).absolutePath());2779 2780 /* Update recently used list: */2781 QString strRecentListKey = mediumType == VBoxDefs::MediumType_HardDisk ? VBoxDefs::GUI_RecentListHD :2782 mediumType == VBoxDefs::MediumType_DVD ? VBoxDefs::GUI_RecentListCD :2783 mediumType == VBoxDefs::MediumType_Floppy ? VBoxDefs::GUI_RecentListFD :2784 QString();2785 QStringList recentMediumList = vbox.GetExtraData(strRecentListKey).split(';');2786 if (recentMediumList.contains(strMediumLocation))2787 recentMediumList.removeAll(strMediumLocation);2788 recentMediumList.prepend(strMediumLocation);2789 while(recentMediumList.size() > 5) recentMediumList.removeLast();2790 vbox.SetExtraData(strRecentListKey, recentMediumList.join(";"));2791 2792 /* Open corresponding medium: */2793 CMedium comMedium = vbox.OpenMedium(strMediumLocation, mediumTypeToGlobal(mediumType), KAccessMode_ReadWrite);2794 2795 if (vbox.isOk())2796 {2797 /* Prepare vbox medium wrapper: */2798 VBoxMedium vboxMedium;2799 2800 /* First of all we should test if that medium already opened: */2801 if (!vboxGlobal().findMedium(comMedium, vboxMedium))2802 {2803 /* And create new otherwise: */2804 vboxMedium = VBoxMedium(CMedium(comMedium), mediumType, KMediumState_Created);2805 vboxGlobal().addMedium(vboxMedium);2806 }2807 2808 /* Return vboxMedium id: */2809 return vboxMedium.id();2810 }2811 else2812 vboxProblem().cannotOpenMedium(pParent, vbox, mediumType, strMediumLocation);2813 2814 return QString();2815 }2816 2817 #ifdef VBOX_GUI_WITH_SYSTRAY2818 /**2819 * Returns the number of current running Fe/Qt4 main windows.2820 *2821 * @return Number of running main windows.2822 */2823 int VBoxGlobal::mainWindowCount ()2824 {2825 return mVBox.GetExtraData (VBoxDefs::GUI_MainWindowCount).toInt();2826 }2827 #endif2828 2829 /**2830 * Native language name of the currently installed translation.2831 * Returns "English" if no translation is installed2832 * or if the translation file is invalid.2833 */2834 QString VBoxGlobal::languageName() const2835 {2836 2837 return qApp->translate ("@@@", "English",2838 "Native language name");2839 }2840 2841 /**2842 * Native language country name of the currently installed translation.2843 * Returns "--" if no translation is installed or if the translation file is2844 * invalid, or if the language is independent on the country.2845 */2846 QString VBoxGlobal::languageCountry() const2847 {2848 return qApp->translate ("@@@", "--",2849 "Native language country name "2850 "(empty if this language is for all countries)");2851 }2852 2853 /**2854 * Language name of the currently installed translation, in English.2855 * Returns "English" if no translation is installed2856 * or if the translation file is invalid.2857 */2858 QString VBoxGlobal::languageNameEnglish() const2859 {2860 2861 return qApp->translate ("@@@", "English",2862 "Language name, in English");2863 }2864 2865 /**2866 * Language country name of the currently installed translation, in English.2867 * Returns "--" if no translation is installed or if the translation file is2868 * invalid, or if the language is independent on the country.2869 */2870 QString VBoxGlobal::languageCountryEnglish() const2871 {2872 return qApp->translate ("@@@", "--",2873 "Language country name, in English "2874 "(empty if native country name is empty)");2875 }2876 2877 /**2878 * Comma-separated list of authors of the currently installed translation.2879 * Returns "Oracle Corporation" if no translation is installed or if the2880 * translation file is invalid, or if the translation is supplied by Oracle2881 * Corporation2882 */2883 QString VBoxGlobal::languageTranslators() const2884 {2885 return qApp->translate ("@@@", "Oracle Corporation",2886 "Comma-separated list of translators");2887 }2888 2889 /**2890 * Changes the language of all global string constants according to the2891 * currently installed translations tables.2892 */2893 void VBoxGlobal::retranslateUi()2894 {2895 mMachineStates [KMachineState_PoweredOff] = tr ("Powered Off", "MachineState");2896 mMachineStates [KMachineState_Saved] = tr ("Saved", "MachineState");2897 mMachineStates [KMachineState_Teleported] = tr ("Teleported", "MachineState");2898 mMachineStates [KMachineState_Aborted] = tr ("Aborted", "MachineState");2899 mMachineStates [KMachineState_Running] = tr ("Running", "MachineState");2900 mMachineStates [KMachineState_Paused] = tr ("Paused", "MachineState");2901 mMachineStates [KMachineState_Stuck] = tr ("Guru Meditation", "MachineState");2902 mMachineStates [KMachineState_Teleporting] = tr ("Teleporting", "MachineState");2903 mMachineStates [KMachineState_LiveSnapshotting] = tr ("Taking Live Snapshot", "MachineState");2904 mMachineStates [KMachineState_Starting] = tr ("Starting", "MachineState");2905 mMachineStates [KMachineState_Stopping] = tr ("Stopping", "MachineState");2906 mMachineStates [KMachineState_Saving] = tr ("Saving", "MachineState");2907 mMachineStates [KMachineState_Restoring] = tr ("Restoring", "MachineState");2908 mMachineStates [KMachineState_TeleportingPausedVM] = tr ("Teleporting Paused VM", "MachineState");2909 mMachineStates [KMachineState_TeleportingIn] = tr ("Teleporting", "MachineState");2910 mMachineStates [KMachineState_RestoringSnapshot] = tr ("Restoring Snapshot", "MachineState");2911 mMachineStates [KMachineState_DeletingSnapshot] = tr ("Deleting Snapshot", "MachineState");2912 mMachineStates [KMachineState_DeletingSnapshotOnline] = tr ("Deleting Snapshot", "MachineState");2913 mMachineStates [KMachineState_DeletingSnapshotPaused] = tr ("Deleting Snapshot", "MachineState");2914 mMachineStates [KMachineState_SettingUp] = tr ("Setting Up", "MachineState");2915 mMachineStates [KMachineState_FaultTolerantSyncing] = tr ("Fault Tolerant Syncing", "MachineState");2916 2917 mSessionStates [KSessionState_Unlocked] = tr ("Unlocked", "SessionState");2918 mSessionStates [KSessionState_Locked] = tr ("Locked", "SessionState");2919 mSessionStates [KSessionState_Spawning] = tr ("Spawning", "SessionState");2920 mSessionStates [KSessionState_Unlocking] = tr ("Unlocking", "SessionState");2921 2922 mDeviceTypes [KDeviceType_Null] = tr ("None", "DeviceType");2923 mDeviceTypes [KDeviceType_Floppy] = tr ("Floppy", "DeviceType");2924 mDeviceTypes [KDeviceType_DVD] = tr ("CD/DVD-ROM", "DeviceType");2925 mDeviceTypes [KDeviceType_HardDisk] = tr ("Hard Disk", "DeviceType");2926 mDeviceTypes [KDeviceType_Network] = tr ("Network", "DeviceType");2927 mDeviceTypes [KDeviceType_USB] = tr ("USB", "DeviceType");2928 mDeviceTypes [KDeviceType_SharedFolder] = tr ("Shared Folder", "DeviceType");2929 2930 mStorageBuses [KStorageBus_IDE] = tr ("IDE", "StorageBus");2931 mStorageBuses [KStorageBus_SATA] = tr ("SATA", "StorageBus");2932 mStorageBuses [KStorageBus_SCSI] = tr ("SCSI", "StorageBus");2933 mStorageBuses [KStorageBus_Floppy] = tr ("Floppy", "StorageBus");2934 mStorageBuses [KStorageBus_SAS] = tr ("SAS", "StorageBus");2935 2936 mStorageBusChannels [0] = tr ("Primary", "StorageBusChannel");2937 mStorageBusChannels [1] = tr ("Secondary", "StorageBusChannel");2938 mStorageBusChannels [2] = tr ("Port %1", "StorageBusChannel");2939 2940 mStorageBusDevices [0] = tr ("Master", "StorageBusDevice");2941 mStorageBusDevices [1] = tr ("Slave", "StorageBusDevice");2942 mStorageBusDevices [2] = tr ("Device %1", "StorageBusDevice");2943 2944 mSlotTemplates [0] = tr ("IDE Primary Master", "New Storage UI : Slot Name");2945 mSlotTemplates [1] = tr ("IDE Primary Slave", "New Storage UI : Slot Name");2946 mSlotTemplates [2] = tr ("IDE Secondary Master", "New Storage UI : Slot Name");2947 mSlotTemplates [3] = tr ("IDE Secondary Slave", "New Storage UI : Slot Name");2948 mSlotTemplates [4] = tr ("SATA Port %1", "New Storage UI : Slot Name");2949 mSlotTemplates [5] = tr ("SCSI Port %1", "New Storage UI : Slot Name");2950 mSlotTemplates [6] = tr ("SAS Port %1", "New Storage UI : Slot Name");2951 mSlotTemplates [7] = tr ("Floppy Device %1", "New Storage UI : Slot Name");2952 2953 mDiskTypes [KMediumType_Normal] = tr ("Normal", "DiskType");2954 mDiskTypes [KMediumType_Immutable] = tr ("Immutable", "DiskType");2955 mDiskTypes [KMediumType_Writethrough] = tr ("Writethrough", "DiskType");2956 mDiskTypes [KMediumType_Shareable] = tr ("Shareable", "DiskType");2957 mDiskTypes [KMediumType_Readonly] = tr ("Readonly", "DiskType");2958 mDiskTypes [KMediumType_MultiAttach] = tr ("Multi-attach", "DiskType");2959 mDiskTypes_Differencing = tr ("Differencing", "DiskType");2960 2961 mAuthTypes [KAuthType_Null] = tr ("Null", "AuthType");2962 mAuthTypes [KAuthType_External] = tr ("External", "AuthType");2963 mAuthTypes [KAuthType_Guest] = tr ("Guest", "AuthType");2964 2965 mPortModeTypes [KPortMode_Disconnected] = tr ("Disconnected", "PortMode");2966 mPortModeTypes [KPortMode_HostPipe] = tr ("Host Pipe", "PortMode");2967 mPortModeTypes [KPortMode_HostDevice] = tr ("Host Device", "PortMode");2968 mPortModeTypes [KPortMode_RawFile] = tr ("Raw File", "PortMode");2969 2970 mUSBFilterActionTypes [KUSBDeviceFilterAction_Ignore] =2971 tr ("Ignore", "USBFilterActionType");2972 mUSBFilterActionTypes [KUSBDeviceFilterAction_Hold] =2973 tr ("Hold", "USBFilterActionType");2974 2975 mAudioDriverTypes [KAudioDriverType_Null] =2976 tr ("Null Audio Driver", "AudioDriverType");2977 mAudioDriverTypes [KAudioDriverType_WinMM] =2978 tr ("Windows Multimedia", "AudioDriverType");2979 mAudioDriverTypes [KAudioDriverType_SolAudio] =2980 tr ("Solaris Audio", "AudioDriverType");2981 mAudioDriverTypes [KAudioDriverType_OSS] =2982 tr ("OSS Audio Driver", "AudioDriverType");2983 mAudioDriverTypes [KAudioDriverType_ALSA] =2984 tr ("ALSA Audio Driver", "AudioDriverType");2985 mAudioDriverTypes [KAudioDriverType_DirectSound] =2986 tr ("Windows DirectSound", "AudioDriverType");2987 mAudioDriverTypes [KAudioDriverType_CoreAudio] =2988 tr ("CoreAudio", "AudioDriverType");2989 mAudioDriverTypes [KAudioDriverType_Pulse] =2990 tr ("PulseAudio", "AudioDriverType");2991 2992 mAudioControllerTypes [KAudioControllerType_AC97] =2993 tr ("ICH AC97", "AudioControllerType");2994 mAudioControllerTypes [KAudioControllerType_SB16] =2995 tr ("SoundBlaster 16", "AudioControllerType");2996 mAudioControllerTypes [KAudioControllerType_HDA] =2997 tr ("Intel HD Audio", "AudioControllerType");2998 2999 mNetworkAdapterTypes [KNetworkAdapterType_Am79C970A] =3000 tr ("PCnet-PCI II (Am79C970A)", "NetworkAdapterType");3001 mNetworkAdapterTypes [KNetworkAdapterType_Am79C973] =3002 tr ("PCnet-FAST III (Am79C973)", "NetworkAdapterType");3003 mNetworkAdapterTypes [KNetworkAdapterType_I82540EM] =3004 tr ("Intel PRO/1000 MT Desktop (82540EM)", "NetworkAdapterType");3005 mNetworkAdapterTypes [KNetworkAdapterType_I82543GC] =3006 tr ("Intel PRO/1000 T Server (82543GC)", "NetworkAdapterType");3007 mNetworkAdapterTypes [KNetworkAdapterType_I82545EM] =3008 tr ("Intel PRO/1000 MT Server (82545EM)", "NetworkAdapterType");3009 #ifdef VBOX_WITH_VIRTIO3010 mNetworkAdapterTypes [KNetworkAdapterType_Virtio] =3011 tr ("Paravirtualized Network (virtio-net)", "NetworkAdapterType");3012 #endif /* VBOX_WITH_VIRTIO */3013 3014 mNetworkAttachmentTypes [KNetworkAttachmentType_Null] =3015 tr ("Not attached", "NetworkAttachmentType");3016 mNetworkAttachmentTypes [KNetworkAttachmentType_NAT] =3017 tr ("NAT", "NetworkAttachmentType");3018 mNetworkAttachmentTypes [KNetworkAttachmentType_Bridged] =3019 tr ("Bridged Adapter", "NetworkAttachmentType");3020 mNetworkAttachmentTypes [KNetworkAttachmentType_Internal] =3021 tr ("Internal Network", "NetworkAttachmentType");3022 mNetworkAttachmentTypes [KNetworkAttachmentType_HostOnly] =3023 tr ("Host-only Adapter", "NetworkAttachmentType");3024 #ifdef VBOX_WITH_VDE3025 mNetworkAttachmentTypes [KNetworkAttachmentType_VDE] =3026 tr ("VDE Adapter", "NetworkAttachmentType");3027 #endif3028 3029 mNATProtocolTypes [KNATProtocol_UDP] =3030 tr ("UDP", "NATProtocolType");3031 mNATProtocolTypes [KNATProtocol_TCP] =3032 tr ("TCP", "NATProtocolType");3033 3034 mClipboardTypes [KClipboardMode_Disabled] =3035 tr ("Disabled", "ClipboardType");3036 mClipboardTypes [KClipboardMode_HostToGuest] =3037 tr ("Host To Guest", "ClipboardType");3038 mClipboardTypes [KClipboardMode_GuestToHost] =3039 tr ("Guest To Host", "ClipboardType");3040 mClipboardTypes [KClipboardMode_Bidirectional] =3041 tr ("Bidirectional", "ClipboardType");3042 3043 mStorageControllerTypes [KStorageControllerType_PIIX3] =3044 tr ("PIIX3", "StorageControllerType");3045 mStorageControllerTypes [KStorageControllerType_PIIX4] =3046 tr ("PIIX4", "StorageControllerType");3047 mStorageControllerTypes [KStorageControllerType_ICH6] =3048 tr ("ICH6", "StorageControllerType");3049 mStorageControllerTypes [KStorageControllerType_IntelAhci] =3050 tr ("AHCI", "StorageControllerType");3051 mStorageControllerTypes [KStorageControllerType_LsiLogic] =3052 tr ("Lsilogic", "StorageControllerType");3053 mStorageControllerTypes [KStorageControllerType_BusLogic] =3054 tr ("BusLogic", "StorageControllerType");3055 mStorageControllerTypes [KStorageControllerType_I82078] =3056 tr ("I82078", "StorageControllerType");3057 mStorageControllerTypes [KStorageControllerType_LsiLogicSas] =3058 tr ("LsiLogic SAS", "StorageControllerType");3059 3060 mUSBDeviceStates [KUSBDeviceState_NotSupported] =3061 tr ("Not supported", "USBDeviceState");3062 mUSBDeviceStates [KUSBDeviceState_Unavailable] =3063 tr ("Unavailable", "USBDeviceState");3064 mUSBDeviceStates [KUSBDeviceState_Busy] =3065 tr ("Busy", "USBDeviceState");3066 mUSBDeviceStates [KUSBDeviceState_Available] =3067 tr ("Available", "USBDeviceState");3068 mUSBDeviceStates [KUSBDeviceState_Held] =3069 tr ("Held", "USBDeviceState");3070 mUSBDeviceStates [KUSBDeviceState_Captured] =3071 tr ("Captured", "USBDeviceState");3072 3073 mChipsetTypes [KChipsetType_PIIX3] =3074 tr ("PIIX3", "ChipsetType");3075 mChipsetTypes [KChipsetType_ICH9] =3076 tr ("ICH9", "ChipsetType");3077 3078 mUserDefinedPortName = tr ("User-defined", "serial port");3079 3080 mWarningIcon = UIIconPool::defaultIcon(UIIconPool::MessageBoxWarningIcon).pixmap (16, 16);3081 Assert (!mWarningIcon.isNull());3082 3083 mErrorIcon = UIIconPool::defaultIcon(UIIconPool::MessageBoxCriticalIcon).pixmap (16, 16);3084 Assert (!mErrorIcon.isNull());3085 3086 /* refresh media properties since they contain some translations too */3087 for (VBoxMediaList::iterator it = mMediaList.begin();3088 it != mMediaList.end(); ++ it)3089 it->refresh();3090 3091 #ifdef Q_WS_X113092 /* As X11 do not have functionality for providing human readable key names,3093 * we keep a table of them, which must be updated when the language is changed. */3094 UIHotKey::retranslateKeyNames();3095 #endif /* Q_WS_X11 */3096 }3097 3098 // public static stuff3099 ////////////////////////////////////////////////////////////////////////////////3100 3101 /* static */3102 bool VBoxGlobal::isDOSType (const QString &aOSTypeId)3103 {3104 if (aOSTypeId.left (3) == "dos" ||3105 aOSTypeId.left (3) == "win" ||3106 aOSTypeId.left (3) == "os2")3107 return true;3108 3109 return false;3110 }3111 3112 const char *gVBoxLangSubDir = "/nls";3113 const char *gVBoxLangFileBase = "VirtualBox_";3114 const char *gVBoxLangFileExt = ".qm";3115 const char *gVBoxLangIDRegExp = "(([a-z]{2})(?:_([A-Z]{2}))?)|(C)";3116 const char *gVBoxBuiltInLangName = "C";3117 3118 class VBoxTranslator : public QTranslator3119 {3120 public:3121 3122 VBoxTranslator (QObject *aParent = 0)3123 : QTranslator (aParent) {}3124 3125 bool loadFile (const QString &aFileName)3126 {3127 QFile file (aFileName);3128 if (!file.open (QIODevice::ReadOnly))3129 return false;3130 mData = file.readAll();3131 return load ((uchar*) mData.data(), mData.size());3132 }3133 3134 private:3135 3136 QByteArray mData;3137 };3138 3139 static VBoxTranslator *sTranslator = 0;3140 static QString sLoadedLangId = gVBoxBuiltInLangName;3141 3142 /**3143 * Returns the loaded (active) language ID.3144 * Note that it may not match with VBoxGlobalSettings::languageId() if the3145 * specified language cannot be loaded.3146 * If the built-in language is active, this method returns "C".3147 *3148 * @note "C" is treated as the built-in language for simplicity -- the C3149 * locale is used in unix environments as a fallback when the requested3150 * locale is invalid. This way we don't need to process both the "built_in"3151 * language and the "C" language (which is a valid environment setting)3152 * separately.3153 */3154 /* static */3155 QString VBoxGlobal::languageId()3156 {3157 return sLoadedLangId;3158 }3159 3160 /**3161 * Loads the language by language ID.3162 *3163 * @param aLangId Language ID in in form of xx_YY. QString::null means the3164 * system default language.3165 */3166 /* static */3167 void VBoxGlobal::loadLanguage (const QString &aLangId)3168 {3169 QString langId = aLangId.isEmpty() ?3170 VBoxGlobal::systemLanguageId() : aLangId;3171 QString languageFileName;3172 QString selectedLangId = gVBoxBuiltInLangName;3173 3174 /* If C is selected we change it temporary to en. This makes sure any extra3175 * "en" translation file will be loaded. This is necessary for loading the3176 * plural forms of some of our translations. */3177 bool fResetToC = false;3178 if (langId == "C")3179 {3180 langId = "en";3181 fResetToC = true;3182 }3183 3184 char szNlsPath[RTPATH_MAX];3185 int rc;3186 3187 rc = RTPathAppPrivateNoArch(szNlsPath, sizeof(szNlsPath));3188 AssertRC (rc);3189 3190 QString nlsPath = QString(szNlsPath) + gVBoxLangSubDir;3191 QDir nlsDir (nlsPath);3192 3193 Assert (!langId.isEmpty());3194 if (!langId.isEmpty() && langId != gVBoxBuiltInLangName)3195 {3196 QRegExp regExp (gVBoxLangIDRegExp);3197 int pos = regExp.indexIn (langId);3198 /* the language ID should match the regexp completely */3199 AssertReturnVoid (pos == 0);3200 3201 QString lang = regExp.cap (2);3202 3203 if (nlsDir.exists (gVBoxLangFileBase + langId + gVBoxLangFileExt))3204 {3205 languageFileName = nlsDir.absoluteFilePath (gVBoxLangFileBase + langId +3206 gVBoxLangFileExt);3207 selectedLangId = langId;3208 }3209 else if (nlsDir.exists (gVBoxLangFileBase + lang + gVBoxLangFileExt))3210 {3211 languageFileName = nlsDir.absoluteFilePath (gVBoxLangFileBase + lang +3212 gVBoxLangFileExt);3213 selectedLangId = lang;3214 }3215 else3216 {3217 /* Never complain when the default language is requested. In any3218 * case, if no explicit language file exists, we will simply3219 * fall-back to English (built-in). */3220 if (!aLangId.isNull() && langId != "en")3221 vboxProblem().cannotFindLanguage (langId, nlsPath);3222 /* selectedLangId remains built-in here */3223 AssertReturnVoid (selectedLangId == gVBoxBuiltInLangName);3224 }3225 }3226 3227 /* delete the old translator if there is one */3228 if (sTranslator)3229 {3230 /* QTranslator destructor will call qApp->removeTranslator() for3231 * us. It will also delete all its child translations we attach to it3232 * below, so we don't have to care about them specially. */3233 delete sTranslator;3234 }3235 3236 /* load new language files */3237 sTranslator = new VBoxTranslator (qApp);3238 Assert (sTranslator);3239 bool loadOk = true;3240 if (sTranslator)3241 {3242 if (selectedLangId != gVBoxBuiltInLangName)3243 {3244 Assert (!languageFileName.isNull());3245 loadOk = sTranslator->loadFile (languageFileName);3246 }3247 /* we install the translator in any case: on failure, this will3248 * activate an empty translator that will give us English3249 * (built-in) */3250 qApp->installTranslator (sTranslator);3251 }3252 else3253 loadOk = false;3254 3255 if (loadOk)3256 sLoadedLangId = selectedLangId;3257 else3258 {3259 vboxProblem().cannotLoadLanguage (languageFileName);3260 sLoadedLangId = gVBoxBuiltInLangName;3261 }3262 3263 /* Try to load the corresponding Qt translation */3264 if (sLoadedLangId != gVBoxBuiltInLangName)3265 {3266 #ifdef Q_OS_UNIX3267 /* We use system installations of Qt on Linux systems, so first, try3268 * to load the Qt translation from the system location. */3269 languageFileName = QLibraryInfo::location(QLibraryInfo::TranslationsPath) + "/qt_" +3270 sLoadedLangId + gVBoxLangFileExt;3271 QTranslator *qtSysTr = new QTranslator (sTranslator);3272 Assert (qtSysTr);3273 if (qtSysTr && qtSysTr->load (languageFileName))3274 qApp->installTranslator (qtSysTr);3275 /* Note that the Qt translation supplied by Oracle is always loaded3276 * afterwards to make sure it will take precedence over the system3277 * translation (it may contain more decent variants of translation3278 * that better correspond to VirtualBox UI). We need to load both3279 * because a newer version of Qt may be installed on the user computer3280 * and the Oracle version may not fully support it. We don't do it on3281 * Win32 because we supply a Qt library there and therefore the3282 * Oracle translation is always the best one. */3283 #endif3284 languageFileName = nlsDir.absoluteFilePath (QString ("qt_") +3285 sLoadedLangId +3286 gVBoxLangFileExt);3287 QTranslator *qtTr = new QTranslator (sTranslator);3288 Assert (qtTr);3289 if (qtTr && (loadOk = qtTr->load (languageFileName)))3290 qApp->installTranslator (qtTr);3291 /* The below message doesn't fit 100% (because it's an additional3292 * language and the main one won't be reset to built-in on failure)3293 * but the load failure is so rare here that it's not worth a separate3294 * message (but still, having something is better than having none) */3295 if (!loadOk && !aLangId.isNull())3296 vboxProblem().cannotLoadLanguage (languageFileName);3297 }3298 if (fResetToC)3299 sLoadedLangId = "C";3300 #ifdef Q_WS_MAC3301 /* Qt doesn't translate the items in the Application menu initially.3302 * Manually trigger an update. */3303 ::darwinRetranslateAppMenu();3304 #endif /* Q_WS_MAC */3305 }3306 3307 QString VBoxGlobal::helpFile() const3308 {3309 #if defined (Q_WS_WIN32)3310 const QString name = "VirtualBox";3311 const QString suffix = "chm";3312 #elif defined (Q_WS_MAC)3313 const QString name = "UserManual";3314 const QString suffix = "pdf";3315 #elif defined (Q_WS_X11)3316 # if defined VBOX_OSE3317 const QString name = "UserManual";3318 const QString suffix = "pdf";3319 # else3320 const QString name = "VirtualBox";3321 const QString suffix = "chm";3322 # endif3323 #endif3324 /* Where are the docs located? */3325 char szDocsPath[RTPATH_MAX];3326 int rc = RTPathAppDocs (szDocsPath, sizeof (szDocsPath));3327 AssertRC (rc);3328 /* Make sure that the language is in two letter code.3329 * Note: if languageId() returns an empty string lang.name() will3330 * return "C" which is an valid language code. */3331 QLocale lang (VBoxGlobal::languageId());3332 3333 /* Construct the path and the filename */3334 QString manual = QString ("%1/%2_%3.%4").arg (szDocsPath)3335 .arg (name)3336 .arg (lang.name())3337 .arg (suffix);3338 /* Check if a help file with that name exists */3339 QFileInfo fi (manual);3340 if (fi.exists())3341 return manual;3342 3343 /* Fall back to the standard */3344 manual = QString ("%1/%2.%4").arg (szDocsPath)3345 .arg (name)3346 .arg (suffix);3347 return manual;3348 }3349 3350 /**3351 * Replacement for QToolButton::setTextLabel() that handles the shortcut3352 * letter (if it is present in the argument string) as if it were a setText()3353 * call: the shortcut letter is used to automatically assign an "Alt+<letter>"3354 * accelerator key sequence to the given tool button.3355 *3356 * @note This method preserves the icon set if it was assigned before. Only3357 * the text label and the accelerator are changed.3358 *3359 * @param aToolButton Tool button to set the text label on.3360 * @param aTextLabel Text label to set.3361 */3362 /* static */3363 void VBoxGlobal::setTextLabel (QToolButton *aToolButton,3364 const QString &aTextLabel)3365 {3366 AssertReturnVoid (aToolButton != NULL);3367 3368 /* remember the icon set as setText() will kill it */3369 QIcon iset = aToolButton->icon();3370 /* re-use the setText() method to detect and set the accelerator */3371 aToolButton->setText (aTextLabel);3372 QKeySequence accel = aToolButton->shortcut();3373 aToolButton->setText (aTextLabel);3374 aToolButton->setIcon (iset);3375 /* set the accel last as setIconSet() would kill it */3376 aToolButton->setShortcut (accel);3377 }3378 3379 /**3380 * Performs direct and flipped search of position for \a aRectangle to make sure3381 * it is fully contained inside \a aBoundRegion region by moving & resizing3382 * \a aRectangle if necessary. Selects the minimum shifted result between direct3383 * and flipped variants.3384 */3385 /* static */3386 QRect VBoxGlobal::normalizeGeometry (const QRect &aRectangle, const QRegion &aBoundRegion,3387 bool aCanResize /* = true */)3388 {3389 /* Direct search for normalized rectangle */3390 QRect var1 (getNormalized (aRectangle, aBoundRegion, aCanResize));3391 3392 /* Flipped search for normalized rectangle */3393 QRect var2 (flip (getNormalized (flip (aRectangle).boundingRect(),3394 flip (aBoundRegion), aCanResize)).boundingRect());3395 3396 /* Calculate shift from starting position for both variants */3397 double length1 = sqrt (pow ((double) (var1.x() - aRectangle.x()), (double) 2) +3398 pow ((double) (var1.y() - aRectangle.y()), (double) 2));3399 double length2 = sqrt (pow ((double) (var2.x() - aRectangle.x()), (double) 2) +3400 pow ((double) (var2.y() - aRectangle.y()), (double) 2));3401 3402 /* Return minimum shifted variant */3403 return length1 > length2 ? var2 : var1;3404 }3405 3406 /**3407 * Ensures that the given rectangle \a aRectangle is fully contained within the3408 * region \a aBoundRegion by moving \a aRectangle if necessary. If \a aRectangle is3409 * larger than \a aBoundRegion, top left corner of \a aRectangle is aligned with the3410 * top left corner of maximum available rectangle and, if \a aCanResize is true,3411 * \a aRectangle is shrinked to become fully visible.3412 */3413 /* static */3414 QRect VBoxGlobal::getNormalized (const QRect &aRectangle, const QRegion &aBoundRegion,3415 bool /* aCanResize = true */)3416 {3417 /* Storing available horizontal sub-rectangles & vertical shifts */3418 int windowVertical = aRectangle.center().y();3419 QVector <QRect> rectanglesVector (aBoundRegion.rects());3420 QList <QRect> rectanglesList;3421 QList <int> shiftsList;3422 foreach (QRect currentItem, rectanglesVector)3423 {3424 int currentDelta = qAbs (windowVertical - currentItem.center().y());3425 int shift2Top = currentItem.top() - aRectangle.top();3426 int shift2Bot = currentItem.bottom() - aRectangle.bottom();3427 3428 int itemPosition = 0;3429 foreach (QRect item, rectanglesList)3430 {3431 int delta = qAbs (windowVertical - item.center().y());3432 if (delta > currentDelta) break; else ++ itemPosition;3433 }3434 rectanglesList.insert (itemPosition, currentItem);3435 3436 int shift2TopPos = 0;3437 foreach (int shift, shiftsList)3438 if (qAbs (shift) > qAbs (shift2Top)) break; else ++ shift2TopPos;3439 shiftsList.insert (shift2TopPos, shift2Top);3440 3441 int shift2BotPos = 0;3442 foreach (int shift, shiftsList)3443 if (qAbs (shift) > qAbs (shift2Bot)) break; else ++ shift2BotPos;3444 shiftsList.insert (shift2BotPos, shift2Bot);3445 }3446 3447 /* Trying to find the appropriate place for window */3448 QRect result;3449 for (int i = -1; i < shiftsList.size(); ++ i)3450 {3451 /* Move to appropriate vertical */3452 QRect rectangle (aRectangle);3453 if (i >= 0) rectangle.translate (0, shiftsList [i]);3454 3455 /* Search horizontal shift */3456 int maxShift = 0;3457 foreach (QRect item, rectanglesList)3458 {3459 QRect trectangle (rectangle.translated (item.left() - rectangle.left(), 0));3460 if (!item.intersects (trectangle))3461 continue;3462 3463 if (rectangle.left() < item.left())3464 {3465 int shift = item.left() - rectangle.left();3466 maxShift = qAbs (shift) > qAbs (maxShift) ? shift : maxShift;3467 }3468 else if (rectangle.right() > item.right())3469 {3470 int shift = item.right() - rectangle.right();3471 maxShift = qAbs (shift) > qAbs (maxShift) ? shift : maxShift;3472 }3473 }3474 3475 /* Shift across the horizontal direction */3476 rectangle.translate (maxShift, 0);3477 3478 /* Check the translated rectangle to feat the rules */3479 if (aBoundRegion.united (rectangle) == aBoundRegion)3480 result = rectangle;3481 3482 if (!result.isNull()) break;3483 }3484 3485 if (result.isNull())3486 {3487 /* Resize window to feat desirable size3488 * using max of available rectangles */3489 QRect maxRectangle;3490 quint64 maxSquare = 0;3491 foreach (QRect item, rectanglesList)3492 {3493 quint64 square = item.width() * item.height();3494 if (square > maxSquare)3495 {3496 maxSquare = square;3497 maxRectangle = item;3498 }3499 }3500 3501 result = aRectangle;3502 result.moveTo (maxRectangle.x(), maxRectangle.y());3503 if (maxRectangle.right() < result.right())3504 result.setRight (maxRectangle.right());3505 if (maxRectangle.bottom() < result.bottom())3506 result.setBottom (maxRectangle.bottom());3507 }3508 3509 return result;3510 }3511 3512 /**3513 * Returns the flipped (transposed) region.3514 */3515 /* static */3516 QRegion VBoxGlobal::flip (const QRegion &aRegion)3517 {3518 QRegion result;3519 QVector <QRect> rectangles (aRegion.rects());3520 foreach (QRect rectangle, rectangles)3521 result += QRect (rectangle.y(), rectangle.x(),3522 rectangle.height(), rectangle.width());3523 return result;3524 }3525 3526 /**3527 * Aligns the center of \a aWidget with the center of \a aRelative.3528 *3529 * If necessary, \a aWidget's position is adjusted to make it fully visible3530 * within the available desktop area. If \a aWidget is bigger then this area,3531 * it will also be resized unless \a aCanResize is false or there is an3532 * inappropriate minimum size limit (in which case the top left corner will be3533 * simply aligned with the top left corner of the available desktop area).3534 *3535 * \a aWidget must be a top-level widget. \a aRelative may be any widget, but3536 * if it's not top-level itself, its top-level widget will be used for3537 * calculations. \a aRelative can also be NULL, in which case \a aWidget will3538 * be centered relative to the available desktop area.3539 */3540 /* static */3541 void VBoxGlobal::centerWidget (QWidget *aWidget, QWidget *aRelative,3542 bool aCanResize /* = true */)3543 {3544 AssertReturnVoid (aWidget);3545 AssertReturnVoid (aWidget->isTopLevel());3546 3547 QRect deskGeo, parentGeo;3548 QWidget *w = aRelative;3549 if (w)3550 {3551 w = w->window();3552 deskGeo = QApplication::desktop()->availableGeometry (w);3553 parentGeo = w->frameGeometry();3554 /* On X11/Gnome, geo/frameGeo.x() and y() are always 0 for top level3555 * widgets with parents, what a shame. Use mapToGlobal() to workaround. */3556 QPoint d = w->mapToGlobal (QPoint (0, 0));3557 d.rx() -= w->geometry().x() - w->x();3558 d.ry() -= w->geometry().y() - w->y();3559 parentGeo.moveTopLeft (d);3560 }3561 else3562 {3563 deskGeo = QApplication::desktop()->availableGeometry();3564 parentGeo = deskGeo;3565 }3566 3567 /* On X11, there is no way to determine frame geometry (including WM3568 * decorations) before the widget is shown for the first time. Stupidly3569 * enumerate other top level widgets to find the thickest frame. The code3570 * is based on the idea taken from QDialog::adjustPositionInternal(). */3571 3572 int extraw = 0, extrah = 0;3573 3574 QWidgetList list = QApplication::topLevelWidgets();3575 QListIterator<QWidget*> it (list);3576 while ((extraw == 0 || extrah == 0) && it.hasNext())3577 {3578 int framew, frameh;3579 QWidget *current = it.next();3580 if (!current->isVisible())3581 continue;3582 3583 framew = current->frameGeometry().width() - current->width();3584 frameh = current->frameGeometry().height() - current->height();3585 3586 extraw = qMax (extraw, framew);3587 extrah = qMax (extrah, frameh);3588 }3589 3590 /// @todo (r=dmik) not sure if we really need this3591 #if 03592 /* sanity check for decoration frames. With embedding, we3593 * might get extraordinary values */3594 if (extraw == 0 || extrah == 0 || extraw > 20 || extrah > 50)3595 {3596 extrah = 50;3597 extraw = 20;3598 }3599 #endif3600 3601 /* On non-X11 platforms, the following would be enough instead of the3602 * above workaround: */3603 // QRect geo = frameGeometry();3604 QRect geo = QRect (0, 0, aWidget->width() + extraw,3605 aWidget->height() + extrah);3606 3607 geo.moveCenter (QPoint (parentGeo.x() + (parentGeo.width() - 1) / 2,3608 parentGeo.y() + (parentGeo.height() - 1) / 2));3609 3610 /* ensure the widget is within the available desktop area */3611 QRect newGeo = normalizeGeometry (geo, deskGeo, aCanResize);3612 #ifdef Q_WS_MAC3613 /* No idea why, but Qt doesn't respect if there is a unified toolbar on the3614 * ::move call. So manually add the height of the toolbar before setting3615 * the position. */3616 if (w)3617 newGeo.translate (0, ::darwinWindowToolBarHeight (aWidget));3618 #endif /* Q_WS_MAC */3619 3620 aWidget->move (newGeo.topLeft());3621 3622 if (aCanResize &&3623 (geo.width() != newGeo.width() || geo.height() != newGeo.height()))3624 aWidget->resize (newGeo.width() - extraw, newGeo.height() - extrah);3625 }3626 3627 /**3628 * Returns the decimal separator for the current locale.3629 */3630 /* static */3631 QChar VBoxGlobal::decimalSep()3632 {3633 return QLocale::system().decimalPoint();3634 }3635 3636 /**3637 * Returns the regexp string that defines the format of the human-readable3638 * size representation, <tt>####[.##] B|KB|MB|GB|TB|PB</tt>.3639 *3640 * This regexp will capture 5 groups of text:3641 * - cap(1): integer number in case when no decimal point is present3642 * (if empty, it means that decimal point is present)3643 * - cap(2): size suffix in case when no decimal point is present (may be empty)3644 * - cap(3): integer number in case when decimal point is present (may be empty)3645 * - cap(4): fraction number (hundredth) in case when decimal point is present3646 * - cap(5): size suffix in case when decimal point is present (note that3647 * B cannot appear there)3648 */3649 /* static */3650 QString VBoxGlobal::sizeRegexp()3651 {3652 QString regexp =3653 QString ("^(?:(?:(\\d+)(?:\\s?(%2|%3|%4|%5|%6|%7))?)|(?:(\\d*)%1(\\d{1,2})(?:\\s?(%3|%4|%5|%6|%7))))$")3654 .arg (decimalSep())3655 .arg (tr ("B", "size suffix Bytes"))3656 .arg (tr ("KB", "size suffix KBytes=1024 Bytes"))3657 .arg (tr ("MB", "size suffix MBytes=1024 KBytes"))3658 .arg (tr ("GB", "size suffix GBytes=1024 MBytes"))3659 .arg (tr ("TB", "size suffix TBytes=1024 GBytes"))3660 .arg (tr ("PB", "size suffix PBytes=1024 TBytes"));3661 return regexp;3662 }3663 3664 /* static */3665 QString VBoxGlobal::toHumanReadableList(const QStringList &list)3666 {3667 QString strList;3668 if (list.size() == 1)3669 strList = list.at(0);3670 else if (list.size() > 1)3671 {3672 for (int i = 0; i < list.size() - 1; ++i)3673 {3674 strList += list.at(i);3675 if (i < list.size() - 2)3676 strList += + ", ";3677 }3678 strList += " " + tr("and") + " " + list.at(list.size() - 1);3679 }3680 return strList;3681 }3682 3683 /**3684 * Parses the given size string that should be in form of3685 * <tt>####[.##] B|KB|MB|GB|TB|PB</tt> and returns3686 * the size value in bytes. Zero is returned on error.3687 */3688 /* static */3689 quint64 VBoxGlobal::parseSize (const QString &aText)3690 {3691 QRegExp regexp (sizeRegexp());3692 int pos = regexp.indexIn (aText);3693 if (pos != -1)3694 {3695 QString intgS = regexp.cap (1);3696 QString hundS;3697 QString suff = regexp.cap (2);3698 if (intgS.isEmpty())3699 {3700 intgS = regexp.cap (3);3701 hundS = regexp.cap (4);3702 suff = regexp.cap (5);3703 }3704 3705 quint64 denom = 0;3706 if (suff.isEmpty() || suff == tr ("B", "size suffix Bytes"))3707 denom = 1;3708 else if (suff == tr ("KB", "size suffix KBytes=1024 Bytes"))3709 denom = _1K;3710 else if (suff == tr ("MB", "size suffix MBytes=1024 KBytes"))3711 denom = _1M;3712 else if (suff == tr ("GB", "size suffix GBytes=1024 MBytes"))3713 denom = _1G;3714 else if (suff == tr ("TB", "size suffix TBytes=1024 GBytes"))3715 denom = _1T;3716 else if (suff == tr ("PB", "size suffix PBytes=1024 TBytes"))3717 denom = _1P;3718 3719 quint64 intg = intgS.toULongLong();3720 if (denom == 1)3721 return intg;3722 3723 quint64 hund = hundS.leftJustified (2, '0').toULongLong();3724 hund = hund * denom / 100;3725 intg = intg * denom + hund;3726 return intg;3727 }3728 else3729 return 0;3730 }3731 3732 /**3733 * Formats the given @a aSize value in bytes to a human readable string3734 * in form of <tt>####[.##] B|KB|MB|GB|TB|PB</tt>.3735 *3736 * The @a aMode and @a aDecimal parameters are used for rounding the resulting3737 * number when converting the size value to KB, MB, etc gives a fractional part:3738 * <ul>3739 * <li>When \a aMode is FormatSize_Round, the result is rounded to the3740 * closest number containing \a aDecimal decimal digits.3741 * </li>3742 * <li>When \a aMode is FormatSize_RoundDown, the result is rounded to the3743 * largest number with \a aDecimal decimal digits that is not greater than3744 * the result. This guarantees that converting the resulting string back to3745 * the integer value in bytes will not produce a value greater that the3746 * initial size parameter.3747 * </li>3748 * <li>When \a aMode is FormatSize_RoundUp, the result is rounded to the3749 * smallest number with \a aDecimal decimal digits that is not less than the3750 * result. This guarantees that converting the resulting string back to the3751 * integer value in bytes will not produce a value less that the initial3752 * size parameter.3753 * </li>3754 * </ul>3755 *3756 * @param aSize Size value in bytes.3757 * @param aMode Conversion mode.3758 * @param aDecimal Number of decimal digits in result.3759 * @return Human-readable size string.3760 */3761 /* static */3762 QString VBoxGlobal::formatSize (quint64 aSize, uint aDecimal /* = 2 */,3763 VBoxDefs::FormatSize aMode /* = FormatSize_Round */)3764 {3765 static QString Suffixes [7];3766 Suffixes[0] = tr ("B", "size suffix Bytes");3767 Suffixes[1] = tr ("KB", "size suffix KBytes=1024 Bytes");3768 Suffixes[2] = tr ("MB", "size suffix MBytes=1024 KBytes");3769 Suffixes[3] = tr ("GB", "size suffix GBytes=1024 MBytes");3770 Suffixes[4] = tr ("TB", "size suffix TBytes=1024 GBytes");3771 Suffixes[5] = tr ("PB", "size suffix PBytes=1024 TBytes");3772 Suffixes[6] = (const char *)NULL;3773 AssertCompile(6 < RT_ELEMENTS (Suffixes));3774 3775 quint64 denom = 0;3776 int suffix = 0;3777 3778 if (aSize < _1K)3779 {3780 denom = 1;3781 suffix = 0;3782 }3783 else if (aSize < _1M)3784 {3785 denom = _1K;3786 suffix = 1;3787 }3788 else if (aSize < _1G)3789 {3790 denom = _1M;3791 suffix = 2;3792 }3793 else if (aSize < _1T)3794 {3795 denom = _1G;3796 suffix = 3;3797 }3798 else if (aSize < _1P)3799 {3800 denom = _1T;3801 suffix = 4;3802 }3803 else3804 {3805 denom = _1P;3806 suffix = 5;3807 }3808 3809 quint64 intg = aSize / denom;3810 quint64 decm = aSize % denom;3811 quint64 mult = 1;3812 for (uint i = 0; i < aDecimal; ++ i) mult *= 10;3813 3814 QString number;3815 if (denom > 1)3816 {3817 if (decm)3818 {3819 decm *= mult;3820 /* not greater */3821 if (aMode == VBoxDefs::FormatSize_RoundDown)3822 decm = decm / denom;3823 /* not less */3824 else if (aMode == VBoxDefs::FormatSize_RoundUp)3825 decm = (decm + denom - 1) / denom;3826 /* nearest */3827 else decm = (decm + denom / 2) / denom;3828 }3829 /* check for the fractional part overflow due to rounding */3830 if (decm == mult)3831 {3832 decm = 0;3833 ++ intg;3834 /* check if we've got 1024 XB after rounding and scale down if so */3835 if (intg == 1024 && Suffixes [suffix + 1] != NULL)3836 {3837 intg /= 1024;3838 ++ suffix;3839 }3840 }3841 number = QString::number (intg);3842 if (aDecimal) number += QString ("%1%2").arg (decimalSep())3843 .arg (QString::number (decm).rightJustified (aDecimal, '0'));3844 }3845 else3846 {3847 number = QString::number (intg);3848 }3849 3850 return QString ("%1 %2").arg (number).arg (Suffixes [suffix]);3851 }3852 3853 /* static */3854 bool VBoxGlobal::shouldWarnAboutToLowVRAM(const CMachine *pMachine /* = 0 */)3855 {3856 static QStringList osList = QStringList()3857 << "Other" << "DOS" << "Netware" << "L4" << "QNX" << "JRockitVE";3858 3859 bool fResult = true;3860 if ( pMachine3861 && !pMachine->isNull()3862 && osList.contains(pMachine->GetOSTypeId()))3863 fResult = false;3864 3865 return fResult;3866 }3867 3868 /**3869 * Returns the required video memory in bytes for the current desktop3870 * resolution at maximum possible screen depth in bpp.3871 */3872 /* static */3873 quint64 VBoxGlobal::requiredVideoMemory (CMachine *aMachine /* = 0 */, int cMonitors /* = 1 */)3874 {3875 QSize desktopRes = QApplication::desktop()->screenGeometry().size();3876 QDesktopWidget *pDW = QApplication::desktop();3877 /* We create a list of the size of all available host monitors. This list3878 * is sorted by value and by starting with the biggest one, we calculate3879 * the memory requirements for every guest screen. This is of course not3880 * correct, but as we can't predict on which host screens the user will3881 * open the guest windows, this is the best assumption we can do, cause it3882 * is the worst case. */3883 QVector<int> screenSize(qMax(cMonitors, pDW->numScreens()), 0);3884 for (int i = 0; i < pDW->numScreens(); ++i)3885 {3886 QRect r = pDW->screenGeometry(i);3887 screenSize[i] = r.width() * r.height();3888 }3889 /* Now sort the vector */3890 qSort(screenSize.begin(), screenSize.end(), qGreater<int>());3891 /* For the case that there are more guest screens configured then host3892 * screens available, replace all zeros with the greatest value in the3893 * vector. */3894 for (int i = 0; i < screenSize.size(); ++i)3895 if (screenSize.at(i) == 0)3896 screenSize.replace(i, screenSize.at(0));3897 3898 quint64 needBits = 0;3899 for (int i = 0; i < cMonitors; ++i)3900 {3901 /* Calculate summary required memory amount in bits */3902 needBits += (screenSize.at(i) * /* with x height */3903 32 + /* we will take the maximum possible bpp for now */3904 8 * _1M) + /* current cache per screen - may be changed in future */3905 8 * 4096; /* adapter info */3906 }3907 /* Translate value into megabytes with rounding to highest side */3908 quint64 needMBytes = needBits % (8 * _1M) ? needBits / (8 * _1M) + 1 :3909 needBits / (8 * _1M) /* convert to megabytes */;3910 3911 if (aMachine && !aMachine->isNull())3912 {3913 QString typeId = aMachine->GetOSTypeId();3914 if (typeId.startsWith("Windows"))3915 {3916 /* Windows guests need offscreen VRAM too for graphics acceleration features. */3917 #ifdef VBOX_WITH_CRHGSMI3918 if (typeId == "WindowsVista" || typeId == "Windows7")3919 {3920 /* wddm mode, there are two surfaces for each screen: shadow & primary */3921 needMBytes *= 3;3922 }3923 else3924 #endif3925 {3926 needMBytes *= 2;3927 }3928 }3929 }3930 3931 return needMBytes * _1M;3932 }3933 3934 /**3935 * Puts soft hyphens after every path component in the given file name.3936 *3937 * @param aFileName File name (must be a full path name).3938 */3939 /* static */3940 QString VBoxGlobal::locationForHTML (const QString &aFileName)3941 {3942 /// @todo (dmik) remove?3943 // QString result = QDir::toNativeSeparators (fn);3944 //#ifdef Q_OS_LINUX3945 // result.replace ('/', "/<font color=red>­</font>");3946 //#else3947 // result.replace ('\\', "\\<font color=red>­</font>");3948 //#endif3949 // return result;3950 QFileInfo fi (aFileName);3951 return fi.fileName();3952 }3953 3954 /**3955 * Reformats the input string @a aStr so that:3956 * - strings in single quotes will be put inside <nobr> and marked3957 * with blue color;3958 * - UUIDs be put inside <nobr> and marked3959 * with green color;3960 * - replaces new line chars with </p><p> constructs to form paragraphs3961 * (note that <p> and </p> are not appended to the beginning and to the3962 * end of the string respectively, to allow the result be appended3963 * or prepended to the existing paragraph).3964 *3965 * If @a aToolTip is true, colouring is not applied, only the <nobr> tag3966 * is added. Also, new line chars are replaced with <br> instead of <p>.3967 */3968 /* static */3969 QString VBoxGlobal::highlight (const QString &aStr, bool aToolTip /* = false */)3970 {3971 QString strFont;3972 QString uuidFont;3973 QString endFont;3974 if (!aToolTip)3975 {3976 strFont = "<font color=#0000CC>";3977 uuidFont = "<font color=#008000>";3978 endFont = "</font>";3979 }3980 3981 QString text = aStr;3982 3983 /* replace special entities, '&' -- first! */3984 text.replace ('&', "&");3985 text.replace ('<', "<");3986 text.replace ('>', ">");3987 text.replace ('\"', """);3988 3989 /* mark strings in single quotes with color */3990 QRegExp rx = QRegExp ("((?:^|\\s)[(]?)'([^']*)'(?=[:.-!);]?(?:\\s|$))");3991 rx.setMinimal (true);3992 text.replace (rx,3993 QString ("\\1%1<nobr>'\\2'</nobr>%2").arg (strFont).arg (endFont));3994 3995 /* mark UUIDs with color */3996 text.replace (QRegExp (3997 "((?:^|\\s)[(]?)"3998 "(\\{[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\\})"3999 "(?=[:.-!);]?(?:\\s|$))"),4000 QString ("\\1%1<nobr>\\2</nobr>%2").arg (uuidFont).arg (endFont));4001 4002 /* split to paragraphs at \n chars */4003 if (!aToolTip)4004 text.replace ('\n', "</p><p>");4005 else4006 text.replace ('\n', "<br>");4007 4008 return text;4009 }4010 4011 /* static */4012 QString VBoxGlobal::replaceHtmlEntities(QString strText)4013 {4014 return strText4015 .replace('&', "&")4016 .replace('<', "<")4017 .replace('>', ">")4018 .replace('\"', """);4019 }4020 4021 /**4022 * Reformats the input string @a aStr so that:4023 * - strings in single quotes will be put inside <nobr> and marked4024 * with bold style;4025 * - UUIDs be put inside <nobr> and marked4026 * with italic style;4027 * - replaces new line chars with </p><p> constructs to form paragraphs4028 * (note that <p> and </p> are not appended to the beginning and to the4029 * end of the string respectively, to allow the result be appended4030 * or prepended to the existing paragraph).4031 */4032 /* static */4033 QString VBoxGlobal::emphasize (const QString &aStr)4034 {4035 QString strEmphStart ("<b>");4036 QString strEmphEnd ("</b>");4037 QString uuidEmphStart ("<i>");4038 QString uuidEmphEnd ("</i>");4039 4040 QString text = aStr;4041 4042 /* replace special entities, '&' -- first! */4043 text.replace ('&', "&");4044 text.replace ('<', "<");4045 text.replace ('>', ">");4046 text.replace ('\"', """);4047 4048 /* mark strings in single quotes with bold style */4049 QRegExp rx = QRegExp ("((?:^|\\s)[(]?)'([^']*)'(?=[:.-!);]?(?:\\s|$))");4050 rx.setMinimal (true);4051 text.replace (rx,4052 QString ("\\1%1<nobr>'\\2'</nobr>%2").arg (strEmphStart).arg (strEmphEnd));4053 4054 /* mark UUIDs with italic style */4055 text.replace (QRegExp (4056 "((?:^|\\s)[(]?)"4057 "(\\{[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\\})"4058 "(?=[:.-!);]?(?:\\s|$))"),4059 QString ("\\1%1<nobr>\\2</nobr>%2").arg (uuidEmphStart).arg (uuidEmphEnd));4060 4061 /* split to paragraphs at \n chars */4062 text.replace ('\n', "</p><p>");4063 4064 return text;4065 }4066 4067 /**4068 * This does exactly the same as QLocale::system().name() but corrects its4069 * wrong behavior on Linux systems (LC_NUMERIC for some strange reason takes4070 * precedence over any other locale setting in the QLocale::system()4071 * implementation). This implementation first looks at LC_ALL (as defined by4072 * SUS), then looks at LC_MESSAGES which is designed to define a language for4073 * program messages in case if it differs from the language for other locale4074 * categories. Then it looks for LANG and finally falls back to4075 * QLocale::system().name().4076 *4077 * The order of precedence is well defined here:4078 * http://opengroup.org/onlinepubs/007908799/xbd/envvar.html4079 *4080 * @note This method will return "C" when the requested locale is invalid or4081 * when the "C" locale is set explicitly.4082 */4083 /* static */4084 QString VBoxGlobal::systemLanguageId()4085 {4086 #if defined (Q_WS_MAC)4087 /* QLocale return the right id only if the user select the format of the4088 * language also. So we use our own implementation */4089 return ::darwinSystemLanguage();4090 #elif defined (Q_OS_UNIX)4091 const char *s = RTEnvGet ("LC_ALL");4092 if (s == 0)4093 s = RTEnvGet ("LC_MESSAGES");4094 if (s == 0)4095 s = RTEnvGet ("LANG");4096 if (s != 0)4097 return QLocale (s).name();4098 #endif4099 return QLocale::system().name();4100 }4101 4102 #if defined (Q_WS_X11)4103 4104 static char *XXGetProperty (Display *aDpy, Window aWnd,4105 Atom aPropType, const char *aPropName)4106 {4107 Atom propNameAtom = XInternAtom (aDpy, aPropName,4108 True /* only_if_exists */);4109 if (propNameAtom == None)4110 return NULL;4111 4112 Atom actTypeAtom = None;4113 int actFmt = 0;4114 unsigned long nItems = 0;4115 unsigned long nBytesAfter = 0;4116 unsigned char *propVal = NULL;4117 int rc = XGetWindowProperty (aDpy, aWnd, propNameAtom,4118 0, LONG_MAX, False /* delete */,4119 aPropType, &actTypeAtom, &actFmt,4120 &nItems, &nBytesAfter, &propVal);4121 if (rc != Success)4122 return NULL;4123 4124 return reinterpret_cast <char *> (propVal);4125 }4126 4127 static Bool XXSendClientMessage (Display *aDpy, Window aWnd, const char *aMsg,4128 unsigned long aData0 = 0, unsigned long aData1 = 0,4129 unsigned long aData2 = 0, unsigned long aData3 = 0,4130 unsigned long aData4 = 0)4131 {4132 Atom msgAtom = XInternAtom (aDpy, aMsg, True /* only_if_exists */);4133 if (msgAtom == None)4134 return False;4135 4136 XEvent ev;4137 4138 ev.xclient.type = ClientMessage;4139 ev.xclient.serial = 0;4140 ev.xclient.send_event = True;4141 ev.xclient.display = aDpy;4142 ev.xclient.window = aWnd;4143 ev.xclient.message_type = msgAtom;4144 4145 /* always send as 32 bit for now */4146 ev.xclient.format = 32;4147 ev.xclient.data.l [0] = aData0;4148 ev.xclient.data.l [1] = aData1;4149 ev.xclient.data.l [2] = aData2;4150 ev.xclient.data.l [3] = aData3;4151 ev.xclient.data.l [4] = aData4;4152 4153 return XSendEvent (aDpy, DefaultRootWindow (aDpy), False,4154 SubstructureRedirectMask, &ev) != 0;4155 }4156 4157 #endif4158 4159 /**4160 * Activates the specified window. If necessary, the window will be4161 * de-iconified activation.4162 *4163 * @note On X11, it is implied that @a aWid represents a window of the same4164 * display the application was started on.4165 *4166 * @param aWId Window ID to activate.4167 * @param aSwitchDesktop @c true to switch to the window's desktop before4168 * activation.4169 *4170 * @return @c true on success and @c false otherwise.4171 */4172 /* static */4173 bool VBoxGlobal::activateWindow (WId aWId, bool aSwitchDesktop /* = true */)4174 {4175 bool result = true;4176 4177 #if defined (Q_WS_WIN32)4178 4179 if (IsIconic (aWId))4180 result &= !!ShowWindow (aWId, SW_RESTORE);4181 else if (!IsWindowVisible (aWId))4182 result &= !!ShowWindow (aWId, SW_SHOW);4183 4184 result &= !!SetForegroundWindow (aWId);4185 4186 #elif defined (Q_WS_X11)4187 4188 Display *dpy = QX11Info::display();4189 4190 if (aSwitchDesktop)4191 {4192 /* try to find the desktop ID using the NetWM property */4193 CARD32 *desktop = (CARD32 *) XXGetProperty (dpy, aWId, XA_CARDINAL,4194 "_NET_WM_DESKTOP");4195 if (desktop == NULL)4196 /* if the NetWM properly is not supported try to find the desktop4197 * ID using the GNOME WM property */4198 desktop = (CARD32 *) XXGetProperty (dpy, aWId, XA_CARDINAL,4199 "_WIN_WORKSPACE");4200 4201 if (desktop != NULL)4202 {4203 Bool ok = XXSendClientMessage (dpy, DefaultRootWindow (dpy),4204 "_NET_CURRENT_DESKTOP",4205 *desktop);4206 if (!ok)4207 {4208 LogWarningFunc (("Couldn't switch to desktop=%08X\n",4209 desktop));4210 result = false;4211 }4212 XFree (desktop);4213 }4214 else4215 {4216 LogWarningFunc (("Couldn't find a desktop ID for aWId=%08X\n",4217 aWId));4218 result = false;4219 }4220 }4221 4222 Bool ok = XXSendClientMessage (dpy, aWId, "_NET_ACTIVE_WINDOW");4223 result &= !!ok;4224 4225 XRaiseWindow (dpy, aWId);4226 4227 #else4228 4229 NOREF (aWId);4230 NOREF (aSwitchDesktop);4231 AssertFailed();4232 result = false;4233 4234 #endif4235 4236 if (!result)4237 LogWarningFunc (("Couldn't activate aWId=%08X\n", aWId));4238 4239 return result;4240 }4241 4242 /**4243 * Removes the accelerator mark (the ampersand symbol) from the given string4244 * and returns the result. The string is supposed to be a menu item's text4245 * that may (or may not) contain the accelerator mark.4246 *4247 * In order to support accelerators used in non-alphabet languages4248 * (e.g. Japanese) that has a form of "(&<L>)" (where <L> is a latin letter),4249 * this method first searches for this pattern and, if found, removes it as a4250 * whole. If such a pattern is not found, then the '&' character is simply4251 * removed from the string.4252 *4253 * @note This function removes only the first occurrence of the accelerator4254 * mark.4255 *4256 * @param aText Menu item's text to remove the accelerator mark from.4257 *4258 * @return The resulting string.4259 */4260 /* static */4261 QString VBoxGlobal::removeAccelMark (const QString &aText)4262 {4263 QString result = aText;4264 4265 QRegExp accel ("\\(&[a-zA-Z]\\)");4266 int pos = accel.indexIn (result);4267 if (pos >= 0)4268 result.remove (pos, accel.cap().length());4269 else4270 {4271 pos = result.indexOf ('&');4272 if (pos >= 0)4273 result.remove (pos, 1);4274 }4275 4276 return result;4277 }4278 4279 /* static */4280 QString VBoxGlobal::insertKeyToActionText(const QString &strText, const QString &strKey)4281 {4282 #ifdef Q_WS_MAC4283 QString pattern("%1 (Host+%2)");4284 #else4285 QString pattern("%1 \tHost+%2");4286 #endif4287 if ( strKey.isEmpty()4288 || strKey.compare("None", Qt::CaseInsensitive) == 0)4289 return strText;4290 else4291 return pattern.arg(strText).arg(QKeySequence(strKey).toString(QKeySequence::NativeText));4292 }4293 4294 /* static */4295 QString VBoxGlobal::extractKeyFromActionText (const QString &aText)4296 {4297 QString key;4298 #ifdef Q_WS_MAC4299 QRegExp re (".* \\(Host\\+(.+)\\)");4300 #else4301 QRegExp re (".* \\t\\Host\\+(.+)");4302 #endif4303 if (re.exactMatch (aText))4304 key = re.cap (1);4305 return key;4306 }4307 4308 /**4309 * Joins two pixmaps horizontally with 2px space between them and returns the4310 * result.4311 *4312 * @param aPM1 Left pixmap.4313 * @param aPM2 Right pixmap.4314 */4315 /* static */4316 QPixmap VBoxGlobal::joinPixmaps (const QPixmap &aPM1, const QPixmap &aPM2)4317 {4318 if (aPM1.isNull())4319 return aPM2;4320 if (aPM2.isNull())4321 return aPM1;4322 4323 QPixmap result (aPM1.width() + aPM2.width() + 2,4324 qMax (aPM1.height(), aPM2.height()));4325 result.fill (Qt::transparent);4326 4327 QPainter painter (&result);4328 painter.drawPixmap (0, 0, aPM1);4329 painter.drawPixmap (aPM1.width() + 2, result.height() - aPM2.height(), aPM2);4330 painter.end();4331 4332 return result;4333 }4334 4335 /**4336 * Searches for a widget that with @a aName (if it is not NULL) which inherits4337 * @a aClassName (if it is not NULL) and among children of @a aParent. If @a4338 * aParent is NULL, all top-level widgets are searched. If @a aRecursive is4339 * true, child widgets are recursively searched as well.4340 */4341 /* static */4342 QWidget *VBoxGlobal::findWidget (QWidget *aParent, const char *aName,4343 const char *aClassName /* = NULL */,4344 bool aRecursive /* = false */)4345 {4346 if (aParent == NULL)4347 {4348 QWidgetList list = QApplication::topLevelWidgets();4349 foreach(QWidget *w, list)4350 {4351 if ((!aName || strcmp (w->objectName().toAscii().constData(), aName) == 0) &&4352 (!aClassName || strcmp (w->metaObject()->className(), aClassName) == 0))4353 return w;4354 if (aRecursive)4355 {4356 w = findWidget (w, aName, aClassName, aRecursive);4357 if (w)4358 return w;4359 }4360 }4361 return NULL;4362 }4363 4364 /* Find the first children of aParent with the appropriate properties.4365 * Please note that this call is recursively. */4366 QList<QWidget *> list = qFindChildren<QWidget *> (aParent, aName);4367 foreach(QWidget *child, list)4368 {4369 if (!aClassName || strcmp (child->metaObject()->className(), aClassName) == 0)4370 return child;4371 }4372 return NULL;4373 }4374 4375 /**4376 * Figures out which medium formats are currently supported by VirtualBox for4377 * the given device type.4378 * Returned is a list of pairs with the form4379 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>.4380 */4381 /* static */4382 QList <QPair <QString, QString> > VBoxGlobal::MediumBackends(KDeviceType enmType)4383 {4384 CSystemProperties systemProperties = vboxGlobal().virtualBox().GetSystemProperties();4385 QVector<CMediumFormat> mediumFormats = systemProperties.GetMediumFormats();4386 QList< QPair<QString, QString> > backendPropList;4387 for (int i = 0; i < mediumFormats.size(); ++ i)4388 {4389 /* File extensions */4390 QVector <QString> fileExtensions;4391 QVector <KDeviceType> deviceTypes;4392 4393 mediumFormats [i].DescribeFileExtensions(fileExtensions, deviceTypes);4394 4395 QStringList f;4396 for (int a = 0; a < fileExtensions.size(); ++ a)4397 if (deviceTypes [a] == enmType)4398 f << QString ("*.%1").arg (fileExtensions [a]);4399 /* Create a pair out of the backend description and all suffix's. */4400 if (!f.isEmpty())4401 backendPropList << QPair<QString, QString> (mediumFormats [i].GetName(), f.join(" "));4402 }4403 return backendPropList;4404 }4405 4406 /**4407 * Figures out which hard disk formats are currently supported by VirtualBox.4408 * Returned is a list of pairs with the form4409 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>.4410 */4411 /* static */4412 QList <QPair <QString, QString> > VBoxGlobal::HDDBackends()4413 {4414 return MediumBackends(KDeviceType_HardDisk);4415 }4416 4417 /**4418 * Figures out which CD/DVD disk formats are currently supported by VirtualBox.4419 * Returned is a list of pairs with the form4420 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>.4421 */4422 /* static */4423 QList <QPair <QString, QString> > VBoxGlobal::DVDBackends()4424 {4425 return MediumBackends(KDeviceType_DVD);4426 }4427 4428 /**4429 * Figures out which floppy disk formats are currently supported by VirtualBox.4430 * Returned is a list of pairs with the form4431 * <tt>{"Backend Name", "*.suffix1 .suffix2 ..."}</tt>.4432 */4433 /* static */4434 QList <QPair <QString, QString> > VBoxGlobal::FloppyBackends()4435 {4436 return MediumBackends(KDeviceType_Floppy);4437 }4438 4439 /* static */4440 QString VBoxGlobal::documentsPath()4441 {4442 QString path;4443 #if QT_VERSION < 0x0404004444 path = QDir::homePath();4445 #else4446 path = QDesktopServices::storageLocation (QDesktopServices::DocumentsLocation);4447 #endif4448 4449 /* Make sure the path exists */4450 QDir dir (path);4451 if (dir.exists())4452 return QDir::cleanPath (dir.canonicalPath());4453 else4454 {4455 dir.setPath (QDir::homePath() + "/Documents");4456 if (dir.exists())4457 return QDir::cleanPath (dir.canonicalPath());4458 else4459 return QDir::homePath();4460 }4461 }4462 4463 #ifdef VBOX_WITH_VIDEOHWACCEL4464 /* static */4465 bool VBoxGlobal::isAcceleration2DVideoAvailable()4466 {4467 return VBoxQGLOverlay::isAcceleration2DVideoAvailable();4468 }4469 4470 /** additional video memory required for the best 2D support performance4471 * total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory */4472 /* static */4473 quint64 VBoxGlobal::required2DOffscreenVideoMemory()4474 {4475 return VBoxQGLOverlay::required2DOffscreenVideoMemory();4476 }4477 4478 #endif4479 4480 #ifdef VBOX_WITH_CRHGSMI4481 /* static */4482 quint64 VBoxGlobal::required3DWddmOffscreenVideoMemory(CMachine *aMachine /* = 0 */, int cMonitors /* = 1 */)4483 {4484 cMonitors = RT_MAX(cMonitors, 1);4485 quint64 cbSize = VBoxGlobal::requiredVideoMemory(aMachine, 1); /* why not cMonitors? */4486 cbSize += 64 * _1M;4487 return cbSize;4488 }4489 #endif4490 4491 #ifdef Q_WS_MAC4492 bool VBoxGlobal::isSheetWindowsAllowed(QWidget *pParent) const4493 {4494 if (!( qobject_cast<UIMachineWindowFullscreen*>(pParent)4495 || qobject_cast<UIMachineWindowSeamless*>(pParent)))4496 return true;4497 return false;4498 }4499 #endif /* Q_WS_MAC */4500 4501 // Public slots4502 ////////////////////////////////////////////////////////////////////////////////4503 4504 /**4505 * Opens the specified URL using OS/Desktop capabilities.4506 *4507 * @param aURL URL to open4508 *4509 * @return true on success and false otherwise4510 */4511 bool VBoxGlobal::openURL (const QString &aURL)4512 {4513 /* Service event */4514 class ServiceEvent : public QEvent4515 {4516 public:4517 4518 ServiceEvent (bool aResult) : QEvent (QEvent::User), mResult (aResult) {}4519 4520 bool result() const { return mResult; }4521 4522 private:4523 4524 bool mResult;4525 };4526 4527 /* Service-Client object */4528 class ServiceClient : public QEventLoop4529 {4530 public:4531 4532 ServiceClient() : mResult (false) {}4533 4534 bool result() const { return mResult; }4535 4536 private:4537 4538 bool event (QEvent *aEvent)4539 {4540 if (aEvent->type() == QEvent::User)4541 {4542 ServiceEvent *pEvent = static_cast <ServiceEvent*> (aEvent);4543 mResult = pEvent->result();4544 pEvent->accept();4545 quit();4546 return true;4547 }4548 return false;4549 }4550 4551 bool mResult;4552 };4553 4554 /* Service-Server object */4555 class ServiceServer : public QThread4556 {4557 public:4558 4559 ServiceServer (ServiceClient &aClient, const QString &sURL)4560 : mClient (aClient), mURL (sURL) {}4561 4562 private:4563 4564 void run()4565 {4566 QApplication::postEvent (&mClient, new ServiceEvent (QDesktopServices::openUrl (mURL)));4567 }4568 4569 ServiceClient &mClient;4570 const QString &mURL;4571 };4572 4573 ServiceClient client;4574 ServiceServer server (client, aURL);4575 server.start();4576 client.exec();4577 server.wait();4578 4579 bool result = client.result();4580 4581 if (!result)4582 vboxProblem().cannotOpenURL (aURL);4583 4584 return result;4585 }4586 4587 /**4588 * Shows the VirtualBox registration dialog.4589 *4590 * @note that this method is not part of VBoxProblemReporter (like e.g.4591 * VBoxProblemReporter::showHelpAboutDialog()) because it is tied to4592 * VBoxCallback::OnExtraDataChange() handling performed by VBoxGlobal.4593 *4594 * @param aForce4595 */4596 void VBoxGlobal::showRegistrationDialog (bool aForce)4597 {4598 NOREF(aForce);4599 #ifdef VBOX_WITH_REGISTRATION4600 if (!aForce && !UIRegistrationWzd::hasToBeShown())4601 return;4602 4603 if (mRegDlg)4604 {4605 /* Show the already opened registration dialog */4606 mRegDlg->setWindowState (mRegDlg->windowState() & ~Qt::WindowMinimized);4607 mRegDlg->raise();4608 mRegDlg->activateWindow();4609 }4610 else4611 {4612 /* Store the ID of the main window to ensure that only one4613 * registration dialog is shown at a time. Due to manipulations with4614 * OnExtraDataCanChange() and OnExtraDataChange() signals, this extra4615 * data item acts like an inter-process mutex, so the first process4616 * that attempts to set it will win, the rest will get a failure from4617 * the SetExtraData() call. */4618 mVBox.SetExtraData (VBoxDefs::GUI_RegistrationDlgWinID,4619 QString ("%1").arg ((qulonglong) mMainWindow->winId()));4620 4621 if (mVBox.isOk())4622 {4623 /* We've got the "mutex", create a new registration dialog */4624 UIRegistrationWzd *dlg = new UIRegistrationWzd (&mRegDlg);4625 dlg->setAttribute (Qt::WA_DeleteOnClose);4626 Assert (dlg == mRegDlg);4627 mRegDlg->show();4628 }4629 }4630 #endif4631 }4632 4633 /**4634 * Shows the VirtualBox version check & update dialog.4635 *4636 * @note that this method is not part of VBoxProblemReporter (like e.g.4637 * VBoxProblemReporter::showHelpAboutDialog()) because it is tied to4638 * VBoxCallback::OnExtraDataChange() handling performed by VBoxGlobal.4639 *4640 * @param aForce4641 */4642 void VBoxGlobal::showUpdateDialog (bool aForce)4643 {4644 /* Silently check in one day after current time-stamp */4645 QTimer::singleShot (24 /* hours */ * 60 /* minutes */ *4646 60 /* seconds */ * 1000 /* milliseconds */,4647 this, SLOT (perDayNewVersionNotifier()));4648 4649 bool isNecessary = VBoxUpdateDlg::isNecessary();4650 4651 if (!aForce && !isNecessary)4652 return;4653 4654 if (mUpdDlg)4655 {4656 if (!mUpdDlg->isHidden())4657 {4658 mUpdDlg->setWindowState (mUpdDlg->windowState() & ~Qt::WindowMinimized);4659 mUpdDlg->raise();4660 mUpdDlg->activateWindow();4661 }4662 }4663 else4664 {4665 /* Store the ID of the main window to ensure that only one4666 * update dialog is shown at a time. Due to manipulations with4667 * OnExtraDataCanChange() and OnExtraDataChange() signals, this extra4668 * data item acts like an inter-process mutex, so the first process4669 * that attempts to set it will win, the rest will get a failure from4670 * the SetExtraData() call. */4671 mVBox.SetExtraData (VBoxDefs::GUI_UpdateDlgWinID,4672 QString ("%1").arg ((qulonglong) mMainWindow->winId()));4673 4674 if (mVBox.isOk())4675 {4676 /* We've got the "mutex", create a new update dialog */4677 VBoxUpdateDlg *dlg = new VBoxUpdateDlg (&mUpdDlg, aForce, 0);4678 dlg->setAttribute (Qt::WA_DeleteOnClose);4679 Assert (dlg == mUpdDlg);4680 4681 /* Update dialog always in background mode for now.4682 * if (!aForce && isAutomatic) */4683 mUpdDlg->search();4684 /* else mUpdDlg->show(); */4685 }4686 }4687 }4688 4689 void VBoxGlobal::perDayNewVersionNotifier()4690 {4691 showUpdateDialog (false /* force show? */);4692 }4693 4694 void VBoxGlobal::sltGUILanguageChange(QString strLang)4695 {4696 loadLanguage(strLang);4697 }4698 4699 // Protected members4700 ////////////////////////////////////////////////////////////////////////////////4701 4702 bool VBoxGlobal::event (QEvent *e)4703 {4704 switch (e->type())4705 {4706 case VBoxDefs::MediaEnumEventType:4707 {4708 VBoxMediaEnumEvent *ev = (VBoxMediaEnumEvent*) e;4709 4710 if (!ev->mLast)4711 {4712 if (ev->mMedium.state() == KMediumState_Inaccessible &&4713 !ev->mMedium.result().isOk())4714 vboxProblem().cannotGetMediaAccessibility (ev->mMedium);4715 Assert (ev->mIterator != mMediaList.end());4716 *(ev->mIterator) = ev->mMedium;4717 emit mediumEnumerated (*ev->mIterator);4718 ++ ev->mIterator;4719 }4720 else4721 {4722 /* the thread has posted the last message, wait for termination */4723 mMediaEnumThread->wait();4724 delete mMediaEnumThread;4725 mMediaEnumThread = 0;4726 emit mediumEnumFinished (mMediaList);4727 }4728 4729 return true;4730 }4731 4732 default:4733 break;4734 }4735 4736 return QObject::event (e);4737 }4738 4739 bool VBoxGlobal::eventFilter (QObject *aObject, QEvent *aEvent)4740 {4741 if (aEvent->type() == QEvent::LanguageChange &&4742 aObject->isWidgetType() &&4743 static_cast <QWidget *> (aObject)->isTopLevel())4744 {4745 /* Catch the language change event before any other widget gets it in4746 * order to invalidate cached string resources (like the details view4747 * templates) that may be used by other widgets. */4748 QWidgetList list = QApplication::topLevelWidgets();4749 if (list.first() == aObject)4750 {4751 /* call this only once per every language change (see4752 * QApplication::installTranslator() for details) */4753 retranslateUi();4754 }4755 }4756 4757 return QObject::eventFilter (aObject, aEvent);4758 }4759 4760 #ifdef VBOX_WITH_DEBUGGER_GUI4761 4762 bool VBoxGlobal::isDebuggerEnabled(CMachine &aMachine)4763 {4764 return isDebuggerWorker(&mDbgEnabled, aMachine, VBoxDefs::GUI_DbgEnabled);4765 }4766 4767 bool VBoxGlobal::isDebuggerAutoShowEnabled(CMachine &aMachine)4768 {4769 return isDebuggerWorker(&mDbgAutoShow, aMachine, VBoxDefs::GUI_DbgAutoShow);4770 }4771 4772 bool VBoxGlobal::isDebuggerAutoShowCommandLineEnabled(CMachine &aMachine)4773 {4774 return isDebuggerWorker(&mDbgAutoShowCommandLine, aMachine, VBoxDefs::GUI_DbgAutoShow);4775 }4776 4777 bool VBoxGlobal::isDebuggerAutoShowStatisticsEnabled(CMachine &aMachine)4778 {4779 return isDebuggerWorker(&mDbgAutoShowStatistics, aMachine, VBoxDefs::GUI_DbgAutoShow);4780 }4781 4782 #endif /* VBOX_WITH_DEBUGGER_GUI */4783 4784 // Private members4785 ////////////////////////////////////////////////////////////////////////////////4786 4787 bool VBoxGlobal::processArgs()4788 {4789 bool fResult = false;4790 QStringList args = qApp->arguments();4791 QList<QUrl> list;4792 for (int i = 1; i < args.size(); ++i)4793 {4794 /* We break out after the first parameter, cause there could be4795 parameters with arguments (e.g. --comment comment). */4796 if (args.at(i).startsWith("-"))4797 break;4798 #ifdef Q_WS_MAC4799 QString strArg = ::darwinResolveAlias(args.at(i));4800 #else /* Q_WS_MAC */4801 QString strArg = args.at(i);4802 #endif /* !Q_WS_MAC */4803 if ( !strArg.isEmpty()4804 && QFile::exists(strArg))4805 list << QUrl::fromLocalFile(strArg);4806 }4807 if (!list.isEmpty())4808 {4809 for (int i = 0; i < list.size(); ++i)4810 {4811 const QString& strFile = list.at(i).toLocalFile();4812 if (VBoxGlobal::hasAllowedExtension(strFile, VBoxDefs::VBoxFileExts))4813 {4814 CVirtualBox vbox = vboxGlobal().virtualBox();4815 CMachine machine = vbox.FindMachine(strFile);4816 if (!machine.isNull())4817 {4818 fResult = true;4819 launchMachine(machine);4820 /* Remove from the arg list. */4821 list.removeAll(strFile);4822 }4823 }4824 }4825 }4826 if (!list.isEmpty())4827 {4828 m_ArgUrlList = list;4829 QTimer::singleShot(0, &vboxGlobal().selectorWnd(), SLOT(sltOpenUrls()));4830 }4831 return fResult;4832 }4833 4834 void VBoxGlobal::init()4835 {4836 #ifdef DEBUG4837 mVerString += " [DEBUG]";4838 #endif4839 4840 HRESULT rc = COMBase::InitializeCOM(true);4841 if (FAILED (rc))4842 {4843 vboxProblem().cannotInitCOM (rc);4844 return;4845 }4846 4847 mVBox.createInstance (CLSID_VirtualBox);4848 if (!mVBox.isOk())4849 {4850 vboxProblem().cannotCreateVirtualBox (mVBox);4851 return;4852 }4853 4854 /* create default non-null global settings */4855 gset = VBoxGlobalSettings (false);4856 4857 /* try to load global settings */4858 gset.load (mVBox);4859 if (!mVBox.isOk() || !gset)4860 {4861 vboxProblem().cannotLoadGlobalConfig (mVBox, gset.lastError());4862 return;4863 }4864 4865 /* Load the customized language as early as possible to get possible error4866 * messages translated */4867 QString sLanguageId = gset.languageId();4868 if (!sLanguageId.isNull())4869 loadLanguage (sLanguageId);4870 4871 retranslateUi();4872 4873 connect(gEDataEvents, SIGNAL(sigGUILanguageChange(QString)),4874 this, SLOT(sltGUILanguageChange(QString)));4875 4876 #ifdef VBOX_GUI_WITH_SYSTRAY4877 {4878 /* Increase open Fe/Qt4 windows reference count. */4879 int c = mVBox.GetExtraData (VBoxDefs::GUI_MainWindowCount).toInt() + 1;4880 AssertMsgReturnVoid ((c >= 0) || (mVBox.isOk()),4881 ("Something went wrong with the window reference count!"));4882 mVBox.SetExtraData (VBoxDefs::GUI_MainWindowCount, QString ("%1").arg (c));4883 mIncreasedWindowCounter = mVBox.isOk();4884 AssertReturnVoid (mIncreasedWindowCounter);4885 }4886 #endif4887 4888 /* Initialize guest OS Type list. */4889 CGuestOSTypeVector coll = mVBox.GetGuestOSTypes();4890 int osTypeCount = coll.size();4891 AssertMsg (osTypeCount > 0, ("Number of OS types must not be zero"));4892 if (osTypeCount > 0)4893 {4894 /* Here we assume the 'Other' type is always the first, so we4895 * remember it and will append it to the list when finished. */4896 CGuestOSType otherType = coll[0];4897 QString otherFamilyId (otherType.GetFamilyId());4898 4899 /* Fill the lists with all the available OS Types except4900 * the 'Other' type, which will be appended. */4901 for (int i = 1; i < coll.size(); ++i)4902 {4903 CGuestOSType os = coll[i];4904 QString familyId (os.GetFamilyId());4905 if (!mFamilyIDs.contains (familyId))4906 {4907 mFamilyIDs << familyId;4908 mTypes << QList <CGuestOSType> ();4909 }4910 mTypes [mFamilyIDs.indexOf (familyId)].append (os);4911 }4912 4913 /* Append the 'Other' OS Type to the end of list. */4914 if (!mFamilyIDs.contains (otherFamilyId))4915 {4916 mFamilyIDs << otherFamilyId;4917 mTypes << QList <CGuestOSType> ();4918 }4919 mTypes [mFamilyIDs.indexOf (otherFamilyId)].append (otherType);4920 }4921 4922 /* Fill in OS type icon dictionary. */4923 static const char *kOSTypeIcons [][2] =4924 {4925 {"Other", ":/os_other.png"},4926 {"DOS", ":/os_dos.png"},4927 {"Netware", ":/os_netware.png"},4928 {"L4", ":/os_l4.png"},4929 {"Windows31", ":/os_win31.png"},4930 {"Windows95", ":/os_win95.png"},4931 {"Windows98", ":/os_win98.png"},4932 {"WindowsMe", ":/os_winme.png"},4933 {"WindowsNT4", ":/os_winnt4.png"},4934 {"Windows2000", ":/os_win2k.png"},4935 {"WindowsXP", ":/os_winxp.png"},4936 {"WindowsXP_64", ":/os_winxp_64.png"},4937 {"Windows2003", ":/os_win2k3.png"},4938 {"Windows2003_64", ":/os_win2k3_64.png"},4939 {"WindowsVista", ":/os_winvista.png"},4940 {"WindowsVista_64", ":/os_winvista_64.png"},4941 {"Windows2008", ":/os_win2k8.png"},4942 {"Windows2008_64", ":/os_win2k8_64.png"},4943 {"Windows7", ":/os_win7.png"},4944 {"Windows7_64", ":/os_win7_64.png"},4945 {"WindowsNT", ":/os_win_other.png"},4946 {"OS2Warp3", ":/os_os2warp3.png"},4947 {"OS2Warp4", ":/os_os2warp4.png"},4948 {"OS2Warp45", ":/os_os2warp45.png"},4949 {"OS2eCS", ":/os_os2ecs.png"},4950 {"OS2", ":/os_os2_other.png"},4951 {"Linux22", ":/os_linux22.png"},4952 {"Linux24", ":/os_linux24.png"},4953 {"Linux24_64", ":/os_linux24_64.png"},4954 {"Linux26", ":/os_linux26.png"},4955 {"Linux26_64", ":/os_linux26_64.png"},4956 {"ArchLinux", ":/os_archlinux.png"},4957 {"ArchLinux_64", ":/os_archlinux_64.png"},4958 {"Debian", ":/os_debian.png"},4959 {"Debian_64", ":/os_debian_64.png"},4960 {"OpenSUSE", ":/os_opensuse.png"},4961 {"OpenSUSE_64", ":/os_opensuse_64.png"},4962 {"Fedora", ":/os_fedora.png"},4963 {"Fedora_64", ":/os_fedora_64.png"},4964 {"Gentoo", ":/os_gentoo.png"},4965 {"Gentoo_64", ":/os_gentoo_64.png"},4966 {"Mandriva", ":/os_mandriva.png"},4967 {"Mandriva_64", ":/os_mandriva_64.png"},4968 {"RedHat", ":/os_redhat.png"},4969 {"RedHat_64", ":/os_redhat_64.png"},4970 {"Turbolinux", ":/os_turbolinux.png"},4971 {"Turbolinux_64", ":/os_turbolinux_64.png"},4972 {"Ubuntu", ":/os_ubuntu.png"},4973 {"Ubuntu_64", ":/os_ubuntu_64.png"},4974 {"Xandros", ":/os_xandros.png"},4975 {"Xandros_64", ":/os_xandros_64.png"},4976 {"Oracle", ":/os_oracle.png"},4977 {"Oracle_64", ":/os_oracle_64.png"},4978 {"Linux", ":/os_linux_other.png"},4979 {"FreeBSD", ":/os_freebsd.png"},4980 {"FreeBSD_64", ":/os_freebsd_64.png"},4981 {"OpenBSD", ":/os_openbsd.png"},4982 {"OpenBSD_64", ":/os_openbsd_64.png"},4983 {"NetBSD", ":/os_netbsd.png"},4984 {"NetBSD_64", ":/os_netbsd_64.png"},4985 {"Solaris", ":/os_solaris.png"},4986 {"Solaris_64", ":/os_solaris_64.png"},4987 {"OpenSolaris", ":/os_oraclesolaris.png"},4988 {"OpenSolaris_64", ":/os_oraclesolaris_64.png"},4989 {"QNX", ":/os_qnx.png"},4990 {"MacOS", ":/os_macosx.png"},4991 {"MacOS_64", ":/os_macosx_64.png"},4992 {"JRockitVE", ":/os_jrockitve.png"},4993 };4994 for (uint n = 0; n < SIZEOF_ARRAY (kOSTypeIcons); ++ n)4995 {4996 mOsTypeIcons.insert (kOSTypeIcons [n][0],4997 new QPixmap (kOSTypeIcons [n][1]));4998 }4999 5000 /* fill in VM state icon map */5001 static const struct5002 {5003 KMachineState state;5004 const char *name;5005 }5006 kVMStateIcons[] =5007 {5008 {KMachineState_Null, NULL},5009 {KMachineState_PoweredOff, ":/state_powered_off_16px.png"},5010 {KMachineState_Saved, ":/state_saved_16px.png"},5011 {KMachineState_Aborted, ":/state_aborted_16px.png"},5012 {KMachineState_Teleported, ":/state_saved_16px.png"}, /** @todo Live Migration: New icon? (not really important) */5013 {KMachineState_Running, ":/state_running_16px.png"},5014 {KMachineState_Paused, ":/state_paused_16px.png"},5015 {KMachineState_Teleporting, ":/state_running_16px.png"}, /** @todo Live Migration: New icon? (not really important) */5016 {KMachineState_LiveSnapshotting, ":/state_running_16px.png"}, /** @todo Live Migration: New icon? (not really important) */5017 {KMachineState_Stuck, ":/state_stuck_16px.png"},5018 {KMachineState_Starting, ":/state_running_16px.png"}, /// @todo (dmik) separate icon?5019 {KMachineState_Stopping, ":/state_running_16px.png"}, /// @todo (dmik) separate icon?5020 {KMachineState_Saving, ":/state_saving_16px.png"},5021 {KMachineState_Restoring, ":/state_restoring_16px.png"},5022 {KMachineState_TeleportingPausedVM, ":/state_saving_16px.png"}, /** @todo Live Migration: New icon? (not really important) */5023 {KMachineState_TeleportingIn, ":/state_restoring_16px.png"}, /** @todo Live Migration: New icon? (not really important) */5024 {KMachineState_RestoringSnapshot, ":/state_discarding_16px.png"},5025 {KMachineState_DeletingSnapshot, ":/state_discarding_16px.png"},5026 {KMachineState_DeletingSnapshotOnline, ":/state_discarding_16px.png"}, /// @todo live snapshot deletion: new icon?5027 {KMachineState_DeletingSnapshotPaused, ":/state_discarding_16px.png"}, /// @todo live snapshot deletion: new icon?5028 {KMachineState_SettingUp, ":/settings_16px.png"},5029 };5030 for (uint n = 0; n < SIZEOF_ARRAY (kVMStateIcons); n ++)5031 {5032 mVMStateIcons.insert (kVMStateIcons [n].state,5033 new QPixmap (kVMStateIcons [n].name));5034 }5035 5036 /* initialize state colors map */5037 mVMStateColors.insert (KMachineState_Null, new QColor (Qt::red));5038 mVMStateColors.insert (KMachineState_PoweredOff, new QColor (Qt::gray));5039 mVMStateColors.insert (KMachineState_Saved, new QColor (Qt::yellow));5040 mVMStateColors.insert (KMachineState_Aborted, new QColor (Qt::darkRed));5041 mVMStateColors.insert (KMachineState_Teleported, new QColor (Qt::red));5042 mVMStateColors.insert (KMachineState_Running, new QColor (Qt::green));5043 mVMStateColors.insert (KMachineState_Paused, new QColor (Qt::darkGreen));5044 mVMStateColors.insert (KMachineState_Stuck, new QColor (Qt::darkMagenta));5045 mVMStateColors.insert (KMachineState_Teleporting, new QColor (Qt::blue));5046 mVMStateColors.insert (KMachineState_LiveSnapshotting, new QColor (Qt::green));5047 mVMStateColors.insert (KMachineState_Starting, new QColor (Qt::green));5048 mVMStateColors.insert (KMachineState_Stopping, new QColor (Qt::green));5049 mVMStateColors.insert (KMachineState_Saving, new QColor (Qt::green));5050 mVMStateColors.insert (KMachineState_Restoring, new QColor (Qt::green));5051 mVMStateColors.insert (KMachineState_TeleportingPausedVM, new QColor (Qt::blue));5052 mVMStateColors.insert (KMachineState_TeleportingIn, new QColor (Qt::blue));5053 mVMStateColors.insert (KMachineState_RestoringSnapshot, new QColor (Qt::green));5054 mVMStateColors.insert (KMachineState_DeletingSnapshot, new QColor (Qt::green));5055 mVMStateColors.insert (KMachineState_DeletingSnapshotOnline, new QColor (Qt::green));5056 mVMStateColors.insert (KMachineState_DeletingSnapshotPaused, new QColor (Qt::darkGreen));5057 mVMStateColors.insert (KMachineState_SettingUp, new QColor (Qt::green));5058 5059 /* online/offline snapshot icons */5060 mOfflineSnapshotIcon = QPixmap (":/offline_snapshot_16px.png");5061 mOnlineSnapshotIcon = QPixmap (":/online_snapshot_16px.png");5062 5063 qApp->installEventFilter (this);5064 5065 /* process command line */5066 5067 bool bForceSeamless = false;5068 bool bForceFullscreen = false;5069 5070 vm_render_mode_str = RTStrDup (virtualBox()5071 .GetExtraData (VBoxDefs::GUI_RenderMode).toAscii().constData());5072 5073 #ifdef Q_WS_X115074 mIsKWinManaged = X11IsWindowManagerKWin();5075 #endif5076 5077 #ifdef VBOX_WITH_DEBUGGER_GUI5078 # ifdef VBOX_WITH_DEBUGGER_GUI_MENU5079 initDebuggerVar(&mDbgEnabled, "VBOX_GUI_DBG_ENABLED", VBoxDefs::GUI_DbgEnabled, true);5080 # else5081 initDebuggerVar(&mDbgEnabled, "VBOX_GUI_DBG_ENABLED", VBoxDefs::GUI_DbgEnabled, false);5082 # endif5083 initDebuggerVar(&mDbgAutoShow, "VBOX_GUI_DBG_AUTO_SHOW", VBoxDefs::GUI_DbgAutoShow, false);5084 mDbgAutoShowCommandLine = mDbgAutoShowStatistics = mDbgAutoShow;5085 mStartPaused = false;5086 #endif5087 5088 mShowStartVMErrors = true;5089 bool startVM = false;5090 QString vmNameOrUuid;5091 5092 int argc = qApp->argc();5093 int i = 1;5094 while (i < argc)5095 {5096 const char *arg = qApp->argv() [i];5097 /* NOTE: the check here must match the corresponding check for the5098 * options to start a VM in main.cpp and hardenedmain.cpp exactly,5099 * otherwise there will be weird error messages. */5100 if ( !::strcmp (arg, "--startvm")5101 || !::strcmp (arg, "-startvm"))5102 {5103 if (++i < argc)5104 {5105 vmNameOrUuid = QString (qApp->argv() [i]);5106 startVM = true;5107 }5108 }5109 #ifdef VBOX_GUI_WITH_PIDFILE5110 else if (!::strcmp(arg, "-pidfile") || !::strcmp(arg, "--pidfile"))5111 {5112 if (++i < argc)5113 m_strPidfile = QString(qApp->argv()[i]);5114 }5115 #endif /* VBOX_GUI_WITH_PIDFILE */5116 else if (!::strcmp(arg, "-seamless") || !::strcmp(arg, "--seamless"))5117 {5118 bForceSeamless = true;5119 }5120 else if (!::strcmp(arg, "-fullscreen") || !::strcmp(arg, "--fullscreen"))5121 {5122 bForceFullscreen = true;5123 }5124 #ifdef VBOX_GUI_WITH_SYSTRAY5125 else if (!::strcmp (arg, "-systray") || !::strcmp (arg, "--systray"))5126 {5127 mIsTrayMenu = true;5128 }5129 #endif5130 else if (!::strcmp (arg, "-comment") || !::strcmp (arg, "--comment"))5131 {5132 ++i;5133 }5134 else if (!::strcmp (arg, "-rmode") || !::strcmp (arg, "--rmode"))5135 {5136 if (++i < argc)5137 vm_render_mode_str = qApp->argv() [i];5138 }5139 else if (!::strcmp (arg, "--no-startvm-errormsgbox"))5140 {5141 mShowStartVMErrors = false;5142 }5143 #ifdef VBOX_WITH_DEBUGGER_GUI5144 else if (!::strcmp (arg, "-dbg") || !::strcmp (arg, "--dbg"))5145 {5146 setDebuggerVar(&mDbgEnabled, true);5147 }5148 else if (!::strcmp( arg, "-debug") || !::strcmp (arg, "--debug"))5149 {5150 setDebuggerVar(&mDbgEnabled, true);5151 setDebuggerVar(&mDbgAutoShow, true);5152 setDebuggerVar(&mDbgAutoShowCommandLine, true);5153 setDebuggerVar(&mDbgAutoShowStatistics, true);5154 mStartPaused = true;5155 }5156 else if (!::strcmp (arg, "--debug-command-line"))5157 {5158 setDebuggerVar(&mDbgEnabled, true);5159 setDebuggerVar(&mDbgAutoShow, true);5160 setDebuggerVar(&mDbgAutoShowCommandLine, true);5161 mStartPaused = true;5162 }5163 else if (!::strcmp (arg, "--debug-statistics"))5164 {5165 setDebuggerVar(&mDbgEnabled, true);5166 setDebuggerVar(&mDbgAutoShow, true);5167 setDebuggerVar(&mDbgAutoShowStatistics, true);5168 mStartPaused = true;5169 }5170 else if (!::strcmp (arg, "-no-debug") || !::strcmp (arg, "--no-debug"))5171 {5172 setDebuggerVar(&mDbgEnabled, false);5173 setDebuggerVar(&mDbgAutoShow, false);5174 setDebuggerVar(&mDbgAutoShowCommandLine, false);5175 setDebuggerVar(&mDbgAutoShowStatistics, false);5176 }5177 /* Not quite debug options, but they're only useful with the debugger bits. */5178 else if (!::strcmp (arg, "--start-paused"))5179 {5180 mStartPaused = true;5181 }5182 else if (!::strcmp (arg, "--start-running"))5183 {5184 mStartPaused = false;5185 }5186 #endif5187 /** @todo add an else { msgbox(syntax error); exit(1); } here, pretty please... */5188 i++;5189 }5190 5191 if (startVM)5192 {5193 QUuid uuid = QUuid(vmNameOrUuid);5194 if (!uuid.isNull())5195 {5196 vmUuid = vmNameOrUuid;5197 }5198 else5199 {5200 CMachine m = mVBox.FindMachine (vmNameOrUuid);5201 if (m.isNull())5202 {5203 if (showStartVMErrors())5204 vboxProblem().cannotFindMachineByName (mVBox, vmNameOrUuid);5205 return;5206 }5207 vmUuid = m.GetId();5208 }5209 }5210 5211 if (bForceSeamless && !vmUuid.isEmpty())5212 {5213 mVBox.FindMachine(vmUuid).SetExtraData(VBoxDefs::GUI_Seamless, "on");5214 }5215 else if (bForceFullscreen && !vmUuid.isEmpty())5216 {5217 mVBox.FindMachine(vmUuid).SetExtraData(VBoxDefs::GUI_Fullscreen, "on");5218 }5219 5220 vm_render_mode = vboxGetRenderMode (vm_render_mode_str);5221 5222 #ifdef VBOX_WITH_DEBUGGER_GUI5223 /* setup the debugger gui. */5224 if (RTEnvExist("VBOX_GUI_NO_DEBUGGER"))5225 mDbgEnabled = mDbgAutoShow = mDbgAutoShowCommandLine = mDbgAutoShowStatistics = false;5226 if (mDbgEnabled)5227 {5228 RTERRINFOSTATIC ErrInfo;5229 RTErrInfoInitStatic(&ErrInfo);5230 int vrc = SUPR3HardenedLdrLoadAppPriv("VBoxDbg", &mhVBoxDbg, RTLDRLOAD_FLAGS_LOCAL, &ErrInfo.Core);5231 if (RT_FAILURE(vrc))5232 {5233 mhVBoxDbg = NIL_RTLDRMOD;5234 mDbgAutoShow = mDbgAutoShowCommandLine = mDbgAutoShowStatistics = false;5235 LogRel(("Failed to load VBoxDbg, rc=%Rrc - %s\n", vrc, ErrInfo.Core.pszMsg));5236 }5237 }5238 #endif5239 5240 mValid = true;5241 5242 /* Cache IMedium data.5243 * There could be no used mediums at all,5244 * but this method should be run anyway just to enumerate null VBoxMedium object,5245 * used by some VBox smart widgets, like VBoxMediaComboBox: */5246 vboxGlobal().startEnumeratingMedia();5247 }5248 5249 5250 /** @internal5251 *5252 * This method should be never called directly. It is called automatically5253 * when the application terminates.5254 */5255 void VBoxGlobal::cleanup()5256 {5257 /* sanity check */5258 if (!sVBoxGlobalInCleanup)5259 {5260 AssertMsgFailed (("Should never be called directly\n"));5261 return;5262 }5263 5264 #ifdef VBOX_GUI_WITH_SYSTRAY5265 if (mIncreasedWindowCounter)5266 {5267 /* Decrease open Fe/Qt4 windows reference count. */5268 int c = mVBox.GetExtraData (VBoxDefs::GUI_MainWindowCount).toInt() - 1;5269 AssertMsg ((c >= 0) || (mVBox.isOk()),5270 ("Something went wrong with the window reference count!"));5271 if (c < 0)5272 c = 0; /* Clean up the mess. */5273 mVBox.SetExtraData (VBoxDefs::GUI_MainWindowCount,5274 (c > 0) ? QString ("%1").arg (c) : NULL);5275 AssertWrapperOk (mVBox);5276 if (c == 0)5277 {5278 mVBox.SetExtraData (VBoxDefs::GUI_TrayIconWinID, NULL);5279 AssertWrapperOk (mVBox);5280 }5281 }5282 #endif5283 5284 #ifdef VBOX_GUI_WITH_PIDFILE5285 deletePidfile();5286 #endif5287 5288 /* Destroy our event handlers */5289 UIExtraDataEventHandler::destroy();5290 5291 if (mMediaEnumThread)5292 {5293 /* sVBoxGlobalInCleanup is true here, so just wait for the thread */5294 mMediaEnumThread->wait();5295 delete mMediaEnumThread;5296 mMediaEnumThread = 0;5297 }5298 5299 #ifdef VBOX_WITH_REGISTRATION5300 if (mRegDlg)5301 mRegDlg->close();5302 #endif5303 5304 if (mSelectorWnd)5305 delete mSelectorWnd;5306 if (m_pVirtualMachine)5307 delete m_pVirtualMachine;5308 5309 /* ensure CGuestOSType objects are no longer used */5310 mFamilyIDs.clear();5311 mTypes.clear();5312 5313 /* media list contains a lot of CUUnknown, release them */5314 mMediaList.clear();5315 /* the last step to ensure we don't use COM any more */5316 mVBox.detach();5317 5318 /* There may be VBoxMediaEnumEvent instances still in the message5319 * queue which reference COM objects. Remove them to release those objects5320 * before uninitializing the COM subsystem. */5321 QApplication::removePostedEvents (this);5322 5323 COMBase::CleanupCOM();5324 5325 mValid = false;5326 }5327 5328 #ifdef VBOX_WITH_DEBUGGER_GUI5329 5330 # define VBOXGLOBAL_DBG_CFG_VAR_FALSE (0)5331 # define VBOXGLOBAL_DBG_CFG_VAR_TRUE (1)5332 # define VBOXGLOBAL_DBG_CFG_VAR_MASK (1)5333 # define VBOXGLOBAL_DBG_CFG_VAR_CMD_LINE RT_BIT(3)5334 # define VBOXGLOBAL_DBG_CFG_VAR_DONE RT_BIT(4)5335 5336 /**5337 * Initialize a debugger config variable.5338 *5339 * @param piDbgCfgVar The debugger config variable to init.5340 * @param pszEnvVar The environment variable name relating to this5341 * variable.5342 * @param pszExtraDataName The extra data name relating to this variable.5343 * @param fDefault The default value.5344 */5345 void VBoxGlobal::initDebuggerVar(int *piDbgCfgVar, const char *pszEnvVar, const char *pszExtraDataName, bool fDefault)5346 {5347 QString strEnvValue;5348 char szEnvValue[256];5349 int rc = RTEnvGetEx(RTENV_DEFAULT, pszEnvVar, szEnvValue, sizeof(szEnvValue), NULL);5350 if (RT_SUCCESS(rc))5351 {5352 strEnvValue = QString::fromUtf8(&szEnvValue[0]).toLower().trimmed();5353 if (strEnvValue.isEmpty())5354 strEnvValue = "yes";5355 }5356 else if (rc != VERR_ENV_VAR_NOT_FOUND)5357 strEnvValue = "veto";5358 5359 QString strExtraValue = mVBox.GetExtraData(pszExtraDataName).toLower().trimmed();5360 if (strExtraValue.isEmpty())5361 strExtraValue = QString();5362 5363 if ( strEnvValue.contains("veto") || strExtraValue.contains("veto"))5364 *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_DONE | VBOXGLOBAL_DBG_CFG_VAR_FALSE;5365 else if (strEnvValue.isNull() && strExtraValue.isNull())5366 *piDbgCfgVar = fDefault ? VBOXGLOBAL_DBG_CFG_VAR_TRUE : VBOXGLOBAL_DBG_CFG_VAR_FALSE;5367 else5368 {5369 QString *pStr = !strEnvValue.isEmpty() ? &strEnvValue : &strExtraValue;5370 if ( pStr->startsWith("y") // yes5371 || pStr->startsWith("e") // enabled5372 || pStr->startsWith("t") // true5373 || pStr->startsWith("on")5374 || pStr->toLongLong() != 0)5375 *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_TRUE;5376 else if ( pStr->startsWith("n") // o5377 || pStr->startsWith("d") // disable5378 || pStr->startsWith("f") // false5379 || pStr->startsWith("off")5380 || pStr->contains("veto")5381 || pStr->toLongLong() == 0)5382 *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_FALSE;5383 else5384 {5385 LogFunc(("Ignoring unknown value '%s' for '%s'\n", pStr->toAscii().constData(), pStr == &strEnvValue ? pszEnvVar : pszExtraDataName));5386 *piDbgCfgVar = fDefault ? VBOXGLOBAL_DBG_CFG_VAR_TRUE : VBOXGLOBAL_DBG_CFG_VAR_FALSE;5387 }5388 }5389 }5390 5391 /**5392 * Set a debugger config variable according according to start up argument.5393 *5394 * @param piDbgCfgVar The debugger config variable to set.5395 * @param fState The value from the command line.5396 */5397 void VBoxGlobal::setDebuggerVar(int *piDbgCfgVar, bool fState)5398 {5399 if (!(*piDbgCfgVar & VBOXGLOBAL_DBG_CFG_VAR_DONE))5400 *piDbgCfgVar = (fState ? VBOXGLOBAL_DBG_CFG_VAR_TRUE : VBOXGLOBAL_DBG_CFG_VAR_FALSE)5401 | VBOXGLOBAL_DBG_CFG_VAR_CMD_LINE;5402 }5403 5404 /**5405 * Checks the state of a debugger config variable, updating it with the machine5406 * settings on the first invocation.5407 *5408 * @returns true / false.5409 * @param piDbgCfgVar The debugger config variable to consult.5410 * @param rMachine Reference to the machine object.5411 * @param pszExtraDataName The extra data name relating to this variable.5412 */5413 bool VBoxGlobal::isDebuggerWorker(int *piDbgCfgVar, CMachine &rMachine, const char *pszExtraDataName)5414 {5415 if (!(*piDbgCfgVar & VBOXGLOBAL_DBG_CFG_VAR_DONE) && !rMachine.isNull())5416 {5417 QString str = mVBox.GetExtraData(pszExtraDataName).toLower().trimmed();5418 if (str.contains("veto"))5419 *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_DONE | VBOXGLOBAL_DBG_CFG_VAR_FALSE;5420 else if (str.isEmpty() || (*piDbgCfgVar & VBOXGLOBAL_DBG_CFG_VAR_CMD_LINE))5421 *piDbgCfgVar |= VBOXGLOBAL_DBG_CFG_VAR_DONE;5422 else if ( str.startsWith("y") // yes5423 || str.startsWith("e") // enabled5424 || str.startsWith("t") // true5425 || str.startsWith("on")5426 || str.toLongLong() != 0)5427 *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_DONE | VBOXGLOBAL_DBG_CFG_VAR_TRUE;5428 else if ( str.startsWith("n") // no5429 || str.startsWith("d") // disable5430 || str.startsWith("f") // false5431 || str.toLongLong() == 0)5432 *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_DONE | VBOXGLOBAL_DBG_CFG_VAR_FALSE;5433 else5434 *piDbgCfgVar |= VBOXGLOBAL_DBG_CFG_VAR_DONE;5435 }5436 5437 return (*piDbgCfgVar & VBOXGLOBAL_DBG_CFG_VAR_MASK) == VBOXGLOBAL_DBG_CFG_VAR_TRUE;5438 }5439 5440 #endif /* VBOX_WITH_DEBUGGER_GUI */5441 5442 /** @fn vboxGlobal5443 *5444 * Shortcut to the static VBoxGlobal::instance() method, for convenience.5445 */5446 5447 /**5448 * USB Popup Menu class methods5449 * This class provides the list of USB devices attached to the host.5450 */5451 VBoxUSBMenu::VBoxUSBMenu (QWidget *aParent) : QMenu (aParent)5452 {5453 connect (this, SIGNAL (aboutToShow()),5454 this, SLOT (processAboutToShow()));5455 // connect (this, SIGNAL (hovered (QAction *)),5456 // this, SLOT (processHighlighted (QAction *)));5457 }5458 5459 const CUSBDevice& VBoxUSBMenu::getUSB (QAction *aAction)5460 {5461 return mUSBDevicesMap [aAction];5462 }5463 5464 void VBoxUSBMenu::setConsole (const CConsole &aConsole)5465 {5466 mConsole = aConsole;5467 }5468 5469 void VBoxUSBMenu::processAboutToShow()5470 {5471 clear();5472 mUSBDevicesMap.clear();5473 5474 CHost host = vboxGlobal().virtualBox().GetHost();5475 5476 bool isUSBEmpty = host.GetUSBDevices().size() == 0;5477 if (isUSBEmpty)5478 {5479 QAction *action = addAction (tr ("<no devices available>", "USB devices"));5480 action->setEnabled (false);5481 action->setToolTip (tr ("No supported devices connected to the host PC",5482 "USB device tooltip"));5483 }5484 else5485 {5486 CHostUSBDeviceVector devvec = host.GetUSBDevices();5487 for (int i = 0; i < devvec.size(); ++i)5488 {5489 CHostUSBDevice dev = devvec[i];5490 CUSBDevice usb (dev);5491 QAction *action = addAction (vboxGlobal().details (usb));5492 action->setCheckable (true);5493 mUSBDevicesMap [action] = usb;5494 /* check if created item was already attached to this session */5495 if (!mConsole.isNull())5496 {5497 CUSBDevice attachedUSB =5498 mConsole.FindUSBDeviceById (usb.GetId());5499 action->setChecked (!attachedUSB.isNull());5500 action->setEnabled (dev.GetState() !=5501 KUSBDeviceState_Unavailable);5502 }5503 }5504 }5505 }5506 5507 bool VBoxUSBMenu::event(QEvent *aEvent)5508 {5509 /* We provide dynamic tooltips for the usb devices */5510 if (aEvent->type() == QEvent::ToolTip)5511 {5512 QHelpEvent *helpEvent = static_cast<QHelpEvent *> (aEvent);5513 QAction *action = actionAt (helpEvent->pos());5514 if (action)5515 {5516 CUSBDevice usb = mUSBDevicesMap [action];5517 if (!usb.isNull())5518 {5519 QToolTip::showText (helpEvent->globalPos(), vboxGlobal().toolTip (usb));5520 return true;5521 }5522 }5523 }5524 return QMenu::event (aEvent);5525 }5526 5527 /**5528 * Enable/Disable Menu class.5529 * This class provides enable/disable menu items.5530 */5531 VBoxSwitchMenu::VBoxSwitchMenu (QWidget *aParent, QAction *aAction,5532 bool aInverted)5533 : QMenu (aParent), mAction (aAction), mInverted (aInverted)5534 {5535 /* this menu works only with toggle action */5536 Assert (aAction->isCheckable());5537 addAction(aAction);5538 connect (this, SIGNAL (aboutToShow()),5539 this, SLOT (processAboutToShow()));5540 }5541 5542 void VBoxSwitchMenu::setToolTip (const QString &aTip)5543 {5544 mAction->setToolTip (aTip);5545 }5546 5547 void VBoxSwitchMenu::processAboutToShow()5548 {5549 QString text = mAction->isChecked() ^ mInverted ? tr ("Disable") : tr ("Enable");5550 mAction->setText (text);5551 }5552 5553 bool VBoxGlobal::switchToMachine(CMachine &machine)5554 {5555 #ifdef Q_WS_MAC5556 ULONG64 id = machine.ShowConsoleWindow();5557 #else5558 WId id = (WId) machine.ShowConsoleWindow();5559 #endif5560 AssertWrapperOk(machine);5561 if (!machine.isOk())5562 return false;5563 5564 /* winId = 0 it means the console window has already done everything5565 * necessary to implement the "show window" semantics. */5566 if (id == 0)5567 return true;5568 5569 #if defined (Q_WS_WIN32) || defined (Q_WS_X11)5570 5571 return vboxGlobal().activateWindow(id, true);5572 5573 #elif defined (Q_WS_MAC)5574 /*5575 * This is just for the case were the other process cannot steal5576 * the focus from us. It will send us a PSN so we can try.5577 */5578 ProcessSerialNumber psn;5579 psn.highLongOfPSN = id >> 32;5580 psn.lowLongOfPSN = (UInt32)id;5581 OSErr rc = ::SetFrontProcess(&psn);5582 if (!rc)5583 Log(("GUI: %#RX64 couldn't do SetFrontProcess on itself, the selector (we) had to do it...\n", id));5584 else5585 Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc));5586 return !rc;5587 5588 #endif5589 5590 return false;5591 5592 /// @todo Below is the old method of switching to the console window5593 // based on the process ID of the console process. It should go away5594 // after the new (callback-based) method is fully tested.5595 #if 05596 5597 if (!canSwitchTo())5598 return false;5599 5600 #if defined (Q_WS_WIN32)5601 5602 HWND hwnd = mWinId;5603 5604 /* if there are blockers (modal and modeless dialogs, etc), find the5605 * topmost one */5606 HWND hwndAbove = NULL;5607 do5608 {5609 hwndAbove = GetNextWindow(hwnd, GW_HWNDPREV);5610 HWND hwndOwner;5611 if (hwndAbove != NULL &&5612 ((hwndOwner = GetWindow(hwndAbove, GW_OWNER)) == hwnd ||5613 hwndOwner == hwndAbove))5614 hwnd = hwndAbove;5615 else5616 break;5617 }5618 while (1);5619 5620 /* first, check that the primary window is visible */5621 if (IsIconic(mWinId))5622 ShowWindow(mWinId, SW_RESTORE);5623 else if (!IsWindowVisible(mWinId))5624 ShowWindow(mWinId, SW_SHOW);5625 5626 #if 05627 LogFlowFunc(("mWinId=%08X hwnd=%08X\n", mWinId, hwnd));5628 #endif5629 5630 /* then, activate the topmost in the group */5631 AllowSetForegroundWindow(m_pid);5632 SetForegroundWindow(hwnd);5633 5634 return true;5635 5636 #elif defined (Q_WS_X11)5637 5638 return false;5639 5640 #elif defined (Q_WS_MAC)5641 5642 ProcessSerialNumber psn;5643 OSStatus rc = ::GetProcessForPID(m_pid, &psn);5644 if (!rc)5645 {5646 rc = ::SetFrontProcess(&psn);5647 5648 if (!rc)5649 {5650 ShowHideProcess(&psn, true);5651 return true;5652 }5653 }5654 return false;5655 5656 #else5657 5658 return false;5659 5660 #endif5661 5662 #endif5663 }5664 5665 bool VBoxGlobal::launchMachine(CMachine &machine)5666 {5667 if (machine.CanShowConsoleWindow())5668 return VBoxGlobal::switchToMachine(machine);5669 5670 KMachineState state = machine.GetState(); NOREF(state);5671 AssertMsg( state == KMachineState_PoweredOff5672 || state == KMachineState_Saved5673 || state == KMachineState_Teleported5674 || state == KMachineState_Aborted5675 , ("Machine must be PoweredOff/Saved/Aborted (%d)", state));5676 5677 CVirtualBox vbox = vboxGlobal().virtualBox();5678 CSession session;5679 session.createInstance(CLSID_Session);5680 if (session.isNull())5681 {5682 vboxProblem().cannotOpenSession(session);5683 return false;5684 }5685 5686 #if defined(Q_OS_WIN32)5687 /* allow the started VM process to make itself the foreground window */5688 AllowSetForegroundWindow(ASFW_ANY);5689 #endif5690 5691 QString env;5692 #if defined(Q_WS_X11)5693 /* make sure the VM process will start on the same display as the Selector */5694 const char *display = RTEnvGet("DISPLAY");5695 if (display)5696 env.append(QString("DISPLAY=%1\n").arg(display));5697 const char *xauth = RTEnvGet("XAUTHORITY");5698 if (xauth)5699 env.append(QString("XAUTHORITY=%1\n").arg(xauth));5700 #endif5701 5702 CProgress progress = machine.LaunchVMProcess(session, "GUI/Qt", env);5703 if ( !vbox.isOk()5704 || progress.isNull())5705 {5706 vboxProblem().cannotOpenSession(vbox, machine);5707 return false;5708 }5709 5710 /* Hide the "VM spawning" progress dialog */5711 /* I hope 1 minute will be enough to spawn any running VM silently, isn't it? */5712 int iSpawningDuration = 60000;5713 vboxProblem().showModalProgressDialog(progress, machine.GetName(), "", 0, false, iSpawningDuration);5714 if (progress.GetResultCode() != 0)5715 vboxProblem().cannotOpenSession(vbox, machine, progress);5716 5717 session.UnlockMachine();5718 5719 return true;5720 } -
trunk/src/VBox/Frontends/VirtualBox/src/platform/win/VBoxUtils-win.h
r35939 r35940 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VBoxGlobal class declaration4 * Declarations of utility classes and functions for handling Win specific tasks 5 5 */ 6 6 7 7 /* 8 * Copyright (C) 20 06-2010Oracle Corporation8 * Copyright (C) 2011 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 17 */ 18 18 19 #ifndef __VBox Global_h__20 #define __VBox Global_h__19 #ifndef __VBoxUtils_WIN_h__ 20 #define __VBoxUtils_WIN_h__ 21 21 22 #include "COMDefs.h" 23 #include "VBox/com/Guid.h"22 /* Qt includes: */ 23 #include <QRegion> 24 24 25 #include "VBoxGlobalSettings.h" 26 #include " VBoxMedium.h"25 /* Platform includes: */ 26 #include "Windows.h" 27 27 28 /* Qt includes */ 29 #include <QApplication> 30 #include <QLayout> 31 #include <QMenu> 32 #include <QStyle> 33 #include <QProcess> 34 #include <QHash> 35 #include <QFileIconProvider> 28 /* Namespace for native window sub-system functions: */ 29 namespace NativeWindowSubsystem 30 { 31 /* Returns area covered by visible always-on-top (top-most) windows: */ 32 const QRegion areaCoveredByTopMostWindows(); 33 } 36 34 37 #ifdef Q_WS_X11 38 # include <sys/wait.h> 39 #endif 35 #endif /* __VBoxUtils_WIN_h__ */ 40 36 41 class QAction;42 class QLabel;43 class QToolButton;44 class UIMachine;45 46 class Process : public QProcess47 {48 Q_OBJECT;49 50 public:51 52 static QByteArray singleShot (const QString &aProcessName,53 int aTimeout = 500054 /* wait for data maximum 5 seconds */)55 {56 /* Why is it really needed is because of Qt4.3 bug with QProcess.57 * This bug is about QProcess sometimes (~70%) do not receive58 * notification about process was finished, so this makes59 * 'bool QProcess::waitForFinished (int)' block the GUI thread and60 * never dismissed with 'true' result even if process was really61 * started&finished. So we just waiting for some information62 * on process output and destroy the process with force. Due to63 * QProcess::~QProcess() has the same 'waitForFinished (int)' blocker64 * we have to change process state to QProcess::NotRunning. */65 66 QByteArray result;67 Process process;68 process.start (aProcessName);69 bool firstShotReady = process.waitForReadyRead (aTimeout);70 if (firstShotReady)71 result = process.readAllStandardOutput();72 process.setProcessState (QProcess::NotRunning);73 #ifdef Q_WS_X1174 int status;75 if (process.pid() > 0)76 waitpid(process.pid(), &status, 0);77 #endif78 return result;79 }80 81 protected:82 83 Process (QWidget *aParent = 0) : QProcess (aParent) {}84 };85 86 struct StorageSlot87 {88 StorageSlot() : bus (KStorageBus_Null), port (0), device (0) {}89 StorageSlot (const StorageSlot &aOther) : bus (aOther.bus), port (aOther.port), device (aOther.device) {}90 StorageSlot (KStorageBus aBus, LONG aPort, LONG aDevice) : bus (aBus), port (aPort), device (aDevice) {}91 StorageSlot& operator= (const StorageSlot &aOther) { bus = aOther.bus; port = aOther.port; device = aOther.device; return *this; }92 bool operator== (const StorageSlot &aOther) const { return bus == aOther.bus && port == aOther.port && device == aOther.device; }93 bool operator!= (const StorageSlot &aOther) const { return bus != aOther.bus || port != aOther.port || device != aOther.device; }94 bool operator< (const StorageSlot &aOther) const { return (bus < aOther.bus) ||95 (bus == aOther.bus && port < aOther.port) ||96 (bus == aOther.bus && port == aOther.port && device < aOther.device); }97 bool operator> (const StorageSlot &aOther) const { return (bus > aOther.bus) ||98 (bus == aOther.bus && port > aOther.port) ||99 (bus == aOther.bus && port == aOther.port && device > aOther.device); }100 bool isNull() { return bus == KStorageBus_Null; }101 KStorageBus bus; LONG port; LONG device;102 };103 Q_DECLARE_METATYPE (StorageSlot);104 105 // VBoxGlobal class106 ////////////////////////////////////////////////////////////////////////////////107 108 class VBoxSelectorWnd;109 class UIRegistrationWzd;110 class VBoxUpdateDlg;111 112 class VBoxGlobal : public QObject113 {114 Q_OBJECT115 116 public:117 118 typedef QHash <ulong, QString> QULongStringHash;119 typedef QHash <long, QString> QLongStringHash;120 121 static VBoxGlobal &instance();122 123 bool isValid() { return mValid; }124 125 static QString qtRTVersionString();126 static uint qtRTVersion();127 static QString qtCTVersionString();128 static uint qtCTVersion();129 130 QString versionString() const { return mVerString; }131 bool isBeta() const;132 133 CVirtualBox virtualBox() const { return mVBox; }134 135 VBoxGlobalSettings &settings() { return gset; }136 bool setSettings (VBoxGlobalSettings &gs);137 138 VBoxSelectorWnd &selectorWnd();139 140 QWidget *vmWindow();141 142 bool createVirtualMachine(const CSession &session);143 UIMachine* virtualMachine();144 145 /* main window handle storage */146 void setMainWindow (QWidget *aMainWindow) { mMainWindow = aMainWindow; }147 QWidget *mainWindow() const { return mMainWindow; }148 149 #ifdef VBOX_GUI_WITH_PIDFILE150 void createPidfile();151 void deletePidfile();152 #endif153 154 /* branding */155 bool brandingIsActive (bool aForce = false);156 QString brandingGetKey (QString aKey);157 158 bool processArgs();159 160 bool switchToMachine(CMachine &machine);161 bool launchMachine(CMachine &machine);162 163 bool isVMConsoleProcess() const { return !vmUuid.isNull(); }164 bool showStartVMErrors() const { return mShowStartVMErrors; }165 #ifdef VBOX_GUI_WITH_SYSTRAY166 bool isTrayMenu() const;167 void setTrayMenu(bool aIsTrayMenu);168 void trayIconShowSelector();169 bool trayIconInstall();170 #endif171 QString managedVMUuid() const { return vmUuid; }172 QList<QUrl> &argUrlList() { return m_ArgUrlList; }173 174 VBoxDefs::RenderMode vmRenderMode() const { return vm_render_mode; }175 const char *vmRenderModeStr() const { return vm_render_mode_str; }176 bool isKWinManaged() const { return mIsKWinManaged; }177 178 const QRect availableGeometry(int iScreen = 0) const;179 180 #ifdef Q_WS_WIN181 static QList<QRect> m_sTopMostRects;182 static const QRegion areaCoveredByTopMostWindows();183 #endif /* Q_WS_WIN */184 185 #ifdef VBOX_WITH_DEBUGGER_GUI186 bool isDebuggerEnabled(CMachine &aMachine);187 bool isDebuggerAutoShowEnabled(CMachine &aMachine);188 bool isDebuggerAutoShowCommandLineEnabled(CMachine &aMachine);189 bool isDebuggerAutoShowStatisticsEnabled(CMachine &aMachine);190 RTLDRMOD getDebuggerModule() const { return mhVBoxDbg; }191 192 bool isStartPausedEnabled() const { return mStartPaused; }193 #else194 bool isDebuggerAutoShowEnabled(CMachine & /*aMachine*/) const { return false; }195 bool isDebuggerAutoShowCommandLineEnabled(CMachine & /*aMachine*/) const { return false; }196 bool isDebuggerAutoShowStatisticsEnabled(CMachine & /*aMachine*/) const { return false; }197 198 bool isStartPausedEnabled() const { return false; }199 #endif200 201 /* VBox enum to/from string/icon/color convertors */202 203 QList <CGuestOSType> vmGuestOSFamilyList() const;204 QList <CGuestOSType> vmGuestOSTypeList (const QString &aFamilyId) const;205 QPixmap vmGuestOSTypeIcon (const QString &aTypeId) const;206 CGuestOSType vmGuestOSType (const QString &aTypeId,207 const QString &aFamilyId = QString::null) const;208 QString vmGuestOSTypeDescription (const QString &aTypeId) const;209 210 QPixmap toIcon (KMachineState s) const211 {212 QPixmap *pm = mVMStateIcons.value (s);213 AssertMsg (pm, ("Icon for VM state %d must be defined", s));214 return pm ? *pm : QPixmap();215 }216 217 static inline QString yearsToString (uint32_t cVal)218 {219 return tr("%n year(s)", "", cVal);220 }221 222 static inline QString monthsToString (uint32_t cVal)223 {224 return tr("%n month(s)", "", cVal);225 }226 227 static inline QString daysToString (uint32_t cVal)228 {229 return tr("%n day(s)", "", cVal);230 }231 232 static inline QString hoursToString (uint32_t cVal)233 {234 return tr("%n hour(s)", "", cVal);235 }236 237 static inline QString minutesToString (uint32_t cVal)238 {239 return tr("%n minute(s)", "", cVal);240 }241 242 static inline QString secondsToString (uint32_t cVal)243 {244 return tr("%n second(s)", "", cVal);245 }246 247 const QColor &toColor (KMachineState s) const248 {249 static const QColor none;250 AssertMsg (mVMStateColors.value (s), ("No color for %d", s));251 return mVMStateColors.value (s) ? *mVMStateColors.value (s) : none;252 }253 254 QString toString (KMachineState s) const255 {256 AssertMsg (!mMachineStates.value (s).isNull(), ("No text for %d", s));257 return mMachineStates.value (s);258 }259 260 QString toString (KSessionState s) const261 {262 AssertMsg (!mSessionStates.value (s).isNull(), ("No text for %d", s));263 return mSessionStates.value (s);264 }265 266 /**267 * Returns a string representation of the given KStorageBus enum value.268 * Complementary to #toStorageBusType (const QString &) const.269 */270 QString toString (KStorageBus aBus) const271 {272 AssertMsg (!mStorageBuses.value (aBus).isNull(), ("No text for %d", aBus));273 return mStorageBuses [aBus];274 }275 276 /**277 * Returns a KStorageBus enum value corresponding to the given string278 * representation. Complementary to #toString (KStorageBus) const.279 */280 KStorageBus toStorageBusType (const QString &aBus) const281 {282 QULongStringHash::const_iterator it =283 qFind (mStorageBuses.begin(), mStorageBuses.end(), aBus);284 AssertMsg (it != mStorageBuses.end(), ("No value for {%s}",285 aBus.toLatin1().constData()));286 return KStorageBus (it.key());287 }288 289 KStorageBus toStorageBusType (KStorageControllerType aControllerType) const290 {291 KStorageBus sb = KStorageBus_Null;292 switch (aControllerType)293 {294 case KStorageControllerType_Null: sb = KStorageBus_Null; break;295 case KStorageControllerType_PIIX3:296 case KStorageControllerType_PIIX4:297 case KStorageControllerType_ICH6: sb = KStorageBus_IDE; break;298 case KStorageControllerType_IntelAhci: sb = KStorageBus_SATA; break;299 case KStorageControllerType_LsiLogic:300 case KStorageControllerType_BusLogic: sb = KStorageBus_SCSI; break;301 case KStorageControllerType_I82078: sb = KStorageBus_Floppy; break;302 default:303 AssertMsgFailed (("toStorageBusType: %d not handled\n", aControllerType)); break;304 }305 return sb;306 }307 308 QString toString (KStorageBus aBus, LONG aChannel) const;309 LONG toStorageChannel (KStorageBus aBus, const QString &aChannel) const;310 311 QString toString (KStorageBus aBus, LONG aChannel, LONG aDevice) const;312 LONG toStorageDevice (KStorageBus aBus, LONG aChannel, const QString &aDevice) const;313 314 QString toString (StorageSlot aSlot) const;315 StorageSlot toStorageSlot (const QString &aSlot) const;316 317 QString toString (KMediumType t) const318 {319 AssertMsg (!mDiskTypes.value (t).isNull(), ("No text for %d", t));320 return mDiskTypes.value (t);321 }322 323 /**324 * Similar to toString (KMediumType), but returns 'Differencing' for325 * normal hard disks that have a parent.326 */327 QString mediumTypeString (const CMedium &aHD) const328 {329 if (!aHD.GetParent().isNull())330 {331 Assert (aHD.GetType() == KMediumType_Normal);332 return mDiskTypes_Differencing;333 }334 return toString (aHD.GetType());335 }336 337 QString toString (KAuthType t) const338 {339 AssertMsg (!mAuthTypes.value (t).isNull(), ("No text for %d", t));340 return mAuthTypes.value (t);341 }342 343 QString toString (KPortMode t) const344 {345 AssertMsg (!mPortModeTypes.value (t).isNull(), ("No text for %d", t));346 return mPortModeTypes.value (t);347 }348 349 QString toString (KUSBDeviceFilterAction t) const350 {351 AssertMsg (!mUSBFilterActionTypes.value (t).isNull(), ("No text for %d", t));352 return mUSBFilterActionTypes.value (t);353 }354 355 QString toString (KClipboardMode t) const356 {357 AssertMsg (!mClipboardTypes.value (t).isNull(), ("No text for %d", t));358 return mClipboardTypes.value (t);359 }360 361 KClipboardMode toClipboardModeType (const QString &s) const362 {363 QULongStringHash::const_iterator it =364 qFind (mClipboardTypes.begin(), mClipboardTypes.end(), s);365 AssertMsg (it != mClipboardTypes.end(), ("No value for {%s}",366 s.toLatin1().constData()));367 return KClipboardMode (it.key());368 }369 370 QString toString (KStorageControllerType t) const371 {372 AssertMsg (!mStorageControllerTypes.value (t).isNull(), ("No text for %d", t));373 return mStorageControllerTypes.value (t);374 }375 376 KStorageControllerType toControllerType (const QString &s) const377 {378 QULongStringHash::const_iterator it =379 qFind (mStorageControllerTypes.begin(), mStorageControllerTypes.end(), s);380 AssertMsg (it != mStorageControllerTypes.end(), ("No value for {%s}",381 s.toLatin1().constData()));382 return KStorageControllerType (it.key());383 }384 385 KAuthType toAuthType (const QString &s) const386 {387 QULongStringHash::const_iterator it =388 qFind (mAuthTypes.begin(), mAuthTypes.end(), s);389 AssertMsg (it != mAuthTypes.end(), ("No value for {%s}",390 s.toLatin1().constData()));391 return KAuthType (it.key());392 }393 394 KPortMode toPortMode (const QString &s) const395 {396 QULongStringHash::const_iterator it =397 qFind (mPortModeTypes.begin(), mPortModeTypes.end(), s);398 AssertMsg (it != mPortModeTypes.end(), ("No value for {%s}",399 s.toLatin1().constData()));400 return KPortMode (it.key());401 }402 403 KUSBDeviceFilterAction toUSBDevFilterAction (const QString &s) const404 {405 QULongStringHash::const_iterator it =406 qFind (mUSBFilterActionTypes.begin(), mUSBFilterActionTypes.end(), s);407 AssertMsg (it != mUSBFilterActionTypes.end(), ("No value for {%s}",408 s.toLatin1().constData()));409 return KUSBDeviceFilterAction (it.key());410 }411 412 QString toString (KDeviceType t) const413 {414 AssertMsg (!mDeviceTypes.value (t).isNull(), ("No text for %d", t));415 return mDeviceTypes.value (t);416 }417 418 KDeviceType toDeviceType (const QString &s) const419 {420 QULongStringHash::const_iterator it =421 qFind (mDeviceTypes.begin(), mDeviceTypes.end(), s);422 AssertMsg (it != mDeviceTypes.end(), ("No value for {%s}",423 s.toLatin1().constData()));424 return KDeviceType (it.key());425 }426 427 QStringList deviceTypeStrings() const;428 429 QString toString (KAudioDriverType t) const430 {431 AssertMsg (!mAudioDriverTypes.value (t).isNull(), ("No text for %d", t));432 return mAudioDriverTypes.value (t);433 }434 435 KAudioDriverType toAudioDriverType (const QString &s) const436 {437 QULongStringHash::const_iterator it =438 qFind (mAudioDriverTypes.begin(), mAudioDriverTypes.end(), s);439 AssertMsg (it != mAudioDriverTypes.end(), ("No value for {%s}",440 s.toLatin1().constData()));441 return KAudioDriverType (it.key());442 }443 444 QString toString (KAudioControllerType t) const445 {446 AssertMsg (!mAudioControllerTypes.value (t).isNull(), ("No text for %d", t));447 return mAudioControllerTypes.value (t);448 }449 450 KAudioControllerType toAudioControllerType (const QString &s) const451 {452 QULongStringHash::const_iterator it =453 qFind (mAudioControllerTypes.begin(), mAudioControllerTypes.end(), s);454 AssertMsg (it != mAudioControllerTypes.end(), ("No value for {%s}",455 s.toLatin1().constData()));456 return KAudioControllerType (it.key());457 }458 459 QString toString (KNetworkAdapterType t) const460 {461 AssertMsg (!mNetworkAdapterTypes.value (t).isNull(), ("No text for %d", t));462 return mNetworkAdapterTypes.value (t);463 }464 465 KNetworkAdapterType toNetworkAdapterType (const QString &s) const466 {467 QULongStringHash::const_iterator it =468 qFind (mNetworkAdapterTypes.begin(), mNetworkAdapterTypes.end(), s);469 AssertMsg (it != mNetworkAdapterTypes.end(), ("No value for {%s}",470 s.toLatin1().constData()));471 return KNetworkAdapterType (it.key());472 }473 474 QString toString (KNetworkAttachmentType t) const475 {476 AssertMsg (!mNetworkAttachmentTypes.value (t).isNull(), ("No text for %d", t));477 return mNetworkAttachmentTypes.value (t);478 }479 480 KNetworkAttachmentType toNetworkAttachmentType (const QString &s) const481 {482 QULongStringHash::const_iterator it =483 qFind (mNetworkAttachmentTypes.begin(), mNetworkAttachmentTypes.end(), s);484 AssertMsg (it != mNetworkAttachmentTypes.end(), ("No value for {%s}",485 s.toLatin1().constData()));486 return KNetworkAttachmentType (it.key());487 }488 489 QString toString (KNATProtocol t) const490 {491 AssertMsg (!mNATProtocolTypes.value (t).isNull(), ("No text for %d", t));492 return mNATProtocolTypes.value (t);493 }494 495 KNATProtocol toNATProtocolType (const QString &s) const496 {497 QULongStringHash::const_iterator it =498 qFind (mNATProtocolTypes.begin(), mNATProtocolTypes.end(), s);499 AssertMsg (it != mNATProtocolTypes.end(), ("No value for {%s}",500 s.toLatin1().constData()));501 return KNATProtocol (it.key());502 }503 504 QString toString (KUSBDeviceState aState) const505 {506 AssertMsg (!mUSBDeviceStates.value (aState).isNull(), ("No text for %d", aState));507 return mUSBDeviceStates.value (aState);508 }509 510 QString toString (KChipsetType t) const511 {512 AssertMsg (!mChipsetTypes.value (t).isNull(), ("No text for %d", t));513 return mChipsetTypes.value (t);514 }515 516 KChipsetType toChipsetType (const QString &s) const517 {518 QULongStringHash::const_iterator it =519 qFind (mChipsetTypes.begin(), mChipsetTypes.end(), s);520 AssertMsg (it != mChipsetTypes.end(), ("No value for {%s}",521 s.toLatin1().constData()));522 return KChipsetType (it.key());523 }524 525 QStringList COMPortNames() const;526 QString toCOMPortName (ulong aIRQ, ulong aIOBase) const;527 bool toCOMPortNumbers (const QString &aName, ulong &aIRQ, ulong &aIOBase) const;528 529 QStringList LPTPortNames() const;530 QString toLPTPortName (ulong aIRQ, ulong aIOBase) const;531 bool toLPTPortNumbers (const QString &aName, ulong &aIRQ, ulong &aIOBase) const;532 533 QPixmap snapshotIcon (bool online) const534 {535 return online ? mOnlineSnapshotIcon : mOfflineSnapshotIcon;536 }537 538 static bool hasAllowedExtension(const QString &strExt, const QStringList &extList) { for(int i = 0; i < extList.size(); ++i) if (strExt.endsWith(extList.at(i), Qt::CaseInsensitive)) return true; return false;}539 QIcon icon(QFileIconProvider::IconType type) { return m_globalIconProvider.icon(type); }540 QIcon icon(const QFileInfo &info) { return m_globalIconProvider.icon(info); }541 542 QPixmap warningIcon() const { return mWarningIcon; }543 QPixmap errorIcon() const { return mErrorIcon; }544 545 /* details generators */546 547 QString details (const CMedium &aHD, bool aPredictDiff);548 549 QString details (const CUSBDevice &aDevice) const;550 QString toolTip (const CUSBDevice &aDevice) const;551 QString toolTip (const CUSBDeviceFilter &aFilter) const;552 553 QString detailsReport (const CMachine &aMachine, bool aWithLinks);554 555 QString platformInfo();556 557 /* VirtualBox helpers */558 559 #if defined(Q_WS_X11) && !defined(VBOX_OSE)560 double findLicenseFile (const QStringList &aFilesList, QRegExp aPattern, QString &aLicenseFile) const;561 bool showVirtualBoxLicense();562 #endif563 564 CSession openSession(const QString &aId, bool aExisting = false);565 566 /** Shortcut to openSession (aId, true). */567 CSession openExistingSession(const QString &aId) { return openSession (aId, true); }568 569 bool startMachine(const QString &strId);570 571 void startEnumeratingMedia();572 573 /**574 * Returns a list of all currently registered media. This list is used to575 * globally track the accessibility state of all media on a dedicated thread.576 *577 * Note that the media list is initially empty (i.e. before the enumeration578 * process is started for the first time using #startEnumeratingMedia()).579 * See #startEnumeratingMedia() for more information about how meida are580 * sorted in the returned list.581 */582 const VBoxMediaList ¤tMediaList() const { return mMediaList; }583 584 /** Returns true if the media enumeration is in progress. */585 bool isMediaEnumerationStarted() const { return mMediaEnumThread != NULL; }586 587 VBoxDefs::MediumType mediumTypeToLocal(KDeviceType globalType);588 KDeviceType mediumTypeToGlobal(VBoxDefs::MediumType localType);589 590 void addMedium (const VBoxMedium &);591 void updateMedium (const VBoxMedium &);592 void removeMedium (VBoxDefs::MediumType, const QString &);593 594 bool findMedium (const CMedium &, VBoxMedium &) const;595 VBoxMedium findMedium (const QString &aMediumId) const;596 597 /** Compact version of #findMediumTo(). Asserts if not found. */598 VBoxMedium getMedium (const CMedium &aObj) const599 {600 VBoxMedium medium;601 if (!findMedium (aObj, medium))602 AssertFailed();603 return medium;604 }605 606 QString openMediumWithFileOpenDialog(VBoxDefs::MediumType mediumType, QWidget *pParent = 0,607 const QString &strDefaultFolder = QString(), bool fUseLastFolder = true);608 QString openMedium(VBoxDefs::MediumType mediumType, QString strMediumLocation, QWidget *pParent = 0);609 610 /* Returns the number of current running Fe/Qt4 main windows. */611 int mainWindowCount();612 613 /* various helpers */614 615 QString languageName() const;616 QString languageCountry() const;617 QString languageNameEnglish() const;618 QString languageCountryEnglish() const;619 QString languageTranslators() const;620 621 void retranslateUi();622 623 /** @internal made public for internal purposes */624 void cleanup();625 626 /* public static stuff */627 628 static bool shouldWarnAboutToLowVRAM(const CMachine *pMachine = 0);629 static bool isDOSType (const QString &aOSTypeId);630 631 static QString languageId();632 static void loadLanguage (const QString &aLangId = QString::null);633 QString helpFile() const;634 635 static void setTextLabel (QToolButton *aToolButton, const QString &aTextLabel);636 637 static QRect normalizeGeometry (const QRect &aRectangle, const QRegion &aBoundRegion,638 bool aCanResize = true);639 static QRect getNormalized (const QRect &aRectangle, const QRegion &aBoundRegion,640 bool aCanResize = true);641 static QRegion flip (const QRegion &aRegion);642 643 static void centerWidget (QWidget *aWidget, QWidget *aRelative,644 bool aCanResize = true);645 646 static QChar decimalSep();647 static QString sizeRegexp();648 649 static QString toHumanReadableList(const QStringList &list);650 651 static quint64 parseSize (const QString &);652 static QString formatSize (quint64 aSize, uint aDecimal = 2,653 VBoxDefs::FormatSize aMode = VBoxDefs::FormatSize_Round);654 655 static quint64 requiredVideoMemory (CMachine *aMachine = 0, int cMonitors = 1);656 657 static QString locationForHTML (const QString &aFileName);658 659 static QString highlight (const QString &aStr, bool aToolTip = false);660 661 static QString replaceHtmlEntities(QString strText);662 static QString emphasize (const QString &aStr);663 664 static QString systemLanguageId();665 666 static bool activateWindow (WId aWId, bool aSwitchDesktop = true);667 668 static QString removeAccelMark (const QString &aText);669 670 static QString insertKeyToActionText (const QString &aText, const QString &aKey);671 static QString extractKeyFromActionText (const QString &aText);672 673 static QPixmap joinPixmaps (const QPixmap &aPM1, const QPixmap &aPM2);674 675 static QWidget *findWidget (QWidget *aParent, const char *aName,676 const char *aClassName = NULL,677 bool aRecursive = false);678 679 static QList <QPair <QString, QString> > MediumBackends(KDeviceType enmDeviceType);680 static QList <QPair <QString, QString> > HDDBackends();681 static QList <QPair <QString, QString> > DVDBackends();682 static QList <QPair <QString, QString> > FloppyBackends();683 684 /* Qt 4.2.0 support function */685 static inline void setLayoutMargin (QLayout *aLayout, int aMargin)686 {687 #if QT_VERSION < 0x040300688 /* Deprecated since > 4.2 */689 aLayout->setMargin (aMargin);690 #else691 /* New since > 4.2 */692 aLayout->setContentsMargins (aMargin, aMargin, aMargin, aMargin);693 #endif694 }695 696 static QString documentsPath();697 698 #ifdef VBOX_WITH_VIDEOHWACCEL699 static bool isAcceleration2DVideoAvailable();700 701 /** additional video memory required for the best 2D support performance702 * total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory */703 static quint64 required2DOffscreenVideoMemory();704 #endif705 706 #ifdef VBOX_WITH_CRHGSMI707 static quint64 required3DWddmOffscreenVideoMemory(CMachine *aMachine = 0, int cMonitors = 1);708 #endif709 710 #ifdef Q_WS_MAC711 bool isSheetWindowsAllowed(QWidget *pParent) const;712 #endif /* Q_WS_MAC */713 714 signals:715 716 /**717 * Emitted at the beginning of the enumeration process started by718 * #startEnumeratingMedia().719 */720 void mediumEnumStarted();721 722 /**723 * Emitted when a new medium item from the list has updated its724 * accessibility state.725 */726 void mediumEnumerated (const VBoxMedium &aMedum);727 728 /**729 * Emitted at the end of the enumeration process started by730 * #startEnumeratingMedia(). The @a aList argument is passed for731 * convenience, it is exactly the same as returned by #currentMediaList().732 */733 void mediumEnumFinished (const VBoxMediaList &aList);734 735 /** Emitted when a new media is added using #addMedia(). */736 void mediumAdded (const VBoxMedium &);737 738 /** Emitted when the media is updated using #updateMedia(). */739 void mediumUpdated (const VBoxMedium &);740 741 /** Emitted when the media is removed using #removeMedia(). */742 void mediumRemoved (VBoxDefs::MediumType, const QString &);743 744 #ifdef VBOX_GUI_WITH_SYSTRAY745 void sigTrayIconShow(bool fEnabled);746 #endif747 748 public slots:749 750 bool openURL (const QString &aURL);751 752 void showRegistrationDialog (bool aForce = true);753 void showUpdateDialog (bool aForce = true);754 void perDayNewVersionNotifier();755 void sltGUILanguageChange(QString strLang);756 757 protected:758 759 bool event (QEvent *e);760 bool eventFilter (QObject *, QEvent *);761 762 private:763 764 VBoxGlobal();765 ~VBoxGlobal();766 767 void init();768 #ifdef VBOX_WITH_DEBUGGER_GUI769 void initDebuggerVar(int *piDbgCfgVar, const char *pszEnvVar, const char *pszExtraDataName, bool fDefault = false);770 void setDebuggerVar(int *piDbgCfgVar, bool fState);771 bool isDebuggerWorker(int *piDbgCfgVar, CMachine &rMachine, const char *pszExtraDataName);772 #endif773 774 bool mValid;775 776 CVirtualBox mVBox;777 778 VBoxGlobalSettings gset;779 780 VBoxSelectorWnd *mSelectorWnd;781 UIMachine *m_pVirtualMachine;782 QWidget* mMainWindow;783 784 #ifdef VBOX_WITH_REGISTRATION785 UIRegistrationWzd *mRegDlg;786 #endif787 VBoxUpdateDlg *mUpdDlg;788 789 QString vmUuid;790 QList<QUrl> m_ArgUrlList;791 792 #ifdef VBOX_GUI_WITH_SYSTRAY793 bool mIsTrayMenu : 1; /*< Tray icon active/desired? */794 bool mIncreasedWindowCounter : 1;795 #endif796 797 /** Whether to show error message boxes for VM start errors. */798 bool mShowStartVMErrors;799 800 QThread *mMediaEnumThread;801 VBoxMediaList mMediaList;802 803 VBoxDefs::RenderMode vm_render_mode;804 const char * vm_render_mode_str;805 bool mIsKWinManaged;806 807 #ifdef VBOX_WITH_DEBUGGER_GUI808 /** Whether the debugger should be accessible or not.809 * Use --dbg, the env.var. VBOX_GUI_DBG_ENABLED, --debug or the env.var.810 * VBOX_GUI_DBG_AUTO_SHOW to enable. */811 int mDbgEnabled;812 /** Whether to show the debugger automatically with the console.813 * Use --debug or the env.var. VBOX_GUI_DBG_AUTO_SHOW to enable. */814 int mDbgAutoShow;815 /** Whether to show the command line window when mDbgAutoShow is set. */816 int mDbgAutoShowCommandLine;817 /** Whether to show the statistics window when mDbgAutoShow is set. */818 int mDbgAutoShowStatistics;819 /** VBoxDbg module handle. */820 RTLDRMOD mhVBoxDbg;821 822 /** Whether to start the VM in paused state or not. */823 bool mStartPaused;824 #endif825 826 #if defined (Q_WS_WIN32)827 DWORD dwHTMLHelpCookie;828 #endif829 830 QString mVerString;831 QString mBrandingConfig;832 833 QList <QString> mFamilyIDs;834 QList <QList <CGuestOSType> > mTypes;835 QHash <QString, QPixmap *> mOsTypeIcons;836 837 QHash <ulong, QPixmap *> mVMStateIcons;838 QHash <ulong, QColor *> mVMStateColors;839 840 QPixmap mOfflineSnapshotIcon, mOnlineSnapshotIcon;841 842 QULongStringHash mMachineStates;843 QULongStringHash mSessionStates;844 QULongStringHash mDeviceTypes;845 846 QULongStringHash mStorageBuses;847 QLongStringHash mStorageBusChannels;848 QLongStringHash mStorageBusDevices;849 QULongStringHash mSlotTemplates;850 851 QULongStringHash mDiskTypes;852 QString mDiskTypes_Differencing;853 854 QULongStringHash mAuthTypes;855 QULongStringHash mPortModeTypes;856 QULongStringHash mUSBFilterActionTypes;857 QULongStringHash mAudioDriverTypes;858 QULongStringHash mAudioControllerTypes;859 QULongStringHash mNetworkAdapterTypes;860 QULongStringHash mNetworkAttachmentTypes;861 QULongStringHash mNATProtocolTypes;862 QULongStringHash mClipboardTypes;863 QULongStringHash mStorageControllerTypes;864 QULongStringHash mUSBDeviceStates;865 QULongStringHash mChipsetTypes;866 867 QString mUserDefinedPortName;868 869 QPixmap mWarningIcon, mErrorIcon;870 871 QFileIconProvider m_globalIconProvider;872 873 #ifdef VBOX_GUI_WITH_PIDFILE874 QString m_strPidfile;875 #endif876 877 friend VBoxGlobal &vboxGlobal();878 };879 880 inline VBoxGlobal &vboxGlobal() { return VBoxGlobal::instance(); }881 882 // Helper classes883 ////////////////////////////////////////////////////////////////////////////////884 885 /**886 * USB Popup Menu class.887 * This class provides the list of USB devices attached to the host.888 */889 class VBoxUSBMenu : public QMenu890 {891 Q_OBJECT892 893 public:894 895 VBoxUSBMenu (QWidget *);896 897 const CUSBDevice& getUSB (QAction *aAction);898 899 void setConsole (const CConsole &);900 901 private slots:902 903 void processAboutToShow();904 905 private:906 bool event(QEvent *aEvent);907 908 QMap <QAction *, CUSBDevice> mUSBDevicesMap;909 CConsole mConsole;910 };911 912 /**913 * Enable/Disable Menu class.914 * This class provides enable/disable menu items.915 */916 class VBoxSwitchMenu : public QMenu917 {918 Q_OBJECT919 920 public:921 922 VBoxSwitchMenu (QWidget *, QAction *, bool aInverted = false);923 924 void setToolTip (const QString &);925 926 private slots:927 928 void processAboutToShow();929 930 private:931 932 QAction *mAction;933 bool mInverted;934 };935 936 #endif /* __VBoxGlobal_h__ */937 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
r35906 r35940 32 32 #include "UIMachineView.h" 33 33 #include "UIFrameBuffer.h" 34 35 #ifdef Q_WS_WIN 36 # include "VBoxUtils-win.h" 37 #endif /* Q_WS_WIN */ 34 38 35 39 #ifdef Q_WS_X11 … … 880 884 /* Trim partial-viewport-rectangle by top-most windows: */ 881 885 QRegion viewportRegion(viewportRectangle); 882 QRegion topMostRegion( VBoxGlobal::areaCoveredByTopMostWindows());886 QRegion topMostRegion(NativeWindowSubsystem::areaCoveredByTopMostWindows()); 883 887 viewportRegion -= topMostRegion; 884 888 /* Check if partial-viewport-region consists of 1 rectangle: */
Note:
See TracChangeset
for help on using the changeset viewer.