VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxVMInformationDlg.cpp@ 28561

Last change on this file since 28561 was 28561, checked in by vboxsync, 15 years ago

FE/Qt: show the additions version in ( ) if the guest additions are currently not active

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 30.8 KB
Line 
1/* $Id: VBoxVMInformationDlg.cpp 28561 2010-04-21 12:23:37Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt4 GUI ("VirtualBox"):
5 * VBoxVMInformationDlg class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#ifdef VBOX_WITH_PRECOMPILED_HEADERS
25# include "precomp.h"
26#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
27/* Global Includes */
28#include <QTimer>
29
30/* Local Includes */
31#include <VBoxVMInformationDlg.h>
32#include <VBoxGlobal.h>
33#include <VBoxConsoleView.h>
34#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
35
36#ifdef VBOX_WITH_NEW_RUNTIME_CORE
37#include "UIMachineLogic.h"
38#include "UIMachineWindow.h"
39#include "UIMachineView.h"
40#include "UISession.h"
41#endif /* VBOX_WITH_NEW_RUNTIME_CORE */
42
43VBoxVMInformationDlg::InfoDlgMap VBoxVMInformationDlg::mSelfArray = InfoDlgMap();
44
45#ifdef VBOX_WITH_NEW_RUNTIME_CORE
46void VBoxVMInformationDlg::createInformationDlg(UIMachineWindow *pMachineWindow)
47{
48 CMachine machine = pMachineWindow->machineLogic()->uisession()->session().GetMachine();
49 if (mSelfArray.find (machine.GetName()) == mSelfArray.end())
50 {
51 /* Creating new information dialog if there is no one existing */
52 VBoxVMInformationDlg *id = new VBoxVMInformationDlg(pMachineWindow, Qt::Window);
53 id->centerAccording (pMachineWindow->machineWindow());
54 // TODO_NEW_CORE: this seems not necessary, cause we set WA_DeleteOnClose.
55 connect (vboxGlobal().mainWindow(), SIGNAL (closing()), id, SLOT (close()));
56 id->setAttribute (Qt::WA_DeleteOnClose);
57 mSelfArray [machine.GetName()] = id;
58 }
59
60 VBoxVMInformationDlg *info = mSelfArray [machine.GetName()];
61 info->show();
62 info->raise();
63 info->setWindowState (info->windowState() & ~Qt::WindowMinimized);
64 info->activateWindow();
65}
66
67VBoxVMInformationDlg::VBoxVMInformationDlg (UIMachineWindow *pMachineWindow, Qt::WindowFlags aFlags)
68# ifdef Q_WS_MAC
69 : QIWithRetranslateUI2 <QIMainDialog> (pMachineWindow->machineWindow(), aFlags)
70# else /* Q_WS_MAC */
71 : QIWithRetranslateUI2 <QIMainDialog> (0, aFlags)
72# endif /* Q_WS_MAC */
73 , mSession (pMachineWindow->session())
74 , mIsPolished (false)
75 , mStatTimer (new QTimer (this))
76{
77 /* Apply UI decorations */
78 Ui::VBoxVMInformationDlg::setupUi (this);
79
80#ifdef Q_WS_MAC
81 /* No icon for this window on the mac, cause this would act as proxy icon which isn't necessary here. */
82 setWindowIcon (QIcon());
83#else
84 /* Apply window icons */
85 setWindowIcon (vboxGlobal().iconSetFull (QSize (32, 32), QSize (16, 16),
86 ":/session_info_32px.png", ":/session_info_16px.png"));
87#endif
88
89 /* Enable size grip without using a status bar. */
90 setSizeGripEnabled (true);
91
92 /* Setup focus-proxy for pages */
93 mPage1->setFocusProxy (mDetailsText);
94 mPage2->setFocusProxy (mStatisticText);
95
96 /* Setup browsers */
97 mDetailsText->viewport()->setAutoFillBackground (false);
98 mStatisticText->viewport()->setAutoFillBackground (false);
99
100 /* Setup margins */
101 mDetailsText->setViewportMargins (5, 5, 5, 5);
102 mStatisticText->setViewportMargins (5, 5, 5, 5);
103
104 /* Setup handlers */
105 connect (pMachineWindow->uisession(), SIGNAL (sigMediumChange(const CMediumAttachment&)), this, SLOT (updateDetails()));
106 connect (pMachineWindow->uisession(), SIGNAL (sigSharedFolderChange()), this, SLOT (updateDetails()));
107 /* TODO_NEW_CORE: this is ofc not really right in the mm sense. There are
108 * more than one screens. */
109 connect (pMachineWindow->machineView(), SIGNAL (resizeHintDone()), this, SLOT (processStatistics()));
110 connect (mInfoStack, SIGNAL (currentChanged (int)), this, SLOT (onPageChanged (int)));
111 connect (&vboxGlobal(), SIGNAL (mediumEnumFinished (const VBoxMediaList &)), this, SLOT (updateDetails()));
112 connect (mStatTimer, SIGNAL (timeout()), this, SLOT (processStatistics()));
113
114 /* Loading language constants */
115 retranslateUi();
116
117 /* Details page update */
118 updateDetails();
119
120 /* Statistics page update */
121 processStatistics();
122 mStatTimer->start (5000);
123
124 /* Preload dialog attributes for this vm */
125 QString dlgsize = mSession.GetMachine().GetExtraData (VBoxDefs::GUI_InfoDlgState);
126 if (dlgsize.isEmpty())
127 {
128 mWidth = 400;
129 mHeight = 450;
130 mMax = false;
131 }
132 else
133 {
134 QStringList list = dlgsize.split (',');
135 mWidth = list [0].toInt(), mHeight = list [1].toInt();
136 mMax = list [2] == "max";
137 }
138
139 /* Make statistics page the default one */
140 mInfoStack->setCurrentIndex (1);
141}
142#endif /* VBOX_WITH_NEW_RUNTIME_CORE */
143
144void VBoxVMInformationDlg::createInformationDlg (const CSession &aSession, VBoxConsoleView *aConsole)
145{
146 CMachine machine = aSession.GetMachine();
147 if (mSelfArray.find (machine.GetName()) == mSelfArray.end())
148 {
149 /* Creating new information dialog if there is no one existing */
150 VBoxVMInformationDlg *id = new VBoxVMInformationDlg (aConsole, aSession, Qt::Window);
151 id->centerAccording (aConsole);
152 connect (vboxGlobal().mainWindow(), SIGNAL (closing()), id, SLOT (close()));
153 id->setAttribute (Qt::WA_DeleteOnClose);
154 mSelfArray [machine.GetName()] = id;
155 }
156
157 VBoxVMInformationDlg *info = mSelfArray [machine.GetName()];
158 info->show();
159 info->raise();
160 info->setWindowState (info->windowState() & ~Qt::WindowMinimized);
161 info->activateWindow();
162}
163
164VBoxVMInformationDlg::VBoxVMInformationDlg (VBoxConsoleView *aConsole, const CSession &aSession, Qt::WindowFlags aFlags)
165# ifdef Q_WS_MAC
166 : QIWithRetranslateUI2 <QIMainDialog> (aConsole, aFlags)
167# else /* Q_WS_MAC */
168 : QIWithRetranslateUI2 <QIMainDialog> (0, aFlags)
169# endif /* Q_WS_MAC */
170 , mConsole (aConsole)
171 , mSession (aSession)
172 , mIsPolished (false)
173 , mStatTimer (new QTimer (this))
174{
175 /* Apply UI decorations */
176 Ui::VBoxVMInformationDlg::setupUi (this);
177
178#ifdef Q_WS_MAC
179 /* No icon for this window on the mac, cause this would act as proxy icon which isn't necessary here. */
180 setWindowIcon (QIcon());
181#else
182 /* Apply window icons */
183 setWindowIcon (vboxGlobal().iconSetFull (QSize (32, 32), QSize (16, 16),
184 ":/session_info_32px.png", ":/session_info_16px.png"));
185#endif
186
187 /* Enable size grip without using a status bar. */
188 setSizeGripEnabled (true);
189
190 /* Setup focus-proxy for pages */
191 mPage1->setFocusProxy (mDetailsText);
192 mPage2->setFocusProxy (mStatisticText);
193
194 /* Setup browsers */
195 mDetailsText->viewport()->setAutoFillBackground (false);
196 mStatisticText->viewport()->setAutoFillBackground (false);
197
198 /* Setup margins */
199 mDetailsText->setViewportMargins (5, 5, 5, 5);
200 mStatisticText->setViewportMargins (5, 5, 5, 5);
201
202 /* Setup handlers */
203 /* Setup handlers */
204 connect (mConsole, SIGNAL (mediaDriveChanged (VBoxDefs::MediumType)), this, SLOT (updateDetails()));
205 connect (mConsole, SIGNAL (sharedFoldersChanged()), this, SLOT (updateDetails()));
206 connect (mConsole, SIGNAL (resizeHintDone()), this, SLOT (processStatistics()));
207 connect (mInfoStack, SIGNAL (currentChanged (int)), this, SLOT (onPageChanged (int)));
208 connect (&vboxGlobal(), SIGNAL (mediumEnumFinished (const VBoxMediaList &)), this, SLOT (updateDetails()));
209 connect (mStatTimer, SIGNAL (timeout()), this, SLOT (processStatistics()));
210
211 /* Loading language constants */
212 retranslateUi();
213
214 /* Details page update */
215 updateDetails();
216
217 /* Statistics page update */
218 processStatistics();
219 mStatTimer->start (5000);
220
221 /* Preload dialog attributes for this vm */
222 QString dlgsize = mSession.GetMachine().GetExtraData (VBoxDefs::GUI_InfoDlgState);
223 if (dlgsize.isEmpty())
224 {
225 mWidth = 400;
226 mHeight = 450;
227 mMax = false;
228 }
229 else
230 {
231 QStringList list = dlgsize.split (',');
232 mWidth = list [0].toInt(), mHeight = list [1].toInt();
233 mMax = list [2] == "max";
234 }
235
236 /* Make statistics page the default one */
237 mInfoStack->setCurrentIndex (1);
238}
239
240VBoxVMInformationDlg::~VBoxVMInformationDlg()
241{
242 /* Save dialog attributes for this vm */
243 QString dlgsize ("%1,%2,%3");
244 mSession.GetMachine().SetExtraData (VBoxDefs::GUI_InfoDlgState,
245 dlgsize.arg (mWidth).arg (mHeight).arg (isMaximized() ? "max" : "normal"));
246
247 if (!mSession.isNull() && !mSession.GetMachine().isNull())
248 mSelfArray.remove (mSession.GetMachine().GetName());
249}
250
251void VBoxVMInformationDlg::retranslateUi()
252{
253 /* Translate uic generated strings */
254 Ui::VBoxVMInformationDlg::retranslateUi (this);
255
256 updateDetails();
257
258 AssertReturnVoid (!mSession.isNull());
259 CMachine machine = mSession.GetMachine();
260 AssertReturnVoid (!machine.isNull());
261
262 /* Setup a dialog caption */
263 setWindowTitle (tr ("%1 - Session Information").arg (machine.GetName()));
264
265 /* Setup a tabwidget page names */
266 mInfoStack->setTabText (0, tr ("&Details"));
267 mInfoStack->setTabText (1, tr ("&Runtime"));
268
269 /* Clear counter names initially */
270 mNamesMap.clear();
271 mUnitsMap.clear();
272 mLinksMap.clear();
273
274 /* Storage statistics */
275 CSystemProperties sp = vboxGlobal().virtualBox().GetSystemProperties();
276 CStorageControllerVector controllers = mSession.GetMachine().GetStorageControllers();
277 int ideCount = 0, sataCount = 0, scsiCount = 0;
278 foreach (const CStorageController &controller, controllers)
279 {
280 switch (controller.GetBus())
281 {
282 case KStorageBus_IDE:
283 {
284 for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus (KStorageBus_IDE); ++ i)
285 {
286 for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus (KStorageBus_IDE); ++ j)
287 {
288 /* Names */
289 mNamesMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/*DMA")
290 .arg (ideCount).arg (i).arg (j)] = tr ("DMA Transfers");
291 mNamesMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/*PIO")
292 .arg (ideCount).arg (i).arg (j)] = tr ("PIO Transfers");
293 mNamesMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/ReadBytes")
294 .arg (ideCount).arg (i).arg (j)] = tr ("Data Read");
295 mNamesMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/WrittenBytes")
296 .arg (ideCount).arg (i).arg (j)] = tr ("Data Written");
297
298 /* Units */
299 mUnitsMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/*DMA")
300 .arg (ideCount).arg (i).arg (j)] = "[B]";
301 mUnitsMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/*PIO")
302 .arg (ideCount).arg (i).arg (j)] = "[B]";
303 mUnitsMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/ReadBytes")
304 .arg (ideCount).arg (i).arg (j)] = "B";
305 mUnitsMap [QString ("/Devices/IDE%1/ATA%2/Unit%3/WrittenBytes")
306 .arg (ideCount).arg (i).arg (j)] = "B";
307
308 /* Belongs to */
309 mLinksMap [QString ("/Devices/IDE%1/ATA%2/Unit%3").arg (ideCount).arg (i).arg (j)] = QStringList()
310 << QString ("/Devices/IDE%1/ATA%2/Unit%3/*DMA").arg (ideCount).arg (i).arg (j)
311 << QString ("/Devices/IDE%1/ATA%2/Unit%3/*PIO").arg (ideCount).arg (i).arg (j)
312 << QString ("/Devices/IDE%1/ATA%2/Unit%3/ReadBytes").arg (ideCount).arg (i).arg (j)
313 << QString ("/Devices/IDE%1/ATA%2/Unit%3/WrittenBytes").arg (ideCount).arg (i).arg (j);
314 }
315 }
316 ++ ideCount;
317 break;
318 }
319 case KStorageBus_SATA:
320 {
321 for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus (KStorageBus_SATA); ++ i)
322 {
323 for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus (KStorageBus_SATA); ++ j)
324 {
325 /* Names */
326 mNamesMap [QString ("/Devices/SATA%1/Port%2/DMA").arg (sataCount).arg (i)]
327 = tr ("DMA Transfers");
328 mNamesMap [QString ("/Devices/SATA%1/Port%2/ReadBytes").arg (sataCount).arg (i)]
329 = tr ("Data Read");
330 mNamesMap [QString ("/Devices/SATA%1/Port%2/WrittenBytes").arg (sataCount).arg (i)]
331 = tr ("Data Written");
332
333 /* Units */
334 mUnitsMap [QString ("/Devices/SATA%1/Port%2/DMA").arg (sataCount).arg (i)] = "[B]";
335 mUnitsMap [QString ("/Devices/SATA%1/Port%2/ReadBytes").arg (sataCount).arg (i)] = "B";
336 mUnitsMap [QString ("/Devices/SATA%1/Port%2/WrittenBytes").arg (sataCount).arg (i)] = "B";
337
338 /* Belongs to */
339 mLinksMap [QString ("/Devices/SATA%1/Port%2").arg (sataCount).arg (i)] = QStringList()
340 << QString ("/Devices/SATA%1/Port%2/DMA").arg (sataCount).arg (i)
341 << QString ("/Devices/SATA%1/Port%2/ReadBytes").arg (sataCount).arg (i)
342 << QString ("/Devices/SATA%1/Port%2/WrittenBytes").arg (sataCount).arg (i);
343 }
344 }
345 ++ sataCount;
346 break;
347 }
348 case KStorageBus_SCSI:
349 {
350 for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus (KStorageBus_SCSI); ++ i)
351 {
352 for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus (KStorageBus_SCSI); ++ j)
353 {
354 /* Names */
355 mNamesMap [QString ("/Devices/SCSI%1/%2/ReadBytes").arg (scsiCount).arg (i)]
356 = tr ("Data Read");
357 mNamesMap [QString ("/Devices/SCSI%1/%2/WrittenBytes").arg (scsiCount).arg (i)]
358 = tr ("Data Written");
359
360 /* Units */
361 mUnitsMap [QString ("/Devices/SCSI%1/%2/ReadBytes").arg (scsiCount).arg (i)] = "B";
362 mUnitsMap [QString ("/Devices/SCSI%1/%2/WrittenBytes").arg (scsiCount).arg (i)] = "B";
363
364 /* Belongs to */
365 mLinksMap [QString ("/Devices/SCSI%1/%2").arg (scsiCount).arg (i)] = QStringList()
366 << QString ("/Devices/SCSI%1/%2/ReadBytes").arg (scsiCount).arg (i)
367 << QString ("/Devices/SCSI%1/%2/WrittenBytes").arg (scsiCount).arg (i);
368 }
369 }
370 ++ scsiCount;
371 break;
372 }
373 default:
374 break;
375 }
376 }
377
378 /* Network statistics: */
379 ulong count = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount();
380 for (ulong i = 0; i < count; ++ i)
381 {
382 CNetworkAdapter na = machine.GetNetworkAdapter (i);
383 KNetworkAdapterType ty = na.GetAdapterType();
384 const char *name;
385
386 switch (ty)
387 {
388 case KNetworkAdapterType_I82540EM:
389 case KNetworkAdapterType_I82543GC:
390 case KNetworkAdapterType_I82545EM:
391 name = "E1k";
392 break;
393 case KNetworkAdapterType_Virtio:
394 name = "VNet";
395 break;
396 default:
397 name = "PCNet";
398 break;
399 }
400
401 /* Names */
402 mNamesMap [QString ("/Devices/%1%2/TransmitBytes")
403 .arg (name).arg (i)] = tr ("Data Transmitted");
404 mNamesMap [QString ("/Devices/%1%2/ReceiveBytes")
405 .arg (name).arg (i)] = tr ("Data Received");
406
407 /* Units */
408 mUnitsMap [QString ("/Devices/%1%2/TransmitBytes")
409 .arg (name).arg (i)] = "B";
410 mUnitsMap [QString ("/Devices/%1%2/ReceiveBytes")
411 .arg (name).arg (i)] = "B";
412
413 /* Belongs to */
414 mLinksMap [QString ("NA%1").arg (i)] = QStringList()
415 << QString ("/Devices/%1%2/TransmitBytes").arg (name).arg (i)
416 << QString ("/Devices/%1%2/ReceiveBytes").arg (name).arg (i);
417 }
418
419 /* Statistics page update. */
420 refreshStatistics();
421}
422
423bool VBoxVMInformationDlg::event (QEvent *aEvent)
424{
425 bool result = QIMainDialog::event (aEvent);
426 switch (aEvent->type())
427 {
428 case QEvent::WindowStateChange:
429 {
430 if (mIsPolished)
431 mMax = isMaximized();
432 else if (mMax == isMaximized())
433 mIsPolished = true;
434 break;
435 }
436 default:
437 break;
438 }
439 return result;
440}
441
442void VBoxVMInformationDlg::resizeEvent (QResizeEvent *aEvent)
443{
444 QIMainDialog::resizeEvent (aEvent);
445
446 /* Store dialog size for this vm */
447 if (mIsPolished && !isMaximized())
448 {
449 mWidth = width();
450 mHeight = height();
451 }
452}
453
454void VBoxVMInformationDlg::showEvent (QShowEvent *aEvent)
455{
456 /* One may think that QWidget::polish() is the right place to do things
457 * below, but apparently, by the time when QWidget::polish() is called,
458 * the widget style & layout are not fully done, at least the minimum
459 * size hint is not properly calculated. Since this is sometimes necessary,
460 * we provide our own "polish" implementation */
461 if (!mIsPolished)
462 {
463 /* Load window size and state */
464 resize (mWidth, mHeight);
465 if (mMax)
466 QTimer::singleShot (0, this, SLOT (showMaximized()));
467 else
468 mIsPolished = true;
469 }
470
471 QIMainDialog::showEvent (aEvent);
472}
473
474
475void VBoxVMInformationDlg::updateDetails()
476{
477 /* Details page update */
478 mDetailsText->setText (vboxGlobal().detailsReport (mSession.GetMachine(), false /* aWithLinks */));
479}
480
481void VBoxVMInformationDlg::processStatistics()
482{
483 CMachineDebugger dbg = mSession.GetConsole().GetDebugger();
484 QString info;
485
486 /* Process selected statistics: */
487 for (DataMapType::const_iterator it = mNamesMap.begin(); it != mNamesMap.end(); ++ it)
488 {
489 dbg.GetStats (it.key(), true, info);
490 mValuesMap [it.key()] = parseStatistics (info);
491 }
492
493 /* Statistics page update */
494 refreshStatistics();
495}
496
497void VBoxVMInformationDlg::onPageChanged (int aIndex)
498{
499 /* Focusing the browser on shown page */
500 mInfoStack->widget (aIndex)->setFocus();
501}
502
503QString VBoxVMInformationDlg::parseStatistics (const QString &aText)
504{
505 /* Filters the statistic counters body */
506 QRegExp query ("^.+<Statistics>\n(.+)\n</Statistics>.*$");
507 if (query.indexIn (aText) == -1)
508 return QString::null;
509
510 QStringList wholeList = query.cap (1).split ("\n");
511
512 ULONG64 summa = 0;
513 for (QStringList::Iterator lineIt = wholeList.begin(); lineIt != wholeList.end(); ++ lineIt)
514 {
515 QString text = *lineIt;
516 text.remove (1, 1);
517 text.remove (text.length() - 2, 2);
518
519 /* Parse incoming counter and fill the counter-element values. */
520 CounterElementType counter;
521 counter.type = text.section (" ", 0, 0);
522 text = text.section (" ", 1);
523 QStringList list = text.split ("\" ");
524 for (QStringList::Iterator it = list.begin(); it != list.end(); ++ it)
525 {
526 QString pair = *it;
527 QRegExp regExp ("^(.+)=\"([^\"]*)\"?$");
528 regExp.indexIn (pair);
529 counter.list.insert (regExp.cap (1), regExp.cap (2));
530 }
531
532 /* Fill the output with the necessary counter's value.
533 * Currently we are using "c" field of simple counter only. */
534 QString result = counter.list.contains ("c") ? counter.list ["c"] : "0";
535 summa += result.toULongLong();
536 }
537
538 return QString::number (summa);
539}
540
541void VBoxVMInformationDlg::refreshStatistics()
542{
543 if (mSession.isNull())
544 return;
545
546 QString table = "<table width=100% cellspacing=1 cellpadding=0>%1</table>";
547 QString hdrRow = "<tr><td width=22><img src='%1'></td>"
548 "<td colspan=2><nobr><b>%2</b></nobr></td></tr>";
549 QString paragraph = "<tr><td colspan=3></td></tr>";
550 QString result;
551
552 CMachine m = mSession.GetMachine();
553
554 /* Runtime Information */
555 {
556 CConsole console = mSession.GetConsole();
557 ULONG width = 0;
558 ULONG height = 0;
559 ULONG bpp = 0;
560 console.GetDisplay().GetScreenResolution(0, width, height, bpp);
561 QString resolution = QString ("%1x%2")
562 .arg (width)
563 .arg (height);
564 if (bpp)
565 resolution += QString ("x%1").arg (bpp);
566 QString virtualization = console.GetDebugger().GetHWVirtExEnabled() ?
567 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") :
568 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)");
569 QString nested = console.GetDebugger().GetHWVirtExNestedPagingEnabled() ?
570 VBoxGlobal::tr ("Enabled", "details report (Nested Paging)") :
571 VBoxGlobal::tr ("Disabled", "details report (Nested Paging)");
572 QString addVersion = m.GetGuestPropertyValue("/VirtualBox/GuestAdd/Version");
573 QString addRevision = m.GetGuestPropertyValue("/VirtualBox/GuestAdd/Revision");
574 QString addVersionStr;
575 if (!addVersion.isEmpty() && !addRevision.isEmpty())
576 {
577 QString addInfo = console.GetGuest().GetAdditionsVersion();
578 addVersionStr = (addInfo.isEmpty() ? "(" : "")
579 + addVersion
580 + " r"
581 + m.GetGuestPropertyValue("/VirtualBox/GuestAdd/Revision")
582 + (addInfo.isEmpty() ? ")" : "");
583 }
584 else
585 addVersionStr = tr ("Not Detected", "guest additions");
586 QString osType = console.GetGuest().GetOSTypeId();
587 if (osType.isEmpty())
588 osType = tr ("Not Detected", "guest os type");
589 else
590 osType = vboxGlobal().vmGuestOSTypeDescription (osType);
591 int vrdpPort = console.GetRemoteDisplayInfo().GetPort();
592 QString vrdpInfo = (vrdpPort == 0 || vrdpPort == -1)?
593 tr ("Not Available", "details report (VRDP server port)") :
594 QString ("%1").arg (vrdpPort);
595
596 /* Searching for longest string */
597 QStringList valuesList;
598 valuesList << resolution << virtualization << nested << addVersionStr << osType << vrdpInfo;
599 int maxLength = 0;
600 foreach (const QString &value, valuesList)
601 maxLength = maxLength < fontMetrics().width (value) ?
602 fontMetrics().width (value) : maxLength;
603
604 result += hdrRow.arg (":/state_running_16px.png").arg (tr ("Runtime Attributes"));
605 result += formatValue (tr ("Screen Resolution"), resolution, maxLength);
606 result += formatValue (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization, maxLength);
607 result += formatValue (VBoxGlobal::tr ("Nested Paging", "details report"), nested, maxLength);
608 result += formatValue (tr ("Guest Additions"), addVersionStr, maxLength);
609 result += formatValue (tr ("Guest OS Type"), osType, maxLength);
610 result += formatValue (VBoxGlobal::tr ("Remote Display Server Port", "details report (VRDP Server)"), vrdpInfo, maxLength);
611 result += paragraph;
612 }
613
614 /* Storage statistics */
615 {
616 QString storageStat;
617
618 result += hdrRow.arg (":/attachment_16px.png").arg (tr ("Storage Statistics"));
619
620 CStorageControllerVector controllers = mSession.GetMachine().GetStorageControllers();
621 int ideCount = 0, sataCount = 0, scsiCount = 0;
622 foreach (const CStorageController &controller, controllers)
623 {
624 QString ctrName = controller.GetName();
625 KStorageBus busType = controller.GetBus();
626 CMediumAttachmentVector attachments = mSession.GetMachine().GetMediumAttachmentsOfController (ctrName);
627 if (!attachments.isEmpty() && busType != KStorageBus_Floppy)
628 {
629 QString header = "<tr><td></td><td colspan=2><nobr>%1</nobr></td></tr>";
630 storageStat += header.arg (ctrName);
631 int scsiIndex = 0;
632 foreach (const CMediumAttachment &attachment, attachments)
633 {
634 LONG attPort = attachment.GetPort();
635 LONG attDevice = attachment.GetDevice();
636 switch (busType)
637 {
638 case KStorageBus_IDE:
639 {
640 storageStat += formatMedium (ctrName, attPort, attDevice,
641 QString ("/Devices/IDE%1/ATA%2/Unit%3").arg (ideCount).arg (attPort).arg (attDevice));
642 break;
643 }
644 case KStorageBus_SATA:
645 {
646 storageStat += formatMedium (ctrName, attPort, attDevice,
647 QString ("/Devices/SATA%1/Port%2").arg (sataCount).arg (attPort));
648 break;
649 }
650 case KStorageBus_SCSI:
651 {
652 storageStat += formatMedium (ctrName, attPort, attDevice,
653 QString ("/Devices/SCSI%1/%2").arg (scsiCount).arg (scsiIndex));
654 ++ scsiIndex;
655 break;
656 }
657 default:
658 break;
659 }
660 storageStat += paragraph;
661 }
662 }
663
664 switch (busType)
665 {
666 case KStorageBus_IDE:
667 {
668 ++ ideCount;
669 break;
670 }
671 case KStorageBus_SATA:
672 {
673 ++ sataCount;
674 break;
675 }
676 case KStorageBus_SCSI:
677 {
678 ++ scsiCount;
679 break;
680 }
681 default:
682 break;
683 }
684 }
685
686 /* If there are no Hard Disks */
687 if (storageStat.isNull())
688 {
689 storageStat = composeArticle (tr ("No Storage Devices"));
690 storageStat += paragraph;
691 }
692
693 result += storageStat;
694 }
695
696 /* Network Adapters Statistics */
697 {
698 QString networkStat;
699
700 result += hdrRow.arg (":/nw_16px.png").arg (tr ("Network Statistics"));
701
702 /* Network Adapters list */
703 ulong count = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount();
704 for (ulong slot = 0; slot < count; ++ slot)
705 {
706 if (m.GetNetworkAdapter (slot).GetEnabled())
707 {
708 networkStat += formatAdapter (slot, QString ("NA%1").arg (slot));
709 networkStat += paragraph;
710 }
711 }
712
713 /* If there are no Network Adapters */
714 if (networkStat.isNull())
715 {
716 networkStat = composeArticle (tr ("No Network Adapters"));
717 networkStat += paragraph;
718 }
719
720 result += networkStat;
721 }
722
723 /* Show full composed page & save/restore scroll-bar position */
724 int vv = mStatisticText->verticalScrollBar()->value();
725 mStatisticText->setText (table.arg (result));
726 mStatisticText->verticalScrollBar()->setValue (vv);
727}
728
729/**
730 * Allows left-aligned values formatting in right column.
731 *
732 * aValueName - the name of value in the left column.
733 * aValue - left-aligned value itself in the right column.
734 * aMaxSize - maximum width (in pixels) of value in right column.
735 */
736QString VBoxVMInformationDlg::formatValue (const QString &aValueName,
737 const QString &aValue, int aMaxSize)
738{
739 QString bdyRow = "<tr><td></td><td width=50%><nobr>%1</nobr></td>"
740 "<td align=right><nobr>%2"
741 "<img src=:/tpixel.png width=%3 height=1></nobr></td></tr>";
742
743 int size = aMaxSize - fontMetrics().width (aValue);
744 return bdyRow.arg (aValueName).arg (aValue).arg (size);
745}
746
747QString VBoxVMInformationDlg::formatMedium (const QString &aCtrName,
748 LONG aPort, LONG aDevice,
749 const QString &aBelongsTo)
750{
751 if (mSession.isNull())
752 return QString::null;
753
754 QString header = "<tr><td></td><td colspan=2><nobr>&nbsp;&nbsp;%1:</nobr></td></tr>";
755 CStorageController ctr = mSession.GetMachine().GetStorageControllerByName (aCtrName);
756 QString name = vboxGlobal().toString (StorageSlot (ctr.GetBus(), aPort, aDevice));
757 return header.arg (name) + composeArticle (aBelongsTo, 2);
758}
759
760QString VBoxVMInformationDlg::formatAdapter (ULONG aSlot,
761 const QString &aBelongsTo)
762{
763 if (mSession.isNull())
764 return QString::null;
765
766 QString header = "<tr><td></td><td colspan=2><nobr>%1</nobr></td></tr>";
767 QString name = VBoxGlobal::tr ("Adapter %1", "details report (network)").arg (aSlot + 1);
768 return header.arg (name) + composeArticle (aBelongsTo, 1);
769}
770
771QString VBoxVMInformationDlg::composeArticle (const QString &aBelongsTo, int aSpacesCount)
772{
773 QString body = "<tr><td></td><td width=50%><nobr>%1%2</nobr></td>"
774 "<td align=right><nobr>%3%4</nobr></td></tr>";
775 QString indent;
776 for (int i = 0; i < aSpacesCount; ++ i)
777 indent += "&nbsp;&nbsp;";
778 body = body.arg (indent);
779
780 QString result;
781
782 if (mLinksMap.contains (aBelongsTo))
783 {
784 QStringList keys = mLinksMap [aBelongsTo];
785 foreach (const QString &key, keys)
786 {
787 QString line (body);
788 if (mNamesMap.contains (key) && mValuesMap.contains (key) && mUnitsMap.contains (key))
789 {
790 line = line.arg (mNamesMap [key]).arg (QString ("%L1").arg (mValuesMap [key].toULongLong()));
791 line = mUnitsMap [key].contains (QRegExp ("\\[\\S+\\]")) ?
792 line.arg (QString ("<img src=:/tpixel.png width=%1 height=1>")
793 .arg (QApplication::fontMetrics().width (
794 QString (" %1").arg (mUnitsMap [key]
795 .mid (1, mUnitsMap [key].length() - 2))))) :
796 line.arg (QString (" %1").arg (mUnitsMap [key]));
797 result += line;
798 }
799 }
800 }
801 else
802 result = body.arg (aBelongsTo).arg (QString::null).arg (QString::null);
803
804 return result;
805}
806
Note: See TracBrowser for help on using the repository browser.

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