PageRenderTime 67ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 1ms

/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp

https://bitbucket.org/diagiman/vbox-trunk
C++ | 5033 lines | 3403 code | 611 blank | 1019 comment | 712 complexity | ccdf44c93e8f2b6eba376c330d717811 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /* $Id$ */
  2. /** @file
  3. * VBox Qt GUI - VBoxGlobal class implementation.
  4. */
  5. /*
  6. * Copyright (C) 2006-2011 Oracle Corporation
  7. *
  8. * This file is part of VirtualBox Open Source Edition (OSE), as
  9. * available from http://www.virtualbox.org. This file is free software;
  10. * you can redistribute it and/or modify it under the terms of the GNU
  11. * General Public License (GPL) as published by the Free Software
  12. * Foundation, in version 2 as it comes in the "COPYING" file of the
  13. * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
  14. * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  15. */
  16. /* Qt includes: */
  17. #include <QProgressDialog>
  18. #include <QLibraryInfo>
  19. #include <QFileDialog>
  20. #include <QToolTip>
  21. #include <QTranslator>
  22. #include <QDesktopWidget>
  23. #include <QDesktopServices>
  24. #include <QMutex>
  25. #include <QToolButton>
  26. #include <QProcess>
  27. #include <QThread>
  28. #include <QPainter>
  29. #include <QSettings>
  30. #include <QTimer>
  31. #include <QDir>
  32. #include <QLocale>
  33. #include <QNetworkProxy>
  34. #ifdef Q_WS_WIN
  35. # include <QEventLoop>
  36. #endif /* Q_WS_WIN */
  37. #ifdef Q_WS_X11
  38. # include <QTextBrowser>
  39. # include <QScrollBar>
  40. # include <QX11Info>
  41. #endif /* Q_WS_X11 */
  42. #ifdef VBOX_GUI_WITH_PIDFILE
  43. # include <QTextStream>
  44. #endif /* VBOX_GUI_WITH_PIDFILE */
  45. /* GUI includes: */
  46. #include "VBoxGlobal.h"
  47. #include "VBoxUtils.h"
  48. #include "UISelectorWindow.h"
  49. #include "UIMessageCenter.h"
  50. #include "QIMessageBox.h"
  51. #include "QIDialogButtonBox.h"
  52. #include "UIIconPool.h"
  53. #include "UIActionPoolSelector.h"
  54. #include "UIActionPoolRuntime.h"
  55. #include "UIExtraDataEventHandler.h"
  56. #include "QIFileDialog.h"
  57. #include "UINetworkManager.h"
  58. #include "UIUpdateManager.h"
  59. #include "UIMachine.h"
  60. #include "UISession.h"
  61. #include "UIConverter.h"
  62. #ifdef Q_WS_X11
  63. # include "UIHotKeyEditor.h"
  64. # ifndef VBOX_OSE
  65. # include "VBoxLicenseViewer.h"
  66. # endif /* VBOX_OSE */
  67. # include "VBoxX11Helper.h"
  68. #endif /* Q_WS_X11 */
  69. #ifdef Q_WS_MAC
  70. # include "VBoxUtils-darwin.h"
  71. # include "UIMachineWindowFullscreen.h"
  72. # include "UIMachineWindowSeamless.h"
  73. #endif /* Q_WS_MAC */
  74. #ifdef VBOX_WITH_VIDEOHWACCEL
  75. # include "VBoxFBOverlay.h"
  76. #endif /* VBOX_WITH_VIDEOHWACCEL */
  77. #ifdef VBOX_WITH_REGISTRATION
  78. # include "UIRegistrationWzd.h"
  79. #endif /* VBOX_WITH_REGISTRATION */
  80. #ifdef VBOX_GUI_WITH_SYSTRAY
  81. #include <iprt/process.h>
  82. #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
  83. #define HOSTSUFF_EXE ".exe"
  84. #else /* !RT_OS_WINDOWS */
  85. #define HOSTSUFF_EXE ""
  86. #endif /* !RT_OS_WINDOWS */
  87. #endif /* VBOX_GUI_WITH_SYSTRAY */
  88. /* COM includes: */
  89. #include "CMachine.h"
  90. #include "CSystemProperties.h"
  91. #include "CUSBDevice.h"
  92. #include "CUSBDeviceFilter.h"
  93. #include "CBIOSSettings.h"
  94. #include "CVRDEServer.h"
  95. #include "CStorageController.h"
  96. #include "CMediumAttachment.h"
  97. #include "CAudioAdapter.h"
  98. #include "CNetworkAdapter.h"
  99. #include "CSerialPort.h"
  100. #include "CParallelPort.h"
  101. #include "CUSBController.h"
  102. #include "CHostUSBDevice.h"
  103. #include "CMediumFormat.h"
  104. #include "CSharedFolder.h"
  105. /* Other VBox includes: */
  106. #include <iprt/asm.h>
  107. #include <iprt/ctype.h>
  108. #include <iprt/err.h>
  109. #include <iprt/param.h>
  110. #include <iprt/path.h>
  111. #include <iprt/env.h>
  112. #include <iprt/file.h>
  113. #include <iprt/ldr.h>
  114. #include <iprt/system.h>
  115. #include <iprt/stream.h>
  116. #include <VBox/vd.h>
  117. #include <VBox/sup.h>
  118. #include <VBox/com/Guid.h>
  119. #include <VBox/VBoxOGLTest.h>
  120. #ifdef Q_WS_X11
  121. #include <iprt/mem.h>
  122. #endif /* Q_WS_X11 */
  123. /* External includes: */
  124. #include <math.h>
  125. #ifdef Q_WS_WIN
  126. #include "shlobj.h"
  127. #endif /* Q_WS_WIN */
  128. #ifdef Q_WS_X11
  129. #undef BOOL /* typedef CARD8 BOOL in Xmd.h conflicts with #define BOOL PRBool
  130. * in COMDefs.h. A better fix would be to isolate X11-specific
  131. * stuff by placing XX* helpers below to a separate source file. */
  132. #include <X11/X.h>
  133. #include <X11/Xmd.h>
  134. #include <X11/Xlib.h>
  135. #include <X11/Xatom.h>
  136. #include <X11/extensions/Xinerama.h>
  137. #define BOOL PRBool
  138. #endif /* Q_WS_X11 */
  139. //#define VBOX_WITH_FULL_DETAILS_REPORT /* hidden for now */
  140. //#warning "port me: check this"
  141. /// @todo bird: Use (U)INT_PTR, (U)LONG_PTR, DWORD_PTR, or (u)intptr_t.
  142. #if defined(Q_OS_WIN64)
  143. typedef __int64 Q_LONG; /* word up to 64 bit signed */
  144. typedef unsigned __int64 Q_ULONG; /* word up to 64 bit unsigned */
  145. #else
  146. typedef long Q_LONG; /* word up to 64 bit signed */
  147. typedef unsigned long Q_ULONG; /* word up to 64 bit unsigned */
  148. #endif
  149. // VBoxMediaEnumEvent
  150. /////////////////////////////////////////////////////////////////////////////
  151. class VBoxMediaEnumEvent : public QEvent
  152. {
  153. public:
  154. /** Constructs a regular enum event */
  155. VBoxMediaEnumEvent (const UIMedium &aMedium,
  156. const VBoxMediaList::iterator &aIterator)
  157. : QEvent ((QEvent::Type) MediaEnumEventType)
  158. , mMedium (aMedium), mIterator (aIterator), mLast (false)
  159. {}
  160. /** Constructs the last enum event */
  161. VBoxMediaEnumEvent (const VBoxMediaList::iterator &aIterator)
  162. : QEvent ((QEvent::Type) MediaEnumEventType)
  163. , mIterator (aIterator), mLast (true)
  164. {}
  165. /** Last enumerated medium (not valid when #last is true) */
  166. const UIMedium mMedium;
  167. /* Iterator which points to the corresponding item in the GUI thread: */
  168. const VBoxMediaList::iterator mIterator;
  169. /** Whether this is the last event for the given enumeration or not */
  170. const bool mLast;
  171. };
  172. // VBoxGlobal
  173. ////////////////////////////////////////////////////////////////////////////////
  174. static bool sVBoxGlobalInited = false;
  175. static bool sVBoxGlobalInCleanup = false;
  176. /** @internal
  177. *
  178. * Special routine to do VBoxGlobal cleanup when the application is being
  179. * terminated. It is called before some essential Qt functionality (for
  180. * instance, QThread) becomes unavailable, allowing us to use it from
  181. * VBoxGlobal::cleanup() if necessary.
  182. */
  183. static void vboxGlobalCleanup()
  184. {
  185. Assert (!sVBoxGlobalInCleanup);
  186. sVBoxGlobalInCleanup = true;
  187. vboxGlobal().cleanup();
  188. }
  189. /** @internal
  190. *
  191. * Determines the rendering mode from the argument. Sets the appropriate
  192. * default rendering mode if the argument is NULL.
  193. */
  194. static RenderMode vboxGetRenderMode (const char *aModeStr)
  195. {
  196. RenderMode mode = InvalidRenderMode;
  197. #if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
  198. mode = Quartz2DMode;
  199. # ifdef RT_ARCH_X86
  200. /* Quartz2DMode doesn't refresh correctly on 32-bit Snow Leopard, use image mode. */
  201. // char szRelease[80];
  202. // if ( RT_SUCCESS (RTSystemQueryOSInfo (RTSYSOSINFO_RELEASE, szRelease, sizeof (szRelease)))
  203. // && !strncmp (szRelease, "10.", 3))
  204. // mode = QImageMode;
  205. # endif
  206. #elif (defined (Q_WS_WIN32) || defined (Q_WS_PM) || defined (Q_WS_X11)) && defined (VBOX_GUI_USE_QIMAGE)
  207. mode = QImageMode;
  208. #elif defined (Q_WS_X11) && defined (VBOX_GUI_USE_SDL)
  209. mode = SDLMode;
  210. #elif defined (VBOX_GUI_USE_QIMAGE)
  211. mode = QImageMode;
  212. #else
  213. # error "Cannot determine the default render mode!"
  214. #endif
  215. if (aModeStr)
  216. {
  217. if (0) ;
  218. #if defined (VBOX_GUI_USE_QIMAGE)
  219. else if (::strcmp (aModeStr, "image") == 0)
  220. mode = QImageMode;
  221. #endif
  222. #if defined (VBOX_GUI_USE_SDL)
  223. else if (::strcmp (aModeStr, "sdl") == 0)
  224. mode = SDLMode;
  225. #endif
  226. #if defined (VBOX_GUI_USE_DDRAW)
  227. else if (::strcmp (aModeStr, "ddraw") == 0)
  228. mode = DDRAWMode;
  229. #endif
  230. #if defined (VBOX_GUI_USE_QUARTZ2D)
  231. else if (::strcmp (aModeStr, "quartz2d") == 0)
  232. mode = Quartz2DMode;
  233. #endif
  234. #if defined (VBOX_GUI_USE_QGLFB)
  235. else if (::strcmp (aModeStr, "qgl") == 0)
  236. mode = QGLMode;
  237. #endif
  238. //#if defined (VBOX_GUI_USE_QGL)
  239. // else if (::strcmp (aModeStr, "qgloverlay") == 0)
  240. // mode = QGLOverlayMode;
  241. //#endif
  242. }
  243. return mode;
  244. }
  245. /** @class VBoxGlobal
  246. *
  247. * The VBoxGlobal class encapsulates the global VirtualBox data.
  248. *
  249. * There is only one instance of this class per VirtualBox application,
  250. * the reference to it is returned by the static instance() method, or by
  251. * the global vboxGlobal() function, that is just an inlined shortcut.
  252. */
  253. VBoxGlobal::VBoxGlobal()
  254. : mValid (false)
  255. , mSelectorWnd (NULL)
  256. , m_pVirtualMachine(0)
  257. , mMainWindow (NULL)
  258. #ifdef VBOX_WITH_REGISTRATION
  259. , mRegDlg (NULL)
  260. #endif
  261. #ifdef VBOX_GUI_WITH_SYSTRAY
  262. , mIsTrayMenu (false)
  263. , mIncreasedWindowCounter (false)
  264. #endif
  265. , mMediaEnumThread (NULL)
  266. , mIsKWinManaged (false)
  267. , mDisablePatm(false)
  268. , mDisableCsam(false)
  269. , mRecompileSupervisor(false)
  270. , mRecompileUser(false)
  271. , mWarpPct(100)
  272. , mVerString("1.0")
  273. , m3DAvailable(false)
  274. , mSettingsPwSet(false)
  275. {
  276. }
  277. //
  278. // Public members
  279. /////////////////////////////////////////////////////////////////////////////
  280. /**
  281. * Returns a reference to the global VirtualBox data, managed by this class.
  282. *
  283. * The main() function of the VBox GUI must call this function soon after
  284. * creating a QApplication instance but before opening any of the main windows
  285. * (to let the VBoxGlobal initialization procedure use various Qt facilities),
  286. * and continue execution only when the isValid() method of the returned
  287. * instancereturns true, i.e. do something like:
  288. *
  289. * @code
  290. * if ( !VBoxGlobal::instance().isValid() )
  291. * return 1;
  292. * @endcode
  293. * or
  294. * @code
  295. * if ( !vboxGlobal().isValid() )
  296. * return 1;
  297. * @endcode
  298. *
  299. * @note Some VBoxGlobal methods can be used on a partially constructed
  300. * VBoxGlobal instance, i.e. from constructors and methods called
  301. * from the VBoxGlobal::init() method, which obtain the instance
  302. * using this instance() call or the ::vboxGlobal() function. Currently, such
  303. * methods are:
  304. * #vmStateText, #vmTypeIcon, #vmTypeText, #vmTypeTextList, #vmTypeFromText.
  305. *
  306. * @see ::vboxGlobal
  307. */
  308. VBoxGlobal &VBoxGlobal::instance()
  309. {
  310. static VBoxGlobal vboxGlobal_instance;
  311. if (!sVBoxGlobalInited)
  312. {
  313. /* check that a QApplication instance is created */
  314. if (qApp)
  315. {
  316. sVBoxGlobalInited = true;
  317. vboxGlobal_instance.init();
  318. /* add our cleanup handler to the list of Qt post routines */
  319. qAddPostRoutine (vboxGlobalCleanup);
  320. }
  321. else
  322. AssertMsgFailed (("Must construct a QApplication first!"));
  323. }
  324. return vboxGlobal_instance;
  325. }
  326. VBoxGlobal::~VBoxGlobal()
  327. {
  328. qDeleteAll (mOsTypeIcons);
  329. }
  330. /* static */
  331. QString VBoxGlobal::qtRTVersionString()
  332. {
  333. return QString::fromLatin1 (qVersion());
  334. }
  335. /* static */
  336. uint VBoxGlobal::qtRTVersion()
  337. {
  338. QString rt_ver_str = VBoxGlobal::qtRTVersionString();
  339. return (rt_ver_str.section ('.', 0, 0).toInt() << 16) +
  340. (rt_ver_str.section ('.', 1, 1).toInt() << 8) +
  341. rt_ver_str.section ('.', 2, 2).toInt();
  342. }
  343. /* static */
  344. QString VBoxGlobal::qtCTVersionString()
  345. {
  346. return QString::fromLatin1 (QT_VERSION_STR);
  347. }
  348. /* static */
  349. uint VBoxGlobal::qtCTVersion()
  350. {
  351. QString ct_ver_str = VBoxGlobal::qtCTVersionString();
  352. return (ct_ver_str.section ('.', 0, 0).toInt() << 16) +
  353. (ct_ver_str.section ('.', 1, 1).toInt() << 8) +
  354. ct_ver_str.section ('.', 2, 2).toInt();
  355. }
  356. QString VBoxGlobal::vboxVersionString() const
  357. {
  358. return mVBox.GetVersion();
  359. }
  360. QString VBoxGlobal::vboxVersionStringNormalized() const
  361. {
  362. return mVBox.GetVersionNormalized();
  363. }
  364. bool VBoxGlobal::isBeta() const
  365. {
  366. return mVBox.GetVersion().contains("BETA", Qt::CaseInsensitive);
  367. }
  368. /**
  369. * Sets the new global settings and saves them to the VirtualBox server.
  370. */
  371. bool VBoxGlobal::setSettings (VBoxGlobalSettings &gs)
  372. {
  373. gs.save (mVBox);
  374. if (!mVBox.isOk())
  375. {
  376. msgCenter().cannotSaveGlobalConfig (mVBox);
  377. return false;
  378. }
  379. /* We don't assign gs to our gset member here, because VBoxCallback
  380. * will update gset as necessary when new settings are successfully
  381. * sent to the VirtualBox server by gs.save(). */
  382. return true;
  383. }
  384. /**
  385. * Returns a reference to the main VBox VM Selector window.
  386. * The reference is valid until application termination.
  387. *
  388. * There is only one such a window per VirtualBox application.
  389. */
  390. UISelectorWindow &VBoxGlobal::selectorWnd()
  391. {
  392. AssertMsg (!vboxGlobal().isVMConsoleProcess(),
  393. ("Must NOT be a VM console process"));
  394. Assert (mValid);
  395. if (!mSelectorWnd)
  396. {
  397. /*
  398. * We pass the address of mSelectorWnd to the constructor to let it be
  399. * initialized right after the constructor is called. It is necessary
  400. * to avoid recursion, since this method may be (and will be) called
  401. * from the below constructor or from constructors/methods it calls.
  402. */
  403. UISelectorWindow *w = new UISelectorWindow (&mSelectorWnd, 0);
  404. Assert (w == mSelectorWnd);
  405. NOREF(w);
  406. }
  407. return *mSelectorWnd;
  408. }
  409. bool VBoxGlobal::startMachine(const QString &strMachineId)
  410. {
  411. /* Some restrictions: */
  412. AssertMsg(mValid, ("VBoxGlobal is invalid"));
  413. AssertMsg(!m_pVirtualMachine, ("Machine already started"));
  414. /* Create VM session: */
  415. CSession session = vboxGlobal().openSession(strMachineId, KLockType_VM);
  416. if (session.isNull())
  417. return false;
  418. /* Start virtual machine: */
  419. UIMachine *pVirtualMachine = new UIMachine(&m_pVirtualMachine, session);
  420. Assert(pVirtualMachine == m_pVirtualMachine);
  421. Q_UNUSED(pVirtualMachine);
  422. return true;
  423. }
  424. UIMachine* VBoxGlobal::virtualMachine()
  425. {
  426. return m_pVirtualMachine;
  427. }
  428. QWidget* VBoxGlobal::vmWindow()
  429. {
  430. if (isVMConsoleProcess() && m_pVirtualMachine)
  431. return m_pVirtualMachine->mainWindow();
  432. return 0;
  433. }
  434. #ifdef VBOX_GUI_WITH_PIDFILE
  435. void VBoxGlobal::createPidfile()
  436. {
  437. if (!m_strPidfile.isEmpty())
  438. {
  439. qint64 pid = qApp->applicationPid();
  440. QFile file(m_strPidfile);
  441. if (file.open(QIODevice::WriteOnly | QIODevice::Truncate))
  442. {
  443. QTextStream out(&file);
  444. out << pid << endl;
  445. }
  446. else
  447. LogRel(("Failed to create pid file %s\n", m_strPidfile.toUtf8().constData()));
  448. }
  449. }
  450. void VBoxGlobal::deletePidfile()
  451. {
  452. if ( !m_strPidfile.isEmpty()
  453. && QFile::exists(m_strPidfile))
  454. QFile::remove(m_strPidfile);
  455. }
  456. #endif
  457. bool VBoxGlobal::brandingIsActive (bool aForce /* = false*/)
  458. {
  459. if (aForce)
  460. return true;
  461. if (mBrandingConfig.isEmpty())
  462. {
  463. mBrandingConfig = QDir(QApplication::applicationDirPath()).absolutePath();
  464. mBrandingConfig += "/custom/custom.ini";
  465. }
  466. return QFile::exists (mBrandingConfig);
  467. }
  468. /**
  469. * Gets a value from the custom .ini file
  470. */
  471. QString VBoxGlobal::brandingGetKey (QString aKey)
  472. {
  473. QSettings s(mBrandingConfig, QSettings::IniFormat);
  474. return s.value(QString("%1").arg(aKey)).toString();
  475. }
  476. #ifdef VBOX_GUI_WITH_SYSTRAY
  477. /**
  478. * Returns true if the current instance a systray menu only (started with
  479. * "-systray" parameter).
  480. */
  481. bool VBoxGlobal::isTrayMenu() const
  482. {
  483. return mIsTrayMenu;
  484. }
  485. void VBoxGlobal::setTrayMenu(bool aIsTrayMenu)
  486. {
  487. mIsTrayMenu = aIsTrayMenu;
  488. }
  489. /**
  490. * Spawns a new selector window (process).
  491. */
  492. void VBoxGlobal::trayIconShowSelector()
  493. {
  494. /* Get the path to the executable. */
  495. char path[RTPATH_MAX];
  496. RTPathAppPrivateArch(path, RTPATH_MAX);
  497. size_t sz = strlen(path);
  498. path[sz++] = RTPATH_DELIMITER;
  499. path[sz] = 0;
  500. char *cmd = path + sz;
  501. sz = RTPATH_MAX - sz;
  502. int rc = 0;
  503. const char VirtualBox_exe[] = "VirtualBox" HOSTSUFF_EXE;
  504. Assert(sz >= sizeof(VirtualBox_exe));
  505. strcpy(cmd, VirtualBox_exe);
  506. const char * args[] = {path, 0 };
  507. rc = RTProcCreate(path, args, RTENV_DEFAULT, RTPROC_FLAGS_DETACHED, NULL);
  508. if (RT_FAILURE(rc))
  509. LogRel(("Systray: Failed to start new selector window! Path=%s, rc=%Rrc\n", path, rc));
  510. }
  511. /**
  512. * Tries to install the tray icon using the current instance (singleton).
  513. * Returns true if this instance is the tray icon, false if not.
  514. */
  515. bool VBoxGlobal::trayIconInstall()
  516. {
  517. int rc = 0;
  518. QString strTrayWinID = mVBox.GetExtraData(GUI_TrayIconWinID);
  519. if (false == strTrayWinID.isEmpty())
  520. {
  521. /* Check if current tray icon is alive by writing some bogus value. */
  522. mVBox.SetExtraData(GUI_TrayIconWinID, "0");
  523. if (mVBox.isOk())
  524. {
  525. /* Current tray icon died - clean up. */
  526. mVBox.SetExtraData(GUI_TrayIconWinID, NULL);
  527. strTrayWinID.clear();
  528. }
  529. }
  530. /* Is there already a tray icon or is tray icon not active? */
  531. if ( (mIsTrayMenu == false)
  532. && (vboxGlobal().settings().trayIconEnabled())
  533. && (QSystemTrayIcon::isSystemTrayAvailable())
  534. && (strTrayWinID.isEmpty()))
  535. {
  536. /* Get the path to the executable. */
  537. char path[RTPATH_MAX];
  538. RTPathAppPrivateArch(path, RTPATH_MAX);
  539. size_t sz = strlen(path);
  540. path[sz++] = RTPATH_DELIMITER;
  541. path[sz] = 0;
  542. char *cmd = path + sz;
  543. sz = RTPATH_MAX - sz;
  544. const char VirtualBox_exe[] = "VirtualBox" HOSTSUFF_EXE;
  545. Assert(sz >= sizeof(VirtualBox_exe));
  546. strcpy(cmd, VirtualBox_exe);
  547. const char * args[] = {path, "-systray", 0 };
  548. rc = RTProcCreate(path, args, RTENV_DEFAULT, RTPROC_FLAGS_DETACHED, NULL);
  549. if (RT_FAILURE(rc))
  550. {
  551. LogRel(("Systray: Failed to start systray window! Path=%s, rc=%Rrc\n", path, rc));
  552. return false;
  553. }
  554. }
  555. if (mIsTrayMenu)
  556. {
  557. // Use this selector for displaying the tray icon
  558. mVBox.SetExtraData(GUI_TrayIconWinID,
  559. QString("%1").arg((qulonglong)vboxGlobal().mainWindow()->winId()));
  560. /* The first process which can grab this "mutex" will win ->
  561. * It will be the tray icon menu then. */
  562. if (mVBox.isOk())
  563. {
  564. emit sigTrayIconShow(true);
  565. return true;
  566. }
  567. }
  568. return false;
  569. }
  570. #endif
  571. #ifdef Q_WS_X11
  572. QList<QRect> XGetDesktopList()
  573. {
  574. /* Prepare empty resulting list: */
  575. QList<QRect> result;
  576. /* Get current display: */
  577. Display* pDisplay = QX11Info::display();
  578. /* If it's a Xinerama desktop: */
  579. if (XineramaIsActive(pDisplay))
  580. {
  581. /* Reading Xinerama data: */
  582. int iScreens = 0;
  583. XineramaScreenInfo *pScreensData = XineramaQueryScreens(pDisplay, &iScreens);
  584. /* Fill resulting list: */
  585. for (int i = 0; i < iScreens; ++ i)
  586. result << QRect(pScreensData[i].x_org, pScreensData[i].y_org,
  587. pScreensData[i].width, pScreensData[i].height);
  588. /* Free screens data: */
  589. XFree(pScreensData);
  590. }
  591. /* Return resulting list: */
  592. return result;
  593. }
  594. QList<Window> XGetWindowIDList()
  595. {
  596. /* Get current display: */
  597. Display *pDisplay = QX11Info::display();
  598. /* Get virtual desktop window: */
  599. Window window = QX11Info::appRootWindow();
  600. /* Get 'client list' atom: */
  601. Atom propNameAtom = XInternAtom(pDisplay, "_NET_CLIENT_LIST", True /* only if exists */);
  602. /* Prepare empty resulting list: */
  603. QList<Window> result;
  604. /* If atom does not exists return empty list: */
  605. if (propNameAtom == None)
  606. return result;
  607. /* Get atom value: */
  608. Atom realAtomType = None;
  609. int iRealFormat = 0;
  610. unsigned long uItemsCount = 0;
  611. unsigned long uBytesAfter = 0;
  612. unsigned char *pData = 0;
  613. int rc = XGetWindowProperty(pDisplay, window, propNameAtom,
  614. 0, 0x7fffffff /*LONG_MAX*/, False /* delete */,
  615. XA_WINDOW, &realAtomType, &iRealFormat,
  616. &uItemsCount, &uBytesAfter, &pData);
  617. /* If get property is failed return empty list: */
  618. if (rc != Success)
  619. return result;
  620. /* Fill resulting list with win ids: */
  621. Window *pWindowData = reinterpret_cast<Window*>(pData);
  622. for (ulong i = 0; i < uItemsCount; ++ i)
  623. result << pWindowData[i];
  624. /* Releasing resources: */
  625. XFree(pData);
  626. /* Return resulting list: */
  627. return result;
  628. }
  629. QList<ulong> XGetStrut(Window window)
  630. {
  631. /* Get current display: */
  632. Display *pDisplay = QX11Info::display();
  633. /* Get 'strut' atom: */
  634. Atom propNameAtom = XInternAtom(pDisplay, "_NET_WM_STRUT_PARTIAL", True /* only if exists */);
  635. /* Prepare empty resulting list: */
  636. QList<ulong> result;
  637. /* If atom does not exists return empty list: */
  638. if (propNameAtom == None)
  639. return result;
  640. /* Get atom value: */
  641. Atom realAtomType = None;
  642. int iRealFormat = 0;
  643. ulong uItemsCount = 0;
  644. ulong uBytesAfter = 0;
  645. unsigned char *pData = 0;
  646. int rc = XGetWindowProperty(pDisplay, window, propNameAtom,
  647. 0, LONG_MAX, False /* delete */,
  648. XA_CARDINAL, &realAtomType, &iRealFormat,
  649. &uItemsCount, &uBytesAfter, &pData);
  650. /* If get property is failed return empty list: */
  651. if (rc != Success)
  652. return result;
  653. /* Fill resulting list with strut shifts: */
  654. ulong *pStrutsData = reinterpret_cast<ulong*>(pData);
  655. for (ulong i = 0; i < uItemsCount; ++ i)
  656. result << pStrutsData[i];
  657. /* Releasing resources: */
  658. XFree(pData);
  659. /* Return resulting list: */
  660. return result;
  661. }
  662. #endif /* ifdef Q_WS_X11 */
  663. const QRect VBoxGlobal::availableGeometry(int iScreen) const
  664. {
  665. /* Prepare empty result: */
  666. QRect result;
  667. #ifdef Q_WS_X11
  668. /* Get current display: */
  669. Display* pDisplay = QX11Info::display();
  670. /* Get current application desktop: */
  671. QDesktopWidget *pDesktopWidget = QApplication::desktop();
  672. /* If it's a virtual desktop: */
  673. if (pDesktopWidget->isVirtualDesktop())
  674. {
  675. /* If it's a Xinerama desktop: */
  676. if (XineramaIsActive(pDisplay))
  677. {
  678. /* Get desktops list: */
  679. QList<QRect> desktops = XGetDesktopList();
  680. /* Combine to get full virtual region: */
  681. QRegion virtualRegion;
  682. foreach (QRect desktop, desktops)
  683. virtualRegion += desktop;
  684. virtualRegion = virtualRegion.boundingRect();
  685. /* Remember initial virtual desktop: */
  686. QRect virtualDesktop = virtualRegion.boundingRect();
  687. //AssertMsgFailed(("LOG... Virtual desktop is: %dx%dx%dx%d\n", virtualDesktop.x(), virtualDesktop.y(),
  688. // virtualDesktop.width(), virtualDesktop.height()));
  689. /* Set available geometry to screen geometry initially: */
  690. result = desktops[iScreen];
  691. /* Feat available geometry of virtual desktop to respect all the struts: */
  692. QList<Window> list = XGetWindowIDList();
  693. for (int i = 0; i < list.size(); ++ i)
  694. {
  695. /* Get window: */
  696. Window wid = list[i];
  697. QList<ulong> struts = XGetStrut(wid);
  698. /* If window has strut: */
  699. if (struts.size())
  700. {
  701. ulong uLeftShift = struts[0];
  702. ulong uLeftFromY = struts[4];
  703. ulong uLeftToY = struts[5];
  704. ulong uRightShift = struts[1];
  705. ulong uRightFromY = struts[6];
  706. ulong uRightToY = struts[7];
  707. ulong uTopShift = struts[2];
  708. ulong uTopFromX = struts[8];
  709. ulong uTopToX = struts[9];
  710. ulong uBottomShift = struts[3];
  711. ulong uBottomFromX = struts[10];
  712. ulong uBottomToX = struts[11];
  713. if (uLeftShift)
  714. {
  715. QRect sr(QPoint(0, uLeftFromY),
  716. QSize(uLeftShift, uLeftToY - uLeftFromY + 1));
  717. //AssertMsgFailed(("LOG... Subtract left strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height()));
  718. virtualRegion -= sr;
  719. }
  720. if (uRightShift)
  721. {
  722. QRect sr(QPoint(virtualDesktop.x() + virtualDesktop.width() - uRightShift, uRightFromY),
  723. QSize(virtualDesktop.x() + virtualDesktop.width(), uRightToY - uRightFromY + 1));
  724. //AssertMsgFailed(("LOG... Subtract right strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height()));
  725. virtualRegion -= sr;
  726. }
  727. if (uTopShift)
  728. {
  729. QRect sr(QPoint(uTopFromX, 0),
  730. QSize(uTopToX - uTopFromX + 1, uTopShift));
  731. //AssertMsgFailed(("LOG... Subtract top strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height()));
  732. virtualRegion -= sr;
  733. }
  734. if (uBottomShift)
  735. {
  736. QRect sr(QPoint(uBottomFromX, virtualDesktop.y() + virtualDesktop.height() - uBottomShift),
  737. QSize(uBottomToX - uBottomFromX + 1, uBottomShift));
  738. //AssertMsgFailed(("LOG... Subtract bottom strut: top-left: %dx%d, size: %dx%d\n", sr.x(), sr.y(), sr.width(), sr.height()));
  739. virtualRegion -= sr;
  740. }
  741. }
  742. }
  743. /* Get final available geometry: */
  744. result = (virtualRegion & result).boundingRect();
  745. }
  746. }
  747. /* If result is still NULL: */
  748. if (result.isNull())
  749. {
  750. /* Use QT default functionality: */
  751. result = pDesktopWidget->availableGeometry(iScreen);
  752. }
  753. //AssertMsgFailed(("LOG... Final geometry: %dx%dx%dx%d\n", result.x(), result.y(), result.width(), result.height()));
  754. #else /* ifdef Q_WS_X11 */
  755. result = QApplication::desktop()->availableGeometry(iScreen);
  756. #endif /* ifndef Q_WS_X11 */
  757. return result;
  758. }
  759. /**
  760. * Returns the list of few guest OS types, queried from
  761. * IVirtualBox corresponding to every family id.
  762. */
  763. QList <CGuestOSType> VBoxGlobal::vmGuestOSFamilyList() const
  764. {
  765. QList <CGuestOSType> result;
  766. for (int i = 0 ; i < mFamilyIDs.size(); ++ i)
  767. result << mTypes [i][0];
  768. return result;
  769. }
  770. /**
  771. * Returns the list of all guest OS types, queried from
  772. * IVirtualBox corresponding to passed family id.
  773. */
  774. QList <CGuestOSType> VBoxGlobal::vmGuestOSTypeList (const QString &aFamilyId) const
  775. {
  776. AssertMsg (mFamilyIDs.contains (aFamilyId), ("Family ID incorrect: '%s'.", aFamilyId.toLatin1().constData()));
  777. return mFamilyIDs.contains (aFamilyId) ?
  778. mTypes [mFamilyIDs.indexOf (aFamilyId)] : QList <CGuestOSType>();
  779. }
  780. /**
  781. * Returns the icon corresponding to the given guest OS type id.
  782. */
  783. QPixmap VBoxGlobal::vmGuestOSTypeIcon (const QString &aTypeId) const
  784. {
  785. static const QPixmap none;
  786. QPixmap *p = mOsTypeIcons.value (aTypeId);
  787. AssertMsg (p, ("Icon for type '%s' must be defined.", aTypeId.toLatin1().constData()));
  788. return p ? *p : none;
  789. }
  790. /**
  791. * Returns the guest OS type object corresponding to the given type id of list
  792. * containing OS types related to OS family determined by family id attribute.
  793. * If the index is invalid a null object is returned.
  794. */
  795. CGuestOSType VBoxGlobal::vmGuestOSType (const QString &aTypeId,
  796. const QString &aFamilyId /* = QString::null */) const
  797. {
  798. QList <CGuestOSType> list;
  799. if (mFamilyIDs.contains (aFamilyId))
  800. {
  801. list = mTypes [mFamilyIDs.indexOf (aFamilyId)];
  802. }
  803. else
  804. {
  805. for (int i = 0; i < mFamilyIDs.size(); ++ i)
  806. list += mTypes [i];
  807. }
  808. for (int j = 0; j < list.size(); ++ j)
  809. if (!list [j].GetId().compare (aTypeId))
  810. return list [j];
  811. AssertMsgFailed (("Type ID incorrect: '%s'.", aTypeId.toLatin1().constData()));
  812. return CGuestOSType();
  813. }
  814. /**
  815. * Returns the description corresponding to the given guest OS type id.
  816. */
  817. QString VBoxGlobal::vmGuestOSTypeDescription (const QString &aTypeId) const
  818. {
  819. for (int i = 0; i < mFamilyIDs.size(); ++ i)
  820. {
  821. QList <CGuestOSType> list (mTypes [i]);
  822. for ( int j = 0; j < list.size(); ++ j)
  823. if (!list [j].GetId().compare (aTypeId))
  824. return list [j].GetDescription();
  825. }
  826. return QString::null;
  827. }
  828. struct PortConfig
  829. {
  830. const char *name;
  831. const ulong IRQ;
  832. const ulong IOBase;
  833. };
  834. static const PortConfig kComKnownPorts[] =
  835. {
  836. { "COM1", 4, 0x3F8 },
  837. { "COM2", 3, 0x2F8 },
  838. { "COM3", 4, 0x3E8 },
  839. { "COM4", 3, 0x2E8 },
  840. /* must not contain an element with IRQ=0 and IOBase=0 used to cause
  841. * toCOMPortName() to return the "User-defined" string for these values. */
  842. };
  843. static const PortConfig kLptKnownPorts[] =
  844. {
  845. { "LPT1", 7, 0x378 },
  846. { "LPT2", 5, 0x278 },
  847. { "LPT1", 2, 0x3BC },
  848. /* must not contain an element with IRQ=0 and IOBase=0 used to cause
  849. * toLPTPortName() to return the "User-defined" string for these values. */
  850. };
  851. /**
  852. * Similar to toString (KMediumType), but returns 'Differencing' for
  853. * normal hard disks that have a parent.
  854. */
  855. QString VBoxGlobal::mediumTypeString(const CMedium &medium) const
  856. {
  857. if (!medium.GetParent().isNull())
  858. {
  859. Assert(medium.GetType() == KMediumType_Normal);
  860. return mDiskTypes_Differencing;
  861. }
  862. return gpConverter->toString(medium.GetType());
  863. }
  864. /**
  865. * Returns the list of the standard COM port names (i.e. "COMx").
  866. */
  867. QStringList VBoxGlobal::COMPortNames() const
  868. {
  869. QStringList list;
  870. for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i)
  871. list << kComKnownPorts [i].name;
  872. return list;
  873. }
  874. /**
  875. * Returns the list of the standard LPT port names (i.e. "LPTx").
  876. */
  877. QStringList VBoxGlobal::LPTPortNames() const
  878. {
  879. QStringList list;
  880. for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i)
  881. list << kLptKnownPorts [i].name;
  882. return list;
  883. }
  884. /**
  885. * Returns the name of the standard COM port corresponding to the given
  886. * parameters, or "User-defined" (which is also returned when both
  887. * @a aIRQ and @a aIOBase are 0).
  888. */
  889. QString VBoxGlobal::toCOMPortName (ulong aIRQ, ulong aIOBase) const
  890. {
  891. for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i)
  892. if (kComKnownPorts [i].IRQ == aIRQ &&
  893. kComKnownPorts [i].IOBase == aIOBase)
  894. return kComKnownPorts [i].name;
  895. return mUserDefinedPortName;
  896. }
  897. /**
  898. * Returns the name of the standard LPT port corresponding to the given
  899. * parameters, or "User-defined" (which is also returned when both
  900. * @a aIRQ and @a aIOBase are 0).
  901. */
  902. QString VBoxGlobal::toLPTPortName (ulong aIRQ, ulong aIOBase) const
  903. {
  904. for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i)
  905. if (kLptKnownPorts [i].IRQ == aIRQ &&
  906. kLptKnownPorts [i].IOBase == aIOBase)
  907. return kLptKnownPorts [i].name;
  908. return mUserDefinedPortName;
  909. }
  910. /**
  911. * Returns port parameters corresponding to the given standard COM name.
  912. * Returns @c true on success, or @c false if the given port name is not one
  913. * of the standard names (i.e. "COMx").
  914. */
  915. bool VBoxGlobal::toCOMPortNumbers (const QString &aName, ulong &aIRQ,
  916. ulong &aIOBase) const
  917. {
  918. for (size_t i = 0; i < RT_ELEMENTS (kComKnownPorts); ++ i)
  919. if (strcmp (kComKnownPorts [i].name, aName.toUtf8().data()) == 0)
  920. {
  921. aIRQ = kComKnownPorts [i].IRQ;
  922. aIOBase = kComKnownPorts [i].IOBase;
  923. return true;
  924. }
  925. return false;
  926. }
  927. /**
  928. * Returns port parameters corresponding to the given standard LPT name.
  929. * Returns @c true on success, or @c false if the given port name is not one
  930. * of the standard names (i.e. "LPTx").
  931. */
  932. bool VBoxGlobal::toLPTPortNumbers (const QString &aName, ulong &aIRQ,
  933. ulong &aIOBase) const
  934. {
  935. for (size_t i = 0; i < RT_ELEMENTS (kLptKnownPorts); ++ i)
  936. if (strcmp (kLptKnownPorts [i].name, aName.toUtf8().data()) == 0)
  937. {
  938. aIRQ = kLptKnownPorts [i].IRQ;
  939. aIOBase = kLptKnownPorts [i].IOBase;
  940. return true;
  941. }
  942. return false;
  943. }
  944. /**
  945. * Searches for the given hard disk in the list of known media descriptors and
  946. * calls UIMedium::details() on the found descriptor.
  947. *
  948. * If the requested hard disk is not found (for example, it's a new hard disk
  949. * for a new VM created outside our UI), then media enumeration is requested and
  950. * the search is repeated. We assume that the second attempt always succeeds and
  951. * assert otherwise.
  952. *
  953. * @note Technically, the second attempt may fail if, for example, the new hard
  954. * passed to this method disk gets removed before #startEnumeratingMedia()
  955. * succeeds. This (unexpected object uninitialization) is a generic
  956. * problem though and needs to be addressed using exceptions (see also the
  957. * @todo in UIMedium::details()).
  958. */
  959. QString VBoxGlobal::details (const CMedium &aMedium, bool aPredictDiff, bool fUseHtml /* = true */)
  960. {
  961. CMedium cmedium (aMedium);
  962. UIMedium medium;
  963. if (!findMedium (cmedium, medium))
  964. {
  965. /* Medium may be new and not already in the media list, request refresh */
  966. startEnumeratingMedia();
  967. if (!findMedium (cmedium, medium))
  968. /* Medium might be deleted already, return null string */
  969. return QString();
  970. }
  971. return fUseHtml ? medium.detailsHTML (true /* aNoDiffs */, aPredictDiff) :
  972. medium.details(true /* aNoDiffs */, aPredictDiff);
  973. }
  974. /**
  975. * Returns the details of the given USB device as a single-line string.
  976. */
  977. QString VBoxGlobal::details (const CUSBDevice &aDevice) const
  978. {
  979. QString sDetails;
  980. if (aDevice.isNull())
  981. sDetails = tr("Unknown device", "USB device details");
  982. else
  983. {
  984. QString m = aDevice.GetManufacturer().trimmed();
  985. QString p = aDevice.GetProduct().trimmed();
  986. if (m.isEmpty() && p.isEmpty())
  987. {
  988. sDetails =
  989. tr ("Unknown device %1:%2", "USB device details")
  990. .arg (QString().sprintf ("%04hX", aDevice.GetVendorId()))
  991. .arg (QString().sprintf ("%04hX", aDevice.GetProductId()));
  992. }
  993. else
  994. {
  995. if (p.toUpper().startsWith (m.toUpper()))
  996. sDetails = p;
  997. else
  998. sDetails = m + " " + p;
  999. }
  1000. ushort r = aDevice.GetRevision();
  1001. if (r != 0)
  1002. sDetails += QString().sprintf (" [%04hX]", r);
  1003. }
  1004. return sDetails.trimmed();
  1005. }
  1006. /**
  1007. * Returns the multi-line description of the given USB device.
  1008. */
  1009. QString VBoxGlobal::toolTip (const CUSBDevice &aDevice) const
  1010. {
  1011. QString tip =
  1012. tr ("<nobr>Vendor ID: %1</nobr><br>"
  1013. "<nobr>Product ID: %2</nobr><br>"
  1014. "<nobr>Revision: %3</nobr>", "USB device tooltip")
  1015. .arg (QString().sprintf ("%04hX", aDevice.GetVendorId()))
  1016. .arg (QString().sprintf ("%04hX", aDevice.GetProductId()))
  1017. .arg (QString().sprintf ("%04hX", aDevice.GetRevision()));
  1018. QString ser = aDevice.GetSerialNumber();
  1019. if (!ser.isEmpty())
  1020. tip += QString (tr ("<br><nobr>Serial No. %1</nobr>", "USB device tooltip"))
  1021. .arg (ser);
  1022. /* add the state field if it's a host USB device */
  1023. CHostUSBDevice hostDev (aDevice);
  1024. if (!hostDev.isNull())
  1025. {
  1026. tip += QString (tr ("<br><nobr>State: %1</nobr>", "USB device tooltip"))
  1027. .arg (gpConverter->toString (hostDev.GetState()));
  1028. }
  1029. return tip;
  1030. }
  1031. /**
  1032. * Returns the multi-line description of the given USB filter
  1033. */
  1034. QString VBoxGlobal::toolTip (const CUSBDeviceFilter &aFilter) const
  1035. {
  1036. QString tip;
  1037. QString vendorId = aFilter.GetVendorId();
  1038. if (!vendorId.isEmpty())
  1039. tip += tr ("<nobr>Vendor ID: %1</nobr>", "USB filter tooltip")
  1040. .arg (vendorId);
  1041. QString productId = aFilter.GetProductId();
  1042. if (!productId.isEmpty())
  1043. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product ID: %2</nobr>", "USB filter tooltip")
  1044. .arg (productId);
  1045. QString revision = aFilter.GetRevision();
  1046. if (!revision.isEmpty())
  1047. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Revision: %3</nobr>", "USB filter tooltip")
  1048. .arg (revision);
  1049. QString product = aFilter.GetProduct();
  1050. if (!product.isEmpty())
  1051. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Product: %4</nobr>", "USB filter tooltip")
  1052. .arg (product);
  1053. QString manufacturer = aFilter.GetManufacturer();
  1054. if (!manufacturer.isEmpty())
  1055. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Manufacturer: %5</nobr>", "USB filter tooltip")
  1056. .arg (manufacturer);
  1057. QString serial = aFilter.GetSerialNumber();
  1058. if (!serial.isEmpty())
  1059. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Serial No.: %1</nobr>", "USB filter tooltip")
  1060. .arg (serial);
  1061. QString port = aFilter.GetPort();
  1062. if (!port.isEmpty())
  1063. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>Port: %1</nobr>", "USB filter tooltip")
  1064. .arg (port);
  1065. /* add the state field if it's a host USB device */
  1066. CHostUSBDevice hostDev (aFilter);
  1067. if (!hostDev.isNull())
  1068. {
  1069. tip += tip.isEmpty() ? "":"<br/>" + tr ("<nobr>State: %1</nobr>", "USB filter tooltip")
  1070. .arg (gpConverter->toString (hostDev.GetState()));
  1071. }
  1072. return tip;
  1073. }
  1074. /**
  1075. * Returns a details report on a given VM represented as a HTML table.
  1076. *
  1077. * @param aMachine Machine to create a report for.
  1078. * @param aWithLinks @c true if section titles should be hypertext links.
  1079. */
  1080. QString VBoxGlobal::detailsReport (const CMachine &aMachine, bool aWithLinks)
  1081. {
  1082. /* Details templates */
  1083. static const char *sTableTpl =
  1084. "<table border=0 cellspacing=1 cellpadding=0>%1</table>";
  1085. static const char *sSectionHrefTpl =
  1086. "<tr><td width=22 rowspan=%1 align=left><img src='%2'></td>"
  1087. "<td colspan=3><b><a href='%3'><nobr>%4</nobr></a></b></td></tr>"
  1088. "%5"
  1089. "<tr><td colspan=3><font size=1>&nbsp;</font></td></tr>";
  1090. static const char *sSectionBoldTpl =
  1091. "<tr><td width=22 rowspan=%1 align=left><img src='%2'></td>"
  1092. "<td colspan=3><!-- %3 --><b><nobr>%4</nobr></b></td></tr>"
  1093. "%5"
  1094. "<tr><td colspan=3><font size=1>&nbsp;</font></td></tr>";
  1095. static const char *sSectionItemTpl1 =
  1096. "<tr><td width=40%><nobr><i>%1</i></nobr></td><td/><td/></tr>";
  1097. static const char *sSectionItemTpl2 =
  1098. "<tr><td width=40%><nobr>%1:</nobr></td><td/><td>%2</td></tr>";
  1099. static const char *sSectionItemTpl3 =
  1100. "<tr><td width=40%><nobr>%1</nobr></td><td/><td/></tr>";
  1101. const QString &sectionTpl = aWithLinks ? sSectionHrefTpl : sSectionBoldTpl;
  1102. /* Compose details report */
  1103. QString report;
  1104. /* General */
  1105. {
  1106. QString item = QString (sSectionItemTpl2).arg (tr ("Name", "details report"),
  1107. aMachine.GetName())
  1108. + QString (sSectionItemTpl2).arg (tr ("OS Type", "details report"),
  1109. vmGuestOSTypeDescription (aMachine.GetOSTypeId()));
  1110. report += sectionTpl
  1111. .arg (2 + 2) /* rows */
  1112. .arg (":/machine_16px.png", /* icon */
  1113. "#general", /* link */
  1114. tr ("General", "details report"), /* title */
  1115. item); /* items */
  1116. }
  1117. /* System */
  1118. {
  1119. /* BIOS Settings holder */
  1120. CBIOSSettings biosSettings = aMachine.GetBIOSSettings();
  1121. /* System details row count: */
  1122. int iRowCount = 2; /* Memory & CPU details rows initially. */
  1123. /* Boot order */
  1124. QString bootOrder;
  1125. for (ulong i = 1; i <= mVBox.GetSystemProperties().GetMaxBootPosition(); ++ i)
  1126. {
  1127. KDeviceType device = aMachine.GetBootOrder (i);
  1128. if (device == KDeviceType_Null)
  1129. continue;
  1130. if (!bootOrder.isEmpty())
  1131. bootOrder += ", ";
  1132. bootOrder += gpConverter->toString (device);
  1133. }
  1134. if (bootOrder.isEmpty())
  1135. bootOrder = gpConverter->toString (KDeviceType_Null);
  1136. iRowCount += 1; /* Boot-order row. */
  1137. #ifdef VBOX_WITH_FULL_DETAILS_REPORT
  1138. /* ACPI */
  1139. QString acpi = biosSettings.GetACPIEnabled()
  1140. ? tr ("Enabled", "details report (ACPI)")
  1141. : tr ("Disabled", "details report (ACPI)");
  1142. /* IO APIC */
  1143. QString ioapic = biosSettings.GetIOAPICEnabled()
  1144. ? tr ("Enabled", "details report (IO APIC)")
  1145. : tr ("Disabled", "details report (IO APIC)");
  1146. /* PAE/NX */
  1147. QString pae = aMachine.GetCpuProperty(KCpuPropertyType_PAE)
  1148. ? tr ("Enabled", "details report (PAE/NX)")
  1149. : tr ("Disabled", "details report (PAE/NX)");
  1150. iRowCount += 3; /* Full report rows. */
  1151. #endif /* VBOX_WITH_FULL_DETAILS_REPORT */
  1152. /* VT-x/AMD-V */
  1153. QString virt = aMachine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled)
  1154. ? tr ("Enabled", "details report (VT-x/AMD-V)")
  1155. : tr ("Disabled", "details report (VT-x/AMD-V)");
  1156. /* Nested Paging */
  1157. QString nested = aMachine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging)
  1158. ? tr ("Enabled", "details report (Nested Paging)")
  1159. : tr ("Disabled", "details report (Nested Paging)");
  1160. /* VT-x/AMD-V availability: */
  1161. bool fVTxAMDVSupported = host().GetProcessorFeature(KProcessorFeature_HWVirtEx);
  1162. if (fVTxAMDVSupported)
  1163. iRowCount += 2; /* VT-x/AMD-V items. */
  1164. QString item = QString (sSectionItemTpl2).arg (tr ("Base Memory", "details report"),
  1165. tr ("<nobr>%1 MB</nobr>", "details report"))
  1166. .arg (aMachine.GetMemorySize())
  1167. + QString (sSectionItemTpl2).arg (tr ("Processor(s)", "details report"),
  1168. tr ("<nobr>%1</nobr>", "details report"))
  1169. .arg (aMachine.GetCPUCount())
  1170. + QString (sSectionItemTpl2).arg (tr ("Execution Cap", "details report"),
  1171. tr ("<nobr>%1%</nobr>", "details report"))
  1172. .arg (aMachine.GetCPUExecutionCap())
  1173. + QString (sSectionItemTpl2).arg (tr ("Boot Order", "details report"), bootOrder)
  1174. #ifdef VBOX_WITH_FULL_DETAILS_REPORT
  1175. + QString (sSectionItemTpl2).arg (tr ("ACPI", "details report"), acpi)
  1176. + QString (sSectionItemTpl2).arg (tr ("IO APIC", "details report"), ioapic)
  1177. + QString (sSectionItemTpl2).arg (tr ("PAE/NX", "details report"), pae)
  1178. #endif /* VBOX_WITH_FULL_DETAILS_REPORT */
  1179. ;
  1180. if (fVTxAMDVSupported)
  1181. item += QString (sSectionItemTpl2).arg (tr ("VT-x/AMD-V", "details report"), virt)
  1182. + QString (sSectionItemTpl2).arg (tr ("Nested Paging", "details report"), nested);
  1183. report += sectionTpl
  1184. .arg (2 + iRowCount) /* rows */
  1185. .arg (":/chipset_16px.png", /* icon */
  1186. "#system", /* link */
  1187. tr ("System", "details report"), /* title */
  1188. item); /* items */
  1189. }
  1190. /* Display */
  1191. {
  1192. /* Rows including section header and footer */
  1193. int rows = 2;
  1194. /* Video tab */
  1195. QString item = QString(sSectionItemTpl2)
  1196. .arg(tr ("Video Memory", "details report"),
  1197. tr ("<nobr>%1 MB</nobr>", "details report"))
  1198. .arg(aMachine.GetVRAMSize());
  1199. ++rows;
  1200. int cGuestScreens = aMachine.GetMonitorCount();
  1201. if (cGuestScreens > 1)
  1202. {
  1203. item += QString(sSectionItemTpl2)
  1204. .arg(tr("Screens", "details report"))
  1205. .arg(cGuestScreens);
  1206. ++rows;
  1207. }
  1208. QString acc3d = is3DAvailable() && aMachine.GetAccelerate3DEnabled()
  1209. ? tr ("Enabled", "details report (3D Acceleration)")
  1210. : tr ("Disabled", "details report (3D Acceleration)");
  1211. item += QString(sSectionItemTpl2)
  1212. .arg(tr("3D Acceleration", "details report"), acc3d);
  1213. ++rows;
  1214. #ifdef VBOX_WITH_VIDEOHWACCEL
  1215. QString acc2dVideo = aMachine.GetAccelerate2DVideoEnabled()
  1216. ? tr ("Enabled", "details report (2D Video Acceleration)")
  1217. : tr ("Disabled", "details report (2D Video Acceleration)");
  1218. item += QString (sSectionItemTpl2)
  1219. .arg (tr ("2D Video Acceleration", "details report"), acc2dVideo);
  1220. ++ rows;
  1221. #endif
  1222. /* VRDP tab */
  1223. CVRDEServer srv = aMachine.GetVRDEServer();
  1224. if (!srv.isNull())
  1225. {
  1226. if (srv.GetEnabled())
  1227. item += QString (sSectionItemTpl2)
  1228. .arg (tr ("Remote Desktop Server Port", "details report (VRDE Server)"))
  1229. .arg (srv.GetVRDEProperty("TCP/Ports"));
  1230. else
  1231. item += QString (sSectionItemTpl2)
  1232. .arg (tr ("Remote Desktop Server", "details report (VRDE Server)"))
  1233. .arg (tr ("Disabled", "details report (VRDE Server)"));
  1234. ++ rows;
  1235. }
  1236. report += sectionTpl
  1237. .arg (rows) /* rows */
  1238. .arg (":/vrdp_16px.png", /* icon */
  1239. "#display", /* link */
  1240. tr ("Display", "details report"), /* title */
  1241. item); /* items */
  1242. }
  1243. /* Storage */
  1244. {
  1245. /* Rows including section header and footer */
  1246. int rows = 2;
  1247. QString item;
  1248. /* Iterate over the all machine controllers: */
  1249. CStorageControllerVector controllers = aMachine.GetStorageControllers();
  1250. for (int i = 0; i < controllers.size(); ++i)
  1251. {
  1252. /* Get current controller: */
  1253. const CStorageController &controller = controllers[i];
  1254. /* Add controller information: */
  1255. QString strControllerName = QApplication::translate("UIMachineSettingsStorage", "Controller: %1");
  1256. item += QString(sSectionItemTpl3).arg(strControllerName.arg(controller.GetName()));
  1257. ++ rows;
  1258. /* Populate sorted map with attachments information: */
  1259. QMap<StorageSlot,QString> attachmentsMap;
  1260. CMediumAttachmentVector attachments = aMachine.GetMediumAttachmentsOfController(controller.GetName());
  1261. for (int j = 0; j < attachments.size(); ++j)
  1262. {
  1263. /* Get current attachment: */
  1264. const CMediumAttachment &attachment = attachments[j];
  1265. /* Prepare current storage slot: */
  1266. StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice());
  1267. /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */
  1268. QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString();
  1269. if (!strDeviceType.isNull())
  1270. strDeviceType.prepend(' ');
  1271. /* Prepare current medium object: */
  1272. const CMedium &medium = attachment.GetMedium();
  1273. /* Prepare information about current medium & attachment: */
  1274. QString strAttachmentInfo = !attachment.isOk() ? QString() :
  1275. QString(sSectionItemTpl2)
  1276. .arg(QString("&nbsp;&nbsp;") +
  1277. gpConverter->toString(StorageSlot(controller.GetBus(),
  1278. attachment.GetPort(),
  1279. attachment.GetDevice())) + strDeviceType)
  1280. .arg(details(medium, false));
  1281. /* Insert that attachment into map: */
  1282. if (!strAttachmentInfo.isNull())
  1283. attachmentsMap.insert(attachmentSlot, strAttachmentInfo);
  1284. }
  1285. /* Iterate over the sorted map with attachments information: */
  1286. QMapIterator<StorageSlot,QString> it(attachmentsMap);
  1287. while (it.hasNext())
  1288. {
  1289. /* Add controller information: */
  1290. it.next();
  1291. item += it.value();
  1292. ++rows;
  1293. }
  1294. }
  1295. if (item.isNull())
  1296. {
  1297. item = QString (sSectionItemTpl1)
  1298. .arg (tr ("Not Attached", "details report (Storage)"));
  1299. ++ rows;
  1300. }
  1301. report += sectionTpl
  1302. .arg (rows) /* rows */
  1303. .arg (":/attachment_16px.png", /* icon */
  1304. "#storage", /* link */
  1305. tr ("Storage", "details report"), /* title */
  1306. item); /* items */
  1307. }
  1308. /* Audio */
  1309. {
  1310. QString item;
  1311. CAudioAdapter audio = aMachine.GetAudioAdapter();
  1312. int rows = audio.GetEnabled() ? 3 : 2;
  1313. if (audio.GetEnabled())
  1314. item = QString (sSectionItemTpl2)
  1315. .arg (tr ("Host Driver", "details report (audio)"),
  1316. gpConverter->toString (audio.GetAudioDriver())) +
  1317. QString

Large files files are truncated, but you can click here to view the full file