VirtualBox

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

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

medium: rename default IDE/FD storage controller names to IDE Controller and Floppy Controller

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