VirtualBox

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

Last change on this file since 43138 was 42868, checked in by vboxsync, 12 years ago

FE/Qt: VM information dialog: Table pseudo-HTML formatting bug fix.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use