VirtualBox

Ignore:
Timestamp:
Feb 11, 2011 11:58:32 AM (14 years ago)
Author:
vboxsync
Message:

FE/Qt: Move some platform-related stuff from VBoxGlobal to VBoxUtils-win.

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

Legend:

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

    r35808 r35940  
    574574VirtualBox_SOURCES.win += \
    575575        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
    577578
    578579VirtualBox_DEFS.darwin += VBOX_DARWIN_USE_NATIVE_CONTROLS
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp

    r35906 r35940  
    843843    return result;
    844844}
    845 
    846 #ifdef Q_WS_WIN
    847 /* 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 */
    898845
    899846/**
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.h

    r35906 r35940  
    178178    const QRect availableGeometry(int iScreen = 0) const;
    179179
    180 #ifdef Q_WS_WIN
    181     static QList<QRect> m_sTopMostRects;
    182     static const QRegion areaCoveredByTopMostWindows();
    183 #endif /* Q_WS_WIN */
    184 
    185180#ifdef VBOX_WITH_DEBUGGER_GUI
    186181    bool isDebuggerEnabled(CMachine &aMachine);
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/win/VBoxUtils-win.cpp

    r35939 r35940  
    33 *
    44 * VBox frontends: Qt GUI ("VirtualBox"):
    5  * VBoxGlobal class implementation
     5 * Utility classes and functions for handling Win specific tasks
    66 */
    77
    88/*
    9  * Copyright (C) 2006-2010 Oracle Corporation
     9 * Copyright (C) 2010-2011 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1818 */
    1919
    20 #include "VBoxGlobal.h"
    21 #include <VBox/vd.h>
    22 #include <VBox/version.h>
     20/* Includes: */
     21#include "VBoxUtils-win.h"
    2322
    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: */
     24namespace NativeWindowSubsystem
    14825{
    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;
    19030}
    19131
    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: */
     33BOOL CALLBACK NativeWindowSubsystem::EnumWindowsProc(HWND hWnd, LPARAM /* lParam */)
    84934{
    85035    /* Ignore NULL HWNDs: */
     
    87156    RECT rect;
    87257    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));
    87459
    87560    /* Proceed to the next window: */
     
    87762}
    87863
    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: */
     65const QRegion NativeWindowSubsystem::areaCoveredByTopMostWindows()
    88466{
    88567    /* Prepare the top-most region: */
    88668    QRegion topMostRegion;
    88769    /* Initialize the list of the top-most rectangles: */
    888     m_sTopMostRects.clear();
     70    topMostRects.clear();
    88971    /* Populate the list of top-most rectangles: */
    89072    EnumWindows((WNDENUMPROC)EnumWindowsProc, 0);
    89173    /* 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];
    89476    /* Return top-most region: */
    89577    return topMostRegion;
    89678}
    897 #endif /* Q_WS_WIN */
    89879
    899 /**
    900  *  Returns the list of few guest OS types, queried from
    901  *  IVirtualBox corresponding to every family id.
    902  */
    903 QList <CGuestOSType> VBoxGlobal::vmGuestOSFamilyList() const
    904 {
    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 from
    913  *  IVirtualBox corresponding to passed family id.
    914  */
    915 QList <CGuestOSType> VBoxGlobal::vmGuestOSTypeList (const QString &aFamilyId) const
    916 {
    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) const
    926 {
    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 list
    935  *  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 */) const
    940 {
    941     QList <CGuestOSType> list;
    942     if (mFamilyIDs.contains (aFamilyId))
    943     {
    944         list = mTypes [mFamilyIDs.indexOf (aFamilyId)];
    945     }
    946     else
    947     {
    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) const
    962 {
    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) const
    978 {
    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) const
    1020 {
    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) const
    1064 {
    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) const
    1109 {
    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 own
    1154  * separately translated string tags allowing to translate a full slot name into human readable format
    1155  * to be consistent with i18n.
    1156  * Complementary to #toStorageSlot (const QString &) const.
    1157  */
    1158 QString VBoxGlobal::toString (StorageSlot aSlot) const
    1159 {
    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) const
    1225 {
    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() const
    1298 {
    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 PortConfig
    1308 {
    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 cause
    1321      * 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 cause
    1330      * 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() const
    1337 {
    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() const
    1349 {
    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 given
    1359  *  parameters, or "User-defined" (which is also returned when both
    1360  *  @a aIRQ and @a aIOBase are 0).
    1361  */
    1362 QString VBoxGlobal::toCOMPortName (ulong aIRQ, ulong aIOBase) const
    1363 {
    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 given
    1374  *  parameters, or "User-defined" (which is also returned when both
    1375  *  @a aIRQ and @a aIOBase are 0).
    1376  */
    1377 QString VBoxGlobal::toLPTPortName (ulong aIRQ, ulong aIOBase) const
    1378 {
    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 one
    1390  *  of the standard names (i.e. "COMx").
    1391  */
    1392 bool VBoxGlobal::toCOMPortNumbers (const QString &aName, ulong &aIRQ,
    1393                                    ulong &aIOBase) const
    1394 {
    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 one
    1409  *  of the standard names (i.e. "LPTx").
    1410  */
    1411 bool VBoxGlobal::toLPTPortNumbers (const QString &aName, ulong &aIRQ,
    1412                                    ulong &aIOBase) const
    1413 {
    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 and
    1427  * calls VBoxMedium::details() on the found descriptor.
    1428  *
    1429  * If the requested hard disk is not found (for example, it's a new hard disk
    1430  * for a new VM created outside our UI), then media enumeration is requested and
    1431  * the search is repeated. We assume that the second attempt always succeeds and
    1432  * assert otherwise.
    1433  *
    1434  * @note Technically, the second attempt may fail if, for example, the new hard
    1435  *       passed to this method disk gets removed before #startEnumeratingMedia()
    1436  *       succeeds. This (unexpected object uninitialization) is a generic
    1437  *       problem though and needs to be addressed using exceptions (see also the
    1438  *       @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) const
    1461 {
    1462     QString sDetails;
    1463     if (aDevice.isNull())
    1464         sDetails = tr("Unknown device", "USB device details");
    1465     else
    1466     {
    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         else
    1478         {
    1479             if (p.toUpper().startsWith (m.toUpper()))
    1480                 sDetails = p;
    1481             else
    1482                 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) const
    1496 {
    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 filter
    1523  */
    1524 QString VBoxGlobal::toolTip (const CUSBDeviceFilter &aFilter) const
    1525 {
    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>&nbsp;</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>&nbsp;</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 &sectionTpl = 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 += sectionTpl
    1615                   .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_REPORT
    1647         /* 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_REPORT
    1689                      + 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 += sectionTpl
    1700                   .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_VIDEOHWACCEL
    1737         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 #endif
    1745 
    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             else
    1755                 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 += sectionTpl
    1762             .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("&nbsp;&nbsp;") +
    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 += sectionTpl
    1833             .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         else
    1854             item = QString (sSectionItemTpl1)
    1855                    .arg (tr ("Disabled", "details report (audio)"));
    1856 
    1857         report += sectionTpl
    1858             .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 have
    1880                  * an additional symbolic network/interface name field, use
    1881                  * 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_VDE
    1892                 else if (type == KNetworkAttachmentType_VDE)
    1893                     attType = attType.arg (tr ("VDE network, '%1'",
    1894                         "details report (network)").arg (adapter.GetVDENetwork()));
    1895 #endif
    1896                 else
    1897                     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 += sectionTpl
    1914             .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                 else
    1942                     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 += sectionTpl
    1959             .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             else
    2029                 item = QString (sSectionItemTpl1)
    2030                        .arg (tr ("Disabled", "details report (USB)"));
    2031 
    2032             report += sectionTpl
    2033                 .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         else
    2053             item = QString (sSectionItemTpl1)
    2054                    .arg (tr ("None", "details report (shared folders)"));
    2055 
    2056         report += sectionTpl
    2057             .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 #else
    2084     platform = "unknown";
    2085 #endif
    2086 
    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         else
    2113             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         else
    2124             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 #else
    2144     /* 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 #endif
    2162 
    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) const
    2168 {
    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() will
    2198      * 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 when
    2239  *  it is no more necessary.
    2240  *
    2241  *  @param aId          Machine ID.
    2242  *  @param aExisting    @c true to open an existing session with the machine
    2243  *                      which is already running, @c false to open a new direct
    2244  *                      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() will
    2266              * 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 registered
    2379  * media.
    2380  *
    2381  * Before the enumeration is started, the current media list (a list returned by
    2382  * #currentMediaList()) is populated with all registered media and the
    2383  * #mediumEnumStarted() signal is emitted. The enumeration thread then walks this
    2384  * list, checks for media accessibility and emits #mediumEnumerated() signals of
    2385  * each checked medium. When all media are checked, the enumeration thread is
    2386  * 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 sorted
    2391  * 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 children
    2394  *      (alphabetically sorted) immediately follow their parent and therefore
    2395  *      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 as
    2401  * 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 QThread
    2429     {
    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 != NULL
    2477      * 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             else
    2545             {
    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     else
    2561     {
    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 DEBUG
    2625     /* sanity: must be no children */
    2626     {
    2627         VBoxMediaList::Iterator jt = it;
    2628         ++ jt;
    2629         AssertReturnVoid (jt == mMediaList.end() || (*jt).parent() != &*it);
    2630     }
    2631 #endif
    2632 
    2633     VBoxMedium *pParent = (*it).parent();
    2634 
    2635     /* remove the medium from the list to keep it in sync with the server "for
    2636      * 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 like
    2642      * 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) const
    2656 {
    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) const
    2675 {
    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 dialog
    2683  * 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     else
    2812         vboxProblem().cannotOpenMedium(pParent, vbox, mediumType, strMediumLocation);
    2813 
    2814     return QString();
    2815 }
    2816 
    2817 #ifdef VBOX_GUI_WITH_SYSTRAY
    2818 /**
    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 #endif
    2828 
    2829 /**
    2830  *  Native language name of the currently installed translation.
    2831  *  Returns "English" if no translation is installed
    2832  *  or if the translation file is invalid.
    2833  */
    2834 QString VBoxGlobal::languageName() const
    2835 {
    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 is
    2844  *  invalid, or if the language is independent on the country.
    2845  */
    2846 QString VBoxGlobal::languageCountry() const
    2847 {
    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 installed
    2856  *  or if the translation file is invalid.
    2857  */
    2858 QString VBoxGlobal::languageNameEnglish() const
    2859 {
    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 is
    2868  *  invalid, or if the language is independent on the country.
    2869  */
    2870 QString VBoxGlobal::languageCountryEnglish() const
    2871 {
    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 the
    2880  *  translation file is invalid, or if the translation is supplied by Oracle
    2881  *  Corporation
    2882  */
    2883 QString VBoxGlobal::languageTranslators() const
    2884 {
    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 the
    2891  *  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_VIRTIO
    3010     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_VDE
    3025     mNetworkAttachmentTypes [KNetworkAttachmentType_VDE] =
    3026         tr ("VDE Adapter", "NetworkAttachmentType");
    3027 #endif
    3028 
    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_X11
    3092     /* 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 stuff
    3099 ////////////////////////////////////////////////////////////////////////////////
    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 QTranslator
    3119 {
    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 the
    3145  *  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 C
    3149  *  locale is used in unix environments as a fallback when the requested
    3150  *  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 the
    3164  *                 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 extra
    3175      * "en" translation file will be loaded. This is necessary for loading the
    3176      * 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         else
    3216         {
    3217             /* Never complain when the default language is requested.  In any
    3218              * case, if no explicit language file exists, we will simply
    3219              * 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() for
    3231          * us. It will also delete all its child translations we attach to it
    3232          * 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 will
    3248          * activate an empty translator that will give us English
    3249          * (built-in) */
    3250         qApp->installTranslator (sTranslator);
    3251     }
    3252     else
    3253         loadOk = false;
    3254 
    3255     if (loadOk)
    3256         sLoadedLangId = selectedLangId;
    3257     else
    3258     {
    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_UNIX
    3267         /* We use system installations of Qt on Linux systems, so first, try
    3268          * 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 loaded
    3276          * afterwards to make sure it will take precedence over the system
    3277          * translation (it may contain more decent variants of translation
    3278          * that better correspond to VirtualBox UI). We need to load both
    3279          * because a newer version of Qt may be installed on the user computer
    3280          * and the Oracle version may not fully support it. We don't do it on
    3281          * Win32 because we supply a Qt library there and therefore the
    3282          * Oracle translation is always the best one. */
    3283 #endif
    3284         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 additional
    3292          * 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 separate
    3294          * 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_MAC
    3301     /* 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() const
    3308 {
    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_OSE
    3317     const QString name = "UserManual";
    3318     const QString suffix = "pdf";
    3319 # else
    3320     const QString name = "VirtualBox";
    3321     const QString suffix = "chm";
    3322 # endif
    3323 #endif
    3324     /* 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() will
    3330      * 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 shortcut
    3352  *  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. Only
    3357  *  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 sure
    3381  *  it is fully contained inside \a aBoundRegion region by moving & resizing
    3382  *  \a aRectangle if necessary. Selects the minimum shifted result between direct
    3383  *  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 the
    3408  *  region \a aBoundRegion by moving \a aRectangle if necessary. If \a aRectangle is
    3409  *  larger than \a aBoundRegion, top left corner of \a aRectangle is aligned with the
    3410  *  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 size
    3488          * 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 visible
    3530  *  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 an
    3532  *  inappropriate minimum size limit (in which case the top left corner will be
    3533  *  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, but
    3536  *  if it's not top-level itself, its top-level widget will be used for
    3537  *  calculations. \a aRelative can also be NULL, in which case \a aWidget will
    3538  *  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 level
    3555          * 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     else
    3562     {
    3563         deskGeo = QApplication::desktop()->availableGeometry();
    3564         parentGeo = deskGeo;
    3565     }
    3566 
    3567     /* On X11, there is no way to determine frame geometry (including WM
    3568      * decorations) before the widget is shown for the first time. Stupidly
    3569      * enumerate other top level widgets to find the thickest frame. The code
    3570      * 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 this
    3591 #if 0
    3592     /* sanity check for decoration frames. With embedding, we
    3593      * might get extraordinary values */
    3594     if (extraw == 0 || extrah == 0 || extraw > 20 || extrah > 50)
    3595     {
    3596         extrah = 50;
    3597         extraw = 20;
    3598     }
    3599 #endif
    3600 
    3601     /* On non-X11 platforms, the following would be enough instead of the
    3602      * 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_MAC
    3613     /* No idea why, but Qt doesn't respect if there is a unified toolbar on the
    3614      * ::move call. So manually add the height of the toolbar before setting
    3615      * 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-readable
    3638  *  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 present
    3642  *            (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 present
    3646  *  - cap(5): size suffix in case when decimal point is present (note that
    3647  *            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 of
    3685  *  <tt>####[.##] B|KB|MB|GB|TB|PB</tt> and returns
    3686  *  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     else
    3729         return 0;
    3730 }
    3731 
    3732 /**
    3733  * Formats the given @a aSize value in bytes to a human readable string
    3734  * 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 resulting
    3737  * 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 the
    3740  *     closest number containing \a aDecimal decimal digits.
    3741  * </li>
    3742  * <li>When \a aMode is FormatSize_RoundDown, the result is rounded to the
    3743  *     largest number with \a aDecimal decimal digits that is not greater than
    3744  *     the result. This guarantees that converting the resulting string back to
    3745  *     the integer value in bytes will not produce a value greater that the
    3746  *     initial size parameter.
    3747  * </li>
    3748  * <li>When \a aMode is FormatSize_RoundUp, the result is rounded to the
    3749  *     smallest number with \a aDecimal decimal digits that is not less than the
    3750  *     result. This guarantees that converting the resulting string back to the
    3751  *     integer value in bytes will not produce a value less that the initial
    3752  *     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     else
    3804     {
    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     else
    3846     {
    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 (   pMachine
    3861         && !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 desktop
    3870  *  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 list
    3878      * is sorted by value and by starting with the biggest one, we calculate
    3879      * the memory requirements for every guest screen. This is of course not
    3880      * correct, but as we can't predict on which host screens the user will
    3881      * open the guest windows, this is the best assumption we can do, cause it
    3882      * 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 host
    3892      * screens available, replace all zeros with the greatest value in the
    3893      * 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_CRHGSMI
    3918            if (typeId == "WindowsVista" || typeId == "Windows7")
    3919            {
    3920                /* wddm mode, there are two surfaces for each screen: shadow & primary */
    3921                needMBytes *= 3;
    3922            }
    3923            else
    3924 #endif
    3925            {
    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_LINUX
    3945 //    result.replace ('/', "/<font color=red>&shy;</font>");
    3946 //#else
    3947 //    result.replace ('\\', "\\<font color=red>&shy;</font>");
    3948 //#endif
    3949 //    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 marked
    3957  *    with blue color;
    3958  *  - UUIDs be put inside <nobr> and marked
    3959  *    with green color;
    3960  *  - replaces new line chars with </p><p> constructs to form paragraphs
    3961  *    (note that <p> and </p> are not appended to the beginning and to the
    3962  *     end of the string respectively, to allow the result be appended
    3963  *     or prepended to the existing paragraph).
    3964  *
    3965  *  If @a aToolTip is true, colouring is not applied, only the <nobr> tag
    3966  *  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 ('&', "&amp;");
    3985     text.replace ('<', "&lt;");
    3986     text.replace ('>', "&gt;");
    3987     text.replace ('\"', "&quot;");
    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     else
    4006         text.replace ('\n', "<br>");
    4007 
    4008     return text;
    4009 }
    4010 
    4011 /* static */
    4012 QString VBoxGlobal::replaceHtmlEntities(QString strText)
    4013 {
    4014     return strText
    4015         .replace('&', "&amp;")
    4016         .replace('<', "&lt;")
    4017         .replace('>', "&gt;")
    4018         .replace('\"', "&quot;");
    4019 }
    4020 
    4021 /**
    4022  *  Reformats the input string @a aStr so that:
    4023  *  - strings in single quotes will be put inside <nobr> and marked
    4024  *    with bold style;
    4025  *  - UUIDs be put inside <nobr> and marked
    4026  *    with italic style;
    4027  *  - replaces new line chars with </p><p> constructs to form paragraphs
    4028  *    (note that <p> and </p> are not appended to the beginning and to the
    4029  *     end of the string respectively, to allow the result be appended
    4030  *     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 ('&', "&amp;");
    4044     text.replace ('<', "&lt;");
    4045     text.replace ('>', "&gt;");
    4046     text.replace ('\"', "&quot;");
    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 its
    4069  *  wrong behavior on Linux systems (LC_NUMERIC for some strange reason takes
    4070  *  precedence over any other locale setting in the QLocale::system()
    4071  *  implementation). This implementation first looks at LC_ALL (as defined by
    4072  *  SUS), then looks at LC_MESSAGES which is designed to define a language for
    4073  *  program messages in case if it differs from the language for other locale
    4074  *  categories. Then it looks for LANG and finally falls back to
    4075  *  QLocale::system().name().
    4076  *
    4077  *  The order of precedence is well defined here:
    4078  *  http://opengroup.org/onlinepubs/007908799/xbd/envvar.html
    4079  *
    4080  *  @note This method will return "C" when the requested locale is invalid or
    4081  *  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 the
    4088      * 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 #endif
    4099     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 #endif
    4158 
    4159 /**
    4160  * Activates the specified window. If necessary, the window will be
    4161  * de-iconified activation.
    4162  *
    4163  * @note On X11, it is implied that @a aWid represents a window of the same
    4164  * 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 before
    4168  *                          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 desktop
    4197              * 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         else
    4215         {
    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 #else
    4228 
    4229     NOREF (aWId);
    4230     NOREF (aSwitchDesktop);
    4231     AssertFailed();
    4232     result = false;
    4233 
    4234 #endif
    4235 
    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 string
    4244  *  and returns the result. The string is supposed to be a menu item's text
    4245  *  that may (or may not) contain the accelerator mark.
    4246  *
    4247  *  In order to support accelerators used in non-alphabet languages
    4248  *  (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 a
    4250  *  whole. If such a pattern is not found, then the '&' character is simply
    4251  *  removed from the string.
    4252  *
    4253  *  @note This function removes only the first occurrence of the accelerator
    4254  *  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     else
    4270     {
    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_MAC
    4283     QString pattern("%1 (Host+%2)");
    4284 #else
    4285     QString pattern("%1 \tHost+%2");
    4286 #endif
    4287     if (   strKey.isEmpty()
    4288         || strKey.compare("None", Qt::CaseInsensitive) == 0)
    4289         return strText;
    4290     else
    4291         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_MAC
    4299     QRegExp re (".* \\(Host\\+(.+)\\)");
    4300 #else
    4301     QRegExp re (".* \\t\\Host\\+(.+)");
    4302 #endif
    4303     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 the
    4310  * 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 inherits
    4337  *  @a aClassName (if it is not NULL) and among children of @a aParent. If @a
    4338  *  aParent is NULL, all top-level widgets are searched. If @a aRecursive is
    4339  *  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 for
    4377  * the given device type.
    4378  * Returned is a list of pairs with the form
    4379  *   <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 form
    4409  *   <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 form
    4420  *   <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 form
    4431  *   <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 < 0x040400
    4444     path = QDir::homePath();
    4445 #else
    4446     path = QDesktopServices::storageLocation (QDesktopServices::DocumentsLocation);
    4447 #endif
    4448 
    4449     /* Make sure the path exists */
    4450     QDir dir (path);
    4451     if (dir.exists())
    4452         return QDir::cleanPath (dir.canonicalPath());
    4453     else
    4454     {
    4455         dir.setPath (QDir::homePath() + "/Documents");
    4456         if (dir.exists())
    4457             return QDir::cleanPath (dir.canonicalPath());
    4458         else
    4459             return QDir::homePath();
    4460     }
    4461 }
    4462 
    4463 #ifdef VBOX_WITH_VIDEOHWACCEL
    4464 /* static */
    4465 bool VBoxGlobal::isAcceleration2DVideoAvailable()
    4466 {
    4467     return VBoxQGLOverlay::isAcceleration2DVideoAvailable();
    4468 }
    4469 
    4470 /** additional video memory required for the best 2D support performance
    4471  *  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 #endif
    4479 
    4480 #ifdef VBOX_WITH_CRHGSMI
    4481 /* 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 #endif
    4490 
    4491 #ifdef Q_WS_MAC
    4492 bool VBoxGlobal::isSheetWindowsAllowed(QWidget *pParent) const
    4493 {
    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 slots
    4502 ////////////////////////////////////////////////////////////////////////////////
    4503 
    4504 /**
    4505  * Opens the specified URL using OS/Desktop capabilities.
    4506  *
    4507  * @param aURL URL to open
    4508  *
    4509  * @return true on success and false otherwise
    4510  */
    4511 bool VBoxGlobal::openURL (const QString &aURL)
    4512 {
    4513     /* Service event */
    4514     class ServiceEvent : public QEvent
    4515     {
    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 QEventLoop
    4529     {
    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 QThread
    4556     {
    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 to
    4592  *       VBoxCallback::OnExtraDataChange() handling performed by VBoxGlobal.
    4593  *
    4594  * @param aForce
    4595  */
    4596 void VBoxGlobal::showRegistrationDialog (bool aForce)
    4597 {
    4598     NOREF(aForce);
    4599 #ifdef VBOX_WITH_REGISTRATION
    4600     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     else
    4611     {
    4612         /* Store the ID of the main window to ensure that only one
    4613          * registration dialog is shown at a time. Due to manipulations with
    4614          * OnExtraDataCanChange() and OnExtraDataChange() signals, this extra
    4615          * data item acts like an inter-process mutex, so the first process
    4616          * that attempts to set it will win, the rest will get a failure from
    4617          * 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 #endif
    4631 }
    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 to
    4638  *       VBoxCallback::OnExtraDataChange() handling performed by VBoxGlobal.
    4639  *
    4640  * @param aForce
    4641  */
    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     else
    4664     {
    4665         /* Store the ID of the main window to ensure that only one
    4666          * update dialog is shown at a time. Due to manipulations with
    4667          * OnExtraDataCanChange() and OnExtraDataChange() signals, this extra
    4668          * data item acts like an inter-process mutex, so the first process
    4669          * that attempts to set it will win, the rest will get a failure from
    4670          * 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 members
    4700 ////////////////////////////////////////////////////////////////////////////////
    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             else
    4721             {
    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 in
    4746          * order to invalidate cached string resources (like the details view
    4747          * 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 (see
    4752              * QApplication::installTranslator() for details) */
    4753             retranslateUi();
    4754         }
    4755     }
    4756 
    4757     return QObject::eventFilter (aObject, aEvent);
    4758 }
    4759 
    4760 #ifdef VBOX_WITH_DEBUGGER_GUI
    4761 
    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 members
    4785 ////////////////////////////////////////////////////////////////////////////////
    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 be
    4795            parameters with arguments (e.g. --comment comment). */
    4796         if (args.at(i).startsWith("-"))
    4797             break;
    4798 #ifdef Q_WS_MAC
    4799         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 DEBUG
    4837     mVerString += " [DEBUG]";
    4838 #endif
    4839 
    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 error
    4866      * 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_SYSTRAY
    4877     {
    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 #endif
    4887 
    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 we
    4895          * 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 except
    4900          * 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 struct
    5002     {
    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_X11
    5074     mIsKWinManaged = X11IsWindowManagerKWin();
    5075 #endif
    5076 
    5077 #ifdef VBOX_WITH_DEBUGGER_GUI
    5078 # ifdef VBOX_WITH_DEBUGGER_GUI_MENU
    5079     initDebuggerVar(&mDbgEnabled, "VBOX_GUI_DBG_ENABLED", VBoxDefs::GUI_DbgEnabled, true);
    5080 # else
    5081     initDebuggerVar(&mDbgEnabled, "VBOX_GUI_DBG_ENABLED", VBoxDefs::GUI_DbgEnabled, false);
    5082 # endif
    5083     initDebuggerVar(&mDbgAutoShow, "VBOX_GUI_DBG_AUTO_SHOW", VBoxDefs::GUI_DbgAutoShow, false);
    5084     mDbgAutoShowCommandLine = mDbgAutoShowStatistics = mDbgAutoShow;
    5085     mStartPaused = false;
    5086 #endif
    5087 
    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 the
    5098          * 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_PIDFILE
    5110         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_SYSTRAY
    5125         else if (!::strcmp (arg, "-systray") || !::strcmp (arg, "--systray"))
    5126         {
    5127             mIsTrayMenu = true;
    5128         }
    5129 #endif
    5130         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_GUI
    5144         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 #endif
    5187         /** @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         else
    5199         {
    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_GUI
    5223     /* 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 #endif
    5239 
    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 /** @internal
    5251  *
    5252  *  This method should be never called directly. It is called automatically
    5253  *  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_SYSTRAY
    5265     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 #endif
    5283 
    5284 #ifdef VBOX_GUI_WITH_PIDFILE
    5285     deletePidfile();
    5286 #endif
    5287 
    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_REGISTRATION
    5300     if (mRegDlg)
    5301         mRegDlg->close();
    5302 #endif
    5303 
    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 message
    5319      * queue which reference COM objects. Remove them to release those objects
    5320      * before uninitializing the COM subsystem. */
    5321     QApplication::removePostedEvents (this);
    5322 
    5323     COMBase::CleanupCOM();
    5324 
    5325     mValid = false;
    5326 }
    5327 
    5328 #ifdef VBOX_WITH_DEBUGGER_GUI
    5329 
    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 this
    5341  *                              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     else
    5368     {
    5369         QString *pStr = !strEnvValue.isEmpty() ? &strEnvValue : &strExtraValue;
    5370         if (   pStr->startsWith("y")  // yes
    5371             || pStr->startsWith("e")  // enabled
    5372             || pStr->startsWith("t")  // true
    5373             || pStr->startsWith("on")
    5374             || pStr->toLongLong() != 0)
    5375             *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_TRUE;
    5376         else if (   pStr->startsWith("n")  // o
    5377                  || pStr->startsWith("d")  // disable
    5378                  || pStr->startsWith("f")  // false
    5379                  || pStr->startsWith("off")
    5380                  || pStr->contains("veto")
    5381                  || pStr->toLongLong() == 0)
    5382             *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_FALSE;
    5383         else
    5384         {
    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 machine
    5406  * 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")  // yes
    5423                  || str.startsWith("e")  // enabled
    5424                  || str.startsWith("t")  // true
    5425                  || 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")  // no
    5429                  || str.startsWith("d")  // disable
    5430                  || str.startsWith("f")  // false
    5431                  || str.toLongLong() == 0)
    5432             *piDbgCfgVar = VBOXGLOBAL_DBG_CFG_VAR_DONE | VBOXGLOBAL_DBG_CFG_VAR_FALSE;
    5433         else
    5434             *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 vboxGlobal
    5443  *
    5444  *  Shortcut to the static VBoxGlobal::instance() method, for convenience.
    5445  */
    5446 
    5447 /**
    5448  *  USB Popup Menu class methods
    5449  *  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     else
    5485     {
    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_MAC
    5556     ULONG64 id = machine.ShowConsoleWindow();
    5557 #else
    5558     WId id = (WId) machine.ShowConsoleWindow();
    5559 #endif
    5560     AssertWrapperOk(machine);
    5561     if (!machine.isOk())
    5562         return false;
    5563 
    5564     /* winId = 0 it means the console window has already done everything
    5565      * 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 steal
    5576      * 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     else
    5585         Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc));
    5586     return !rc;
    5587 
    5588 #endif
    5589 
    5590     return false;
    5591 
    5592     /// @todo Below is the old method of switching to the console window
    5593     //  based on the process ID of the console process. It should go away
    5594     //  after the new (callback-based) method is fully tested.
    5595 #if 0
    5596 
    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 the
    5605      * topmost one */
    5606     HWND hwndAbove = NULL;
    5607     do
    5608     {
    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         else
    5616             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 0
    5627     LogFlowFunc(("mWinId=%08X hwnd=%08X\n", mWinId, hwnd));
    5628 #endif
    5629 
    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 #else
    5657 
    5658     return false;
    5659 
    5660 #endif
    5661 
    5662 #endif
    5663 }
    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_PoweredOff
    5672               || state == KMachineState_Saved
    5673               || state == KMachineState_Teleported
    5674               || state == KMachineState_Aborted
    5675               , ("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 #endif
    5690 
    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 #endif
    5701 
    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  
    22 *
    33 * VBox frontends: Qt GUI ("VirtualBox"):
    4  * VBoxGlobal class declaration
     4 * Declarations of utility classes and functions for handling Win specific tasks
    55 */
    66
    77/*
    8  * Copyright (C) 2006-2010 Oracle Corporation
     8 * Copyright (C) 2011 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1717 */
    1818
    19 #ifndef __VBoxGlobal_h__
    20 #define __VBoxGlobal_h__
     19#ifndef __VBoxUtils_WIN_h__
     20#define __VBoxUtils_WIN_h__
    2121
    22 #include "COMDefs.h"
    23 #include "VBox/com/Guid.h"
     22/* Qt includes: */
     23#include <QRegion>
    2424
    25 #include "VBoxGlobalSettings.h"
    26 #include "VBoxMedium.h"
     25/* Platform includes: */
     26#include "Windows.h"
    2727
    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: */
     29namespace NativeWindowSubsystem
     30{
     31    /* Returns area covered by visible always-on-top (top-most) windows: */
     32    const QRegion areaCoveredByTopMostWindows();
     33}
    3634
    37 #ifdef Q_WS_X11
    38 # include <sys/wait.h>
    39 #endif
     35#endif /* __VBoxUtils_WIN_h__ */
    4036
    41 class QAction;
    42 class QLabel;
    43 class QToolButton;
    44 class UIMachine;
    45 
    46 class Process : public QProcess
    47 {
    48     Q_OBJECT;
    49 
    50 public:
    51 
    52     static QByteArray singleShot (const QString &aProcessName,
    53                                   int aTimeout = 5000
    54                                   /* 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 receive
    58          * notification about process was finished, so this makes
    59          * 'bool QProcess::waitForFinished (int)' block the GUI thread and
    60          * never dismissed with 'true' result even if process was really
    61          * started&finished. So we just waiting for some information
    62          * on process output and destroy the process with force. Due to
    63          * QProcess::~QProcess() has the same 'waitForFinished (int)' blocker
    64          * 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_X11
    74         int status;
    75         if (process.pid() > 0)
    76             waitpid(process.pid(), &status, 0);
    77 #endif
    78         return result;
    79     }
    80 
    81 protected:
    82 
    83     Process (QWidget *aParent = 0) : QProcess (aParent) {}
    84 };
    85 
    86 struct StorageSlot
    87 {
    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 class
    106 ////////////////////////////////////////////////////////////////////////////////
    107 
    108 class VBoxSelectorWnd;
    109 class UIRegistrationWzd;
    110 class VBoxUpdateDlg;
    111 
    112 class VBoxGlobal : public QObject
    113 {
    114     Q_OBJECT
    115 
    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_PIDFILE
    150     void createPidfile();
    151     void deletePidfile();
    152 #endif
    153 
    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_SYSTRAY
    166     bool isTrayMenu() const;
    167     void setTrayMenu(bool aIsTrayMenu);
    168     void trayIconShowSelector();
    169     bool trayIconInstall();
    170 #endif
    171     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_WIN
    181     static QList<QRect> m_sTopMostRects;
    182     static const QRegion areaCoveredByTopMostWindows();
    183 #endif /* Q_WS_WIN */
    184 
    185 #ifdef VBOX_WITH_DEBUGGER_GUI
    186     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 #else
    194     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 #endif
    200 
    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) const
    211     {
    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) const
    248     {
    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) const
    255     {
    256         AssertMsg (!mMachineStates.value (s).isNull(), ("No text for %d", s));
    257         return mMachineStates.value (s);
    258     }
    259 
    260     QString toString (KSessionState s) const
    261     {
    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) const
    271     {
    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 string
    278      * representation. Complementary to #toString (KStorageBus) const.
    279      */
    280     KStorageBus toStorageBusType (const QString &aBus) const
    281     {
    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) const
    290     {
    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) const
    318     {
    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' for
    325      * normal hard disks that have a parent.
    326      */
    327     QString mediumTypeString (const CMedium &aHD) const
    328     {
    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) const
    338     {
    339         AssertMsg (!mAuthTypes.value (t).isNull(), ("No text for %d", t));
    340         return mAuthTypes.value (t);
    341     }
    342 
    343     QString toString (KPortMode t) const
    344     {
    345         AssertMsg (!mPortModeTypes.value (t).isNull(), ("No text for %d", t));
    346         return mPortModeTypes.value (t);
    347     }
    348 
    349     QString toString (KUSBDeviceFilterAction t) const
    350     {
    351         AssertMsg (!mUSBFilterActionTypes.value (t).isNull(), ("No text for %d", t));
    352         return mUSBFilterActionTypes.value (t);
    353     }
    354 
    355     QString toString (KClipboardMode t) const
    356     {
    357         AssertMsg (!mClipboardTypes.value (t).isNull(), ("No text for %d", t));
    358         return mClipboardTypes.value (t);
    359     }
    360 
    361     KClipboardMode toClipboardModeType (const QString &s) const
    362     {
    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) const
    371     {
    372         AssertMsg (!mStorageControllerTypes.value (t).isNull(), ("No text for %d", t));
    373         return mStorageControllerTypes.value (t);
    374     }
    375 
    376     KStorageControllerType toControllerType (const QString &s) const
    377     {
    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) const
    386     {
    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) const
    395     {
    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) const
    404     {
    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) const
    413     {
    414         AssertMsg (!mDeviceTypes.value (t).isNull(), ("No text for %d", t));
    415         return mDeviceTypes.value (t);
    416     }
    417 
    418     KDeviceType toDeviceType (const QString &s) const
    419     {
    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) const
    430     {
    431         AssertMsg (!mAudioDriverTypes.value (t).isNull(), ("No text for %d", t));
    432         return mAudioDriverTypes.value (t);
    433     }
    434 
    435     KAudioDriverType toAudioDriverType (const QString &s) const
    436     {
    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) const
    445     {
    446         AssertMsg (!mAudioControllerTypes.value (t).isNull(), ("No text for %d", t));
    447         return mAudioControllerTypes.value (t);
    448     }
    449 
    450     KAudioControllerType toAudioControllerType (const QString &s) const
    451     {
    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) const
    460     {
    461         AssertMsg (!mNetworkAdapterTypes.value (t).isNull(), ("No text for %d", t));
    462         return mNetworkAdapterTypes.value (t);
    463     }
    464 
    465     KNetworkAdapterType toNetworkAdapterType (const QString &s) const
    466     {
    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) const
    475     {
    476         AssertMsg (!mNetworkAttachmentTypes.value (t).isNull(), ("No text for %d", t));
    477         return mNetworkAttachmentTypes.value (t);
    478     }
    479 
    480     KNetworkAttachmentType toNetworkAttachmentType (const QString &s) const
    481     {
    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) const
    490     {
    491         AssertMsg (!mNATProtocolTypes.value (t).isNull(), ("No text for %d", t));
    492         return mNATProtocolTypes.value (t);
    493     }
    494 
    495     KNATProtocol toNATProtocolType (const QString &s) const
    496     {
    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) const
    505     {
    506         AssertMsg (!mUSBDeviceStates.value (aState).isNull(), ("No text for %d", aState));
    507         return mUSBDeviceStates.value (aState);
    508     }
    509 
    510     QString toString (KChipsetType t) const
    511     {
    512         AssertMsg (!mChipsetTypes.value (t).isNull(), ("No text for %d", t));
    513         return mChipsetTypes.value (t);
    514     }
    515 
    516     KChipsetType toChipsetType (const QString &s) const
    517     {
    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) const
    534     {
    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 #endif
    563 
    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 to
    575      * 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 enumeration
    578      * process is started for the first time using #startEnumeratingMedia()).
    579      * See #startEnumeratingMedia() for more information about how meida are
    580      * sorted in the returned list.
    581      */
    582     const VBoxMediaList &currentMediaList() 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) const
    599     {
    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 < 0x040300
    688         /* Deprecated since > 4.2 */
    689         aLayout->setMargin (aMargin);
    690 #else
    691         /* New since > 4.2 */
    692         aLayout->setContentsMargins (aMargin, aMargin, aMargin, aMargin);
    693 #endif
    694     }
    695 
    696     static QString documentsPath();
    697 
    698 #ifdef VBOX_WITH_VIDEOHWACCEL
    699     static bool isAcceleration2DVideoAvailable();
    700 
    701     /** additional video memory required for the best 2D support performance
    702      *  total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory  */
    703     static quint64 required2DOffscreenVideoMemory();
    704 #endif
    705 
    706 #ifdef VBOX_WITH_CRHGSMI
    707     static quint64 required3DWddmOffscreenVideoMemory(CMachine *aMachine = 0, int cMonitors = 1);
    708 #endif
    709 
    710 #ifdef Q_WS_MAC
    711     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 by
    718      * #startEnumeratingMedia().
    719      */
    720     void mediumEnumStarted();
    721 
    722     /**
    723      * Emitted when a new medium item from the list has updated its
    724      * accessibility state.
    725      */
    726     void mediumEnumerated (const VBoxMedium &aMedum);
    727 
    728     /**
    729      * Emitted at the end of the enumeration process started by
    730      * #startEnumeratingMedia(). The @a aList argument is passed for
    731      * 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_SYSTRAY
    745     void sigTrayIconShow(bool fEnabled);
    746 #endif
    747 
    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_GUI
    769     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 #endif
    773 
    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_REGISTRATION
    785     UIRegistrationWzd *mRegDlg;
    786 #endif
    787     VBoxUpdateDlg *mUpdDlg;
    788 
    789     QString vmUuid;
    790     QList<QUrl> m_ArgUrlList;
    791 
    792 #ifdef VBOX_GUI_WITH_SYSTRAY
    793     bool mIsTrayMenu : 1; /*< Tray icon active/desired? */
    794     bool mIncreasedWindowCounter : 1;
    795 #endif
    796 
    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_GUI
    808     /** 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 #endif
    825 
    826 #if defined (Q_WS_WIN32)
    827     DWORD dwHTMLHelpCookie;
    828 #endif
    829 
    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_PIDFILE
    874     QString m_strPidfile;
    875 #endif
    876 
    877     friend VBoxGlobal &vboxGlobal();
    878 };
    879 
    880 inline VBoxGlobal &vboxGlobal() { return VBoxGlobal::instance(); }
    881 
    882 // Helper classes
    883 ////////////////////////////////////////////////////////////////////////////////
    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 QMenu
    890 {
    891     Q_OBJECT
    892 
    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 QMenu
    917 {
    918     Q_OBJECT
    919 
    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  
    3232#include "UIMachineView.h"
    3333#include "UIFrameBuffer.h"
     34
     35#ifdef Q_WS_WIN
     36# include "VBoxUtils-win.h"
     37#endif /* Q_WS_WIN */
    3438
    3539#ifdef Q_WS_X11
     
    880884        /* Trim partial-viewport-rectangle by top-most windows: */
    881885        QRegion viewportRegion(viewportRectangle);
    882         QRegion topMostRegion(VBoxGlobal::areaCoveredByTopMostWindows());
     886        QRegion topMostRegion(NativeWindowSubsystem::areaCoveredByTopMostWindows());
    883887        viewportRegion -= topMostRegion;
    884888        /* Check if partial-viewport-region consists of 1 rectangle: */
Note: See TracChangeset for help on using the changeset viewer.

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