VirtualBox

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

Last change on this file since 39882 was 39882, checked in by vboxsync, 13 years ago

Config.kmk,VMMDev,Main,QtGui,VBoxManage: Refactored IGuest::additionsVersion and associated acts, splitting it up into additionsVersion and additionsRevision like IVirtualBox and IExtPack handles versioning. Fixed missing saved state in VMMDev where the VMMDevReq_ReportGuestInfo2 info was not saved and Main+Frontends led to believe we were running guest additions older than 3.2. The changes have be subjected to limited testing. Added TODOs for another missing save in VMMDev.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 26.8 KB
Line 
1/* $Id: VBoxVMInformationDlg.cpp 39882 2012-01-26 00:54:50Z 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().GetMaxNetworkAdapters(KChipsetType_PIIX3);
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
455 ULONG width = 0;
456 ULONG height = 0;
457 ULONG bpp = 0;
458 console.GetDisplay().GetScreenResolution(0, width, height, bpp);
459 QString resolution = QString ("%1x%2")
460 .arg (width)
461 .arg (height);
462 if (bpp)
463 resolution += QString ("x%1").arg (bpp);
464
465 CMachineDebugger debugger = console.GetDebugger();
466 QString virtualization = debugger.GetHWVirtExEnabled() ?
467 VBoxGlobal::tr ("Enabled", "details report (VT-x/AMD-V)") :
468 VBoxGlobal::tr ("Disabled", "details report (VT-x/AMD-V)");
469 QString nested = debugger.GetHWVirtExNestedPagingEnabled() ?
470 VBoxGlobal::tr ("Enabled", "details report (Nested Paging)") :
471 VBoxGlobal::tr ("Disabled", "details report (Nested Paging)");
472
473 CGuest guest = console.GetGuest();
474 QString addVersionStr = guest.GetAdditionsVersion();
475 if (addVersionStr.isEmpty())
476 addVersionStr = tr("Not Detected", "guest additions");
477 else
478 {
479 ULONG revision = guest.GetAdditionsRevision();
480 if (revision != 0)
481 addVersionStr += QString(" r%1").arg(revision);
482 }
483 QString osType = guest.GetOSTypeId();
484 if (osType.isEmpty())
485 osType = tr ("Not Detected", "guest os type");
486 else
487 osType = vboxGlobal().vmGuestOSTypeDescription (osType);
488
489 int vrdePort = console.GetVRDEServerInfo().GetPort();
490 QString vrdeInfo = (vrdePort == 0 || vrdePort == -1)?
491 tr ("Not Available", "details report (VRDE server port)") :
492 QString ("%1").arg (vrdePort);
493
494 /* Searching for longest string */
495 QStringList valuesList;
496 valuesList << resolution << virtualization << nested << addVersionStr << osType << vrdeInfo;
497 int maxLength = 0;
498 foreach (const QString &value, valuesList)
499 maxLength = maxLength < fontMetrics().width (value) ?
500 fontMetrics().width (value) : maxLength;
501
502 result += hdrRow.arg (":/state_running_16px.png").arg (tr ("Runtime Attributes"));
503 result += formatValue (tr ("Screen Resolution"), resolution, maxLength);
504 result += formatValue (VBoxGlobal::tr ("VT-x/AMD-V", "details report"), virtualization, maxLength);
505 result += formatValue (VBoxGlobal::tr ("Nested Paging", "details report"), nested, maxLength);
506 result += formatValue (tr ("Guest Additions"), addVersionStr, maxLength);
507 result += formatValue (tr ("Guest OS Type"), osType, maxLength);
508 result += formatValue (VBoxGlobal::tr ("Remote Desktop Server Port", "details report (VRDE Server)"), vrdeInfo, maxLength);
509 result += paragraph;
510 }
511
512 /* Storage statistics */
513 {
514 QString storageStat;
515
516 result += hdrRow.arg (":/attachment_16px.png").arg (tr ("Storage Statistics"));
517
518 CStorageControllerVector controllers = mSession.GetMachine().GetStorageControllers();
519 int ideCount = 0, sataCount = 0, scsiCount = 0;
520 foreach (const CStorageController &controller, controllers)
521 {
522 QString ctrName = controller.GetName();
523 KStorageBus busType = controller.GetBus();
524 CMediumAttachmentVector attachments = mSession.GetMachine().GetMediumAttachmentsOfController (ctrName);
525 if (!attachments.isEmpty() && busType != KStorageBus_Floppy)
526 {
527 QString header = "<tr><td></td><td colspan=2><nobr>%1</nobr></td></tr>";
528 storageStat += header.arg (ctrName);
529 int scsiIndex = 0;
530 foreach (const CMediumAttachment &attachment, attachments)
531 {
532 LONG attPort = attachment.GetPort();
533 LONG attDevice = attachment.GetDevice();
534 switch (busType)
535 {
536 case KStorageBus_IDE:
537 {
538 storageStat += formatMedium (ctrName, attPort, attDevice,
539 QString ("/Devices/IDE%1/ATA%2/Unit%3").arg (ideCount).arg (attPort).arg (attDevice));
540 break;
541 }
542 case KStorageBus_SATA:
543 {
544 storageStat += formatMedium (ctrName, attPort, attDevice,
545 QString ("/Devices/SATA%1/Port%2").arg (sataCount).arg (attPort));
546 break;
547 }
548 case KStorageBus_SCSI:
549 {
550 storageStat += formatMedium (ctrName, attPort, attDevice,
551 QString ("/Devices/SCSI%1/%2").arg (scsiCount).arg (scsiIndex));
552 ++ scsiIndex;
553 break;
554 }
555 default:
556 break;
557 }
558 storageStat += paragraph;
559 }
560 }
561
562 switch (busType)
563 {
564 case KStorageBus_IDE:
565 {
566 ++ ideCount;
567 break;
568 }
569 case KStorageBus_SATA:
570 {
571 ++ sataCount;
572 break;
573 }
574 case KStorageBus_SCSI:
575 {
576 ++ scsiCount;
577 break;
578 }
579 default:
580 break;
581 }
582 }
583
584 /* If there are no Hard Disks */
585 if (storageStat.isNull())
586 {
587 storageStat = composeArticle (tr ("No Storage Devices"));
588 storageStat += paragraph;
589 }
590
591 result += storageStat;
592 }
593
594 /* Network Adapters Statistics */
595 {
596 QString networkStat;
597
598 result += hdrRow.arg (":/nw_16px.png").arg (tr ("Network Statistics"));
599
600 /* Network Adapters list */
601 ulong count = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
602 for (ulong slot = 0; slot < count; ++ slot)
603 {
604 if (m.GetNetworkAdapter (slot).GetEnabled())
605 {
606 networkStat += formatAdapter (slot, QString ("NA%1").arg (slot));
607 networkStat += paragraph;
608 }
609 }
610
611 /* If there are no Network Adapters */
612 if (networkStat.isNull())
613 {
614 networkStat = composeArticle (tr ("No Network Adapters"));
615 networkStat += paragraph;
616 }
617
618 result += networkStat;
619 }
620
621 /* Show full composed page & save/restore scroll-bar position */
622 int vv = mStatisticText->verticalScrollBar()->value();
623 mStatisticText->setText (table.arg (result));
624 mStatisticText->verticalScrollBar()->setValue (vv);
625}
626
627/**
628 * Allows left-aligned values formatting in right column.
629 *
630 * aValueName - the name of value in the left column.
631 * aValue - left-aligned value itself in the right column.
632 * aMaxSize - maximum width (in pixels) of value in right column.
633 */
634QString VBoxVMInformationDlg::formatValue (const QString &aValueName,
635 const QString &aValue, int aMaxSize)
636{
637 QString bdyRow = "<tr><td></td><td width=50%><nobr>%1</nobr></td>"
638 "<td align=right><nobr>%2"
639 "<img src=:/tpixel.png width=%3 height=1></nobr></td></tr>";
640
641 int size = aMaxSize - fontMetrics().width (aValue);
642 return bdyRow.arg (aValueName).arg (aValue).arg (size);
643}
644
645QString VBoxVMInformationDlg::formatMedium (const QString &aCtrName,
646 LONG aPort, LONG aDevice,
647 const QString &aBelongsTo)
648{
649 if (mSession.isNull())
650 return QString::null;
651
652 QString header = "<tr><td></td><td colspan=2><nobr>&nbsp;&nbsp;%1:</nobr></td></tr>";
653 CStorageController ctr = mSession.GetMachine().GetStorageControllerByName (aCtrName);
654 QString name = vboxGlobal().toString (StorageSlot (ctr.GetBus(), aPort, aDevice));
655 return header.arg (name) + composeArticle (aBelongsTo, 2);
656}
657
658QString VBoxVMInformationDlg::formatAdapter (ULONG aSlot,
659 const QString &aBelongsTo)
660{
661 if (mSession.isNull())
662 return QString::null;
663
664 QString header = "<tr><td></td><td colspan=2><nobr>%1</nobr></td></tr>";
665 QString name = VBoxGlobal::tr ("Adapter %1", "details report (network)").arg (aSlot + 1);
666 return header.arg (name) + composeArticle (aBelongsTo, 1);
667}
668
669QString VBoxVMInformationDlg::composeArticle (const QString &aBelongsTo, int aSpacesCount)
670{
671 QString body = "<tr><td></td><td width=50%><nobr>%1%2</nobr></td>"
672 "<td align=right><nobr>%3%4</nobr></td></tr>";
673 QString indent;
674 for (int i = 0; i < aSpacesCount; ++ i)
675 indent += "&nbsp;&nbsp;";
676 body = body.arg (indent);
677
678 QString result;
679
680 if (mLinksMap.contains (aBelongsTo))
681 {
682 QStringList keys = mLinksMap [aBelongsTo];
683 foreach (const QString &key, keys)
684 {
685 QString line (body);
686 if (mNamesMap.contains (key) && mValuesMap.contains (key) && mUnitsMap.contains (key))
687 {
688 line = line.arg (mNamesMap [key]).arg (QString ("%L1").arg (mValuesMap [key].toULongLong()));
689 line = mUnitsMap [key].contains (QRegExp ("\\[\\S+\\]")) ?
690 line.arg (QString ("<img src=:/tpixel.png width=%1 height=1>")
691 .arg (QApplication::fontMetrics().width (
692 QString (" %1").arg (mUnitsMap [key]
693 .mid (1, mUnitsMap [key].length() - 2))))) :
694 line.arg (QString (" %1").arg (mUnitsMap [key]));
695 result += line;
696 }
697 }
698 }
699 else
700 result = body.arg (aBelongsTo).arg (QString::null).arg (QString::null);
701
702 return result;
703}
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