VirtualBox

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

Last change on this file since 35740 was 33386, checked in by vboxsync, 14 years ago

VRDE: API changes for the VRDP server separation.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use