VirtualBox

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

Last change on this file since 50841 was 50841, checked in by vboxsync, 11 years ago

FE/Qt: show VM uptime in session information dialog

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

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