Changeset 80381 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Aug 21, 2019 7:25:25 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132846
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 2 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r80379 r80381 736 736 src/runtime/information/UIInformationRuntime.h \ 737 737 src/runtime/information/UIInformationView.h \ 738 src/runtime/information/UIPerformanceMonitor.h \739 738 src/runtime/information/UIVMInformationDialog.h \ 740 739 src/guestctrl/UIFileManager.h \ … … 978 977 src/runtime/UIFrameBuffer.cpp \ 979 978 src/runtime/UIIndicatorsPool.cpp \ 980 src/runtime/information/UI PerformanceMonitor.cpp \979 src/runtime/information/UIInformationRuntime.cpp \ 981 980 src/guestctrl/UIFileManager.cpp \ 982 981 src/guestctrl/UIFileManagerLogPanel.cpp \ … … 1203 1202 src/runtime/information/UIInformationRuntime.cpp \ 1204 1203 src/runtime/information/UIInformationView.cpp \ 1205 src/runtime/information/UIPerformanceMonitor.cpp \1206 1204 src/runtime/information/UIVMInformationDialog.cpp \ 1207 1205 src/guestctrl/UIFileManager.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIInformationRuntime.cpp
r80379 r80381 18 18 /* Qt includes: */ 19 19 #include <QApplication> 20 #include <QTableWidget> 21 #include <QTextDocument> 22 #include <QVBoxLayout> 20 #include <QLabel> 21 #include <QPainter> 22 #include <QGridLayout> 23 #include <QStyle> 24 #include <QTimer> 23 25 24 26 /* GUI includes: */ 25 27 #include "UICommon.h" 26 28 #include "UIConverter.h" 27 #include "UI IconPool.h"29 #include "UIExtraDataManager.h" 28 30 #include "UIInformationRuntime.h" 29 #include "UIInformationDataItem.h" 30 #include "UIInformationItem.h" 31 #include "UIInformationView.h" 32 #include "UIExtraDataManager.h" 33 #include "UIInformationModel.h" 34 35 /* COM includes: */ 36 #include "CDisplay.h" 31 #include "UISession.h" 32 37 33 #include "CGuest.h" 38 #include "CMachineDebugger.h" 34 #include "CPerformanceCollector.h" 35 #include "CPerformanceMetric.h" 39 36 #include "CVRDEServerInfo.h" 40 37 41 UIInformationRuntime::UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console) 38 #define DATA_SERIES_SIZE 2 39 const ULONG iPeriod = 1; 40 const int iMaximumQueueSize = 120; 41 const int iMetricSetupCount = 1; 42 const int iDecimalCount = 2; 43 44 /********************************************************************************************************************************* 45 * UIChart definition. * 46 *********************************************************************************************************************************/ 47 48 class UIChart : public QWidget 49 { 50 51 Q_OBJECT; 52 53 public: 54 55 UIChart(QWidget *pParent, const UISubMetric *pSubMetric); 56 void setFontSize(int iFontSize); 57 int fontSize() const; 58 void setTextList(const QStringList &textList); 59 const QStringList &textList() const; 60 61 bool drawPieChart() const; 62 void setDrawPieChart(bool fDrawPieChart); 63 64 bool useGradientLineColor() const; 65 void setUseGradientLineColor(bool fUseGradintLineColor); 66 67 QColor dataSeriesColor(int iDataSeriesIndex); 68 void setDataSeriesColor(int iDataSeriesIndex, const QColor &color); 69 70 QString XAxisLabel(); 71 void setXAxisLabel(const QString &strLabel); 72 73 protected: 74 75 virtual void paintEvent(QPaintEvent *pEvent) /* override */; 76 virtual QSize minimumSizeHint() const /* override */; 77 virtual QSize sizeHint() const /* override */; 78 79 private: 80 81 virtual void computeFontSize(); 82 void drawXAxisLabels(QPainter &painter, int iXSubAxisCount); 83 void drawPieCharts(QPainter &painter, ULONG iMaximum); 84 85 const UISubMetric *m_pSubMetric; 86 QSize m_size; 87 QFont m_font; 88 int m_iMarginLeft; 89 int m_iMarginRight; 90 int m_iMarginTop; 91 int m_iMarginBottom; 92 QStringList m_textList; 93 int m_iPieChartSize; 94 QRect m_pieChartRect[DATA_SERIES_SIZE]; 95 bool m_fDrawPieChart; 96 bool m_fUseGradientLineColor; 97 QColor m_dataSeriesColor[DATA_SERIES_SIZE]; 98 QString m_strXAxisLabel; 99 }; 100 101 102 /********************************************************************************************************************************* 103 * UIChart implementation. * 104 *********************************************************************************************************************************/ 105 106 UIChart::UIChart(QWidget *pParent, const UISubMetric *pSubMetric) 107 :QWidget(pParent) 108 , m_pSubMetric(pSubMetric) 109 , m_size(QSize(50, 50)) 110 , m_fDrawPieChart(true) 111 , m_fUseGradientLineColor(true) 112 { 113 m_dataSeriesColor[0] = QColor(Qt::red); 114 m_dataSeriesColor[1] = QColor(Qt::blue); 115 116 m_iMarginLeft = 1 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin); 117 m_iMarginRight = 6 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin); 118 m_iMarginTop = 0.3 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin); 119 m_iMarginBottom = 2 * qApp->QApplication::style()->pixelMetric(QStyle::PM_LayoutTopMargin); 120 m_iPieChartSize = 1.5f * qApp->style()->pixelMetric(QStyle::PM_LargeIconSize); 121 m_pieChartRect[0] = QRect(1.5 * m_iMarginLeft, 1.5 * m_iMarginTop, m_iPieChartSize, m_iPieChartSize); 122 m_pieChartRect[1] = QRect(m_pieChartRect[0].x() + m_iPieChartSize + 0.5 * m_iMarginLeft, 1.5 * m_iMarginTop, m_iPieChartSize, m_iPieChartSize); 123 m_size = QSize(6 * m_iPieChartSize, 2 * m_iPieChartSize); 124 } 125 126 void UIChart::setFontSize(int iFontSize) 127 { 128 m_font.setPixelSize(iFontSize); 129 } 130 131 int UIChart::fontSize() const 132 { 133 return m_font.pixelSize(); 134 } 135 136 void UIChart::setTextList(const QStringList &textList) 137 { 138 m_textList = textList; 139 computeFontSize(); 140 } 141 142 const QStringList &UIChart::textList() const 143 { 144 return m_textList; 145 } 146 147 bool UIChart::drawPieChart() const 148 { 149 return m_fDrawPieChart; 150 } 151 152 void UIChart::setDrawPieChart(bool fDrawPieChart) 153 { 154 if (m_fDrawPieChart == fDrawPieChart) 155 return; 156 m_fDrawPieChart = fDrawPieChart; 157 update(); 158 } 159 160 bool UIChart::useGradientLineColor() const 161 { 162 return m_fUseGradientLineColor; 163 } 164 165 void UIChart::setUseGradientLineColor(bool fUseGradintLineColor) 166 { 167 if (m_fUseGradientLineColor == fUseGradintLineColor) 168 return; 169 m_fUseGradientLineColor = fUseGradintLineColor; 170 update(); 171 } 172 173 174 QColor UIChart::dataSeriesColor(int iDataSeriesIndex) 175 { 176 if (iDataSeriesIndex >= DATA_SERIES_SIZE) 177 return QColor(); 178 return m_dataSeriesColor[iDataSeriesIndex]; 179 } 180 181 void UIChart::setDataSeriesColor(int iDataSeriesIndex, const QColor &color) 182 { 183 if (iDataSeriesIndex >= DATA_SERIES_SIZE) 184 return; 185 if (m_dataSeriesColor[iDataSeriesIndex] == color) 186 return; 187 m_dataSeriesColor[iDataSeriesIndex] = color; 188 update(); 189 } 190 191 QString UIChart::XAxisLabel() 192 { 193 return m_strXAxisLabel; 194 } 195 196 void UIChart::setXAxisLabel(const QString &strLabel) 197 { 198 m_strXAxisLabel = strLabel; 199 } 200 201 QSize UIChart::minimumSizeHint() const 202 { 203 return m_size; 204 } 205 206 QSize UIChart::sizeHint() const 207 { 208 return m_size; 209 } 210 211 void UIChart::computeFontSize() 212 { 213 int iFontSize = 24; 214 215 //const QString &strText = m_pSubMetric->name(); 216 foreach (const QString &strText, m_textList) 217 { 218 m_font.setPixelSize(iFontSize); 219 220 do{ 221 int iWidth = QFontMetrics(m_font).width(strText); 222 if (iWidth + m_iMarginLeft + m_iMarginRight > m_size.width()) 223 --iFontSize; 224 else 225 break; 226 m_font.setPixelSize(iFontSize); 227 }while(iFontSize > 1); 228 } 229 } 230 231 void UIChart::paintEvent(QPaintEvent *pEvent) 232 { 233 Q_UNUSED(pEvent); 234 QPainter painter(this); 235 painter.setRenderHint(QPainter::Antialiasing); 236 237 /* Draw a rectanglar grid over which we will draw the line graphs: */ 238 int iChartHeight = height() - (m_iMarginTop + m_iMarginBottom); 239 int iChartWidth = width() - (m_iMarginLeft + m_iMarginRight); 240 QColor mainAxisColor(120, 120, 120); 241 QColor subAxisColor(200, 200, 200); 242 /* Draw the main axes: */ 243 painter.setPen(mainAxisColor); 244 painter.drawRect(QRect(m_iMarginLeft, m_iMarginTop, iChartWidth, iChartHeight)); 245 246 /* draw Y subaxes: */ 247 painter.setPen(subAxisColor); 248 int iYSubAxisCount = 3; 249 for (int i = 0; i < iYSubAxisCount; ++i) 250 { 251 float fSubAxisY = m_iMarginTop + (i + 1) * iChartHeight / (float) (iYSubAxisCount + 1); 252 painter.drawLine(m_iMarginLeft, fSubAxisY, 253 width() - m_iMarginRight, fSubAxisY); 254 } 255 256 /* draw X subaxes: */ 257 int iXSubAxisCount = 5; 258 for (int i = 0; i < iXSubAxisCount; ++i) 259 { 260 float fSubAxisX = m_iMarginLeft + (i + 1) * iChartWidth / (float) (iXSubAxisCount + 1); 261 painter.drawLine(fSubAxisX, m_iMarginTop, fSubAxisX, height() - m_iMarginBottom); 262 } 263 264 QFontMetrics fontMetrics(painter.font()); 265 int iFontHeight = fontMetrics.height(); 266 267 /* Draw XAxis tick labels: */ 268 painter.setPen(mainAxisColor); 269 drawXAxisLabels(painter, iXSubAxisCount); 270 271 /* Draw a half-transparent rectangle over the whole widget to indicate the it is disabled: */ 272 if (!isEnabled()) 273 { 274 painter.setPen(Qt::NoPen); 275 painter.setBrush(QColor(60, 60, 60, 50)); 276 painter.drawRect(QRect(0, 0, width(), height())); 277 return; 278 } 279 280 if (!m_pSubMetric || iMaximumQueueSize <= 1) 281 return; 282 283 ULONG iMaximum = m_pSubMetric->maximum(); 284 if (iMaximum == 0) 285 return; 286 /* Draw the data lines: */ 287 float fBarWidth = iChartWidth / (float) (iMaximumQueueSize - 1); 288 float fH = iChartHeight / (float)iMaximum; 289 for (int k = 0; k < DATA_SERIES_SIZE; ++k) 290 { 291 if (m_fUseGradientLineColor) 292 { 293 QLinearGradient gradient(0, 0, 0, iChartHeight); 294 gradient.setColorAt(0, Qt::black); 295 gradient.setColorAt(1, m_dataSeriesColor[k]); 296 painter.setPen(QPen(gradient, 2.5)); 297 } 298 299 const QQueue<ULONG> *data = m_pSubMetric->data(k); 300 if (!m_fUseGradientLineColor) 301 painter.setPen(QPen(m_dataSeriesColor[k], 2.5)); 302 for (int i = 0; i < data->size() - 1; ++i) 303 { 304 int j = i + 1; 305 float fHeight = fH * data->at(i); 306 float fX = (width() - m_iMarginRight) - ((data->size() -i - 1) * fBarWidth); 307 float fHeight2 = fH * data->at(j); 308 float fX2 = (width() - m_iMarginRight) - ((data->size() -j - 1) * fBarWidth); 309 QLineF bar(fX, height() - (fHeight + m_iMarginBottom), fX2, height() - (fHeight2 + m_iMarginBottom)); 310 painter.drawLine(bar); 311 } 312 } 313 314 /* Draw YAxis tick labels: */ 315 painter.setPen(mainAxisColor); 316 for (int i = 0; i < iYSubAxisCount + 2; ++i) 317 { 318 int iTextY = 0.5 * iFontHeight + m_iMarginTop + i * iChartHeight / (float) (iYSubAxisCount + 1); 319 QString strValue; 320 ULONG iValue = (iYSubAxisCount + 1 - i) * (iMaximum / (float) (iYSubAxisCount + 1)); 321 if (m_pSubMetric->unit().compare("%", Qt::CaseInsensitive) == 0) 322 strValue = QString::number(iValue); 323 else if (m_pSubMetric->unit().compare("kb", Qt::CaseInsensitive) == 0) 324 strValue = uiCommon().formatSize(_1K * (quint64)iValue, iDecimalCount); 325 else if (m_pSubMetric->unit().compare("b", Qt::CaseInsensitive) == 0 || 326 m_pSubMetric->unit().compare("b/s", Qt::CaseInsensitive) == 0) 327 strValue = uiCommon().formatSize(iValue, iDecimalCount); 328 painter.drawText(width() - 0.9 * m_iMarginRight, iTextY, strValue); 329 } 330 331 if (m_fDrawPieChart) 332 drawPieCharts(painter, iMaximum); 333 } 334 335 void UIChart::drawXAxisLabels(QPainter &painter, int iXSubAxisCount) 336 { 337 QFontMetrics fontMetrics(painter.font()); 338 int iFontHeight = fontMetrics.height(); 339 int iChartWidth = width() - (m_iMarginLeft + m_iMarginRight); 340 int iTotalSeconds = iPeriod * iMaximumQueueSize; 341 for (int i = 0; i < iXSubAxisCount + 2; ++i) 342 { 343 int iTextX = m_iMarginLeft + i * iChartWidth / (float) (iXSubAxisCount + 1); 344 QString strCurentSec = QString::number(iTotalSeconds - i * iTotalSeconds / (float)(iXSubAxisCount + 1)); 345 int iTextWidth = fontMetrics.width(strCurentSec); 346 if (i == 0) 347 { 348 strCurentSec += " " + m_strXAxisLabel; 349 painter.drawText(iTextX, height() - m_iMarginBottom + iFontHeight, strCurentSec); 350 } 351 else 352 painter.drawText(iTextX - 0.5 * iTextWidth, height() - m_iMarginBottom + iFontHeight, strCurentSec); 353 } 354 } 355 356 void UIChart::drawPieCharts(QPainter &painter, ULONG iMaximum) 357 { 358 for (int i = 0; i < DATA_SERIES_SIZE; ++i) 359 { 360 /* Draw the pie chart for the 0th data series only: */ 361 const QQueue<ULONG> *data = m_pSubMetric->data(i); 362 if (!data || data->isEmpty()) 363 continue; 364 365 /* Draw a whole non-filled circle: */ 366 painter.setPen(QPen(Qt::gray, 1)); 367 painter.drawArc(m_pieChartRect[i], 0, 3600 * 16); 368 369 QPointF center(m_pieChartRect[i].center()); 370 QPainterPath fillPath; 371 fillPath.moveTo(center); 372 fillPath.arcTo(m_pieChartRect[i], 90/*startAngle*/, 373 -1 * 360 /*sweepLength*/); 374 375 /* First draw a white filled circle and that the arc for data: */ 376 painter.setPen(Qt::NoPen); 377 painter.setBrush(QColor(255, 255, 255, 175)); 378 painter.drawPath(fillPath); 379 380 /* Prepare the gradient for the pie chart: */ 381 QConicalGradient pieGradient; 382 pieGradient.setCenter(m_pieChartRect[i].center()); 383 pieGradient.setAngle(90); 384 pieGradient.setColorAt(0, Qt::black); 385 pieGradient.setColorAt(1, m_dataSeriesColor[i]); 386 387 QPainterPath dataPath; 388 dataPath.moveTo(center); 389 float fAngle = 360.f * data->back() / (float)iMaximum; 390 dataPath.arcTo(m_pieChartRect[i], 90/*startAngle*/, 391 -1 * fAngle /*sweepLength*/); 392 painter.setBrush(pieGradient); 393 painter.drawPath(dataPath); 394 395 } 396 } 397 398 /********************************************************************************************************************************* 399 * UISubMetric implementation. * 400 *********************************************************************************************************************************/ 401 402 UISubMetric::UISubMetric(const QString &strName, const QString &strUnit, int iMaximumQueueSize) 403 : m_strName(strName) 404 , m_strUnit(strUnit) 405 , m_iMaximum(0) 406 , m_iMaximumQueueSize(iMaximumQueueSize) 407 , m_fRequiresGuestAdditions(false) 408 { 409 } 410 411 UISubMetric::UISubMetric() 412 : m_iMaximumQueueSize(0) 413 { 414 } 415 416 const QString &UISubMetric::name() const 417 { 418 return m_strName; 419 } 420 421 void UISubMetric::setMaximum(ULONG iMaximum) 422 { 423 m_iMaximum = iMaximum; 424 } 425 426 ULONG UISubMetric::maximum() const 427 { 428 return m_iMaximum; 429 } 430 431 void UISubMetric::setUnit(QString strUnit) 432 { 433 m_strUnit = strUnit; 434 435 } 436 const QString &UISubMetric::unit() const 437 { 438 return m_strUnit; 439 } 440 441 void UISubMetric::addData(int iDataSeriesIndex, ULONG fData) 442 { 443 if (iDataSeriesIndex >= DATA_SERIES_SIZE) 444 return; 445 m_data[iDataSeriesIndex].enqueue(fData); 446 if (m_data[iDataSeriesIndex].size() > iMaximumQueueSize) 447 m_data[iDataSeriesIndex].dequeue(); 448 } 449 450 const QQueue<ULONG> *UISubMetric::data(int iDataSeriesIndex) const 451 { 452 if (iDataSeriesIndex >= DATA_SERIES_SIZE) 453 return 0; 454 return &m_data[iDataSeriesIndex]; 455 } 456 457 bool UISubMetric::requiresGuestAdditions() const 458 { 459 return m_fRequiresGuestAdditions; 460 } 461 462 void UISubMetric::setRequiresGuestAdditions(bool fRequiresGAs) 463 { 464 m_fRequiresGuestAdditions = fRequiresGAs; 465 } 466 467 /********************************************************************************************************************************* 468 * UIInformationRuntime implementation. * 469 *********************************************************************************************************************************/ 470 471 UIInformationRuntime::UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console, const UISession *pSession) 42 472 : QIWithRetranslateUI<QWidget>(pParent) 473 , m_fGuestAdditionsAvailable(false) 43 474 , m_machine(machine) 44 475 , m_console(console) 45 { 476 , m_pMainLayout(0) 477 , m_pTimer(0) 478 , m_strCPUMetricName("CPU Load") 479 , m_strRAMMetricName("RAM Usage") 480 , m_strDiskMetricName("Disk Usage") 481 , m_strNetMetricName("Net") 482 { 483 if (!m_console.isNull()) 484 m_comGuest = m_console.GetGuest(); 485 m_fGuestAdditionsAvailable = guestAdditionsAvailable(6 /* minimum major version */); 486 487 connect(pSession, &UISession::sigAdditionsStateChange, this, &UIInformationRuntime::sltGuestAdditionsStateChange); 488 preparePerformaceCollector(); 489 prepareObjects(); 490 enableDisableGuestAdditionDependedWidgets(m_fGuestAdditionsAvailable); 46 491 retranslateUi(); 47 createTableItems(); 492 } 493 494 UIInformationRuntime::~UIInformationRuntime() 495 { 48 496 } 49 497 50 498 void UIInformationRuntime::retranslateUi() 51 499 { 52 m_strRuntimeTitle = QApplication::translate("UIVMInformationDialog", "Runtime Attributes"); 53 } 54 55 void UIInformationRuntime::createTableItems() 56 { 57 // if (!m_pTableWidget) 58 // return; 59 // QFontMetrics fontMetrics(m_pTableWidget->font()); 60 // QTextDocument textDocument; 61 // int iMaxColumn1Length = 0; 62 63 // insertTitleRow(m_strRuntimeTitle, UIIconPool::iconSet(":/state_running_16px.png"), fontMetrics); 64 65 66 // insertInfoRows(runTimeAttributes(), 67 // fontMetrics, textDocument, iMaxColumn1Length); 68 69 70 71 // m_pTableWidget->resizeColumnToContents(0); 72 // /* Resize the column 1 a bit larger than the max string if contains: */ 73 // m_pTableWidget->setColumnWidth(1, 1.5 * iMaxColumn1Length); 74 // m_pTableWidget->resizeColumnToContents(2); 500 foreach (UIChart *pChart, m_charts) 501 pChart->setXAxisLabel(QApplication::translate("UIVMInformationDialog", "Seconds")); 502 int iMaximum = 0; 503 m_strCPUInfoLabelTitle = QApplication::translate("UIVMInformationDialog", "CPU Load"); 504 iMaximum = qMax(iMaximum, m_strCPUInfoLabelTitle.length()); 505 506 m_strCPUInfoLabelGuest = QApplication::translate("UIVMInformationDialog", "Guest Load"); 507 iMaximum = qMax(iMaximum, m_strCPUInfoLabelGuest.length()); 508 m_strCPUInfoLabelVMM = QApplication::translate("UIVMInformationDialog", "VMM Load"); 509 iMaximum = qMax(iMaximum, m_strCPUInfoLabelVMM.length()); 510 511 m_strRAMInfoLabelTitle = QApplication::translate("UIVMInformationDialog", "RAM Usage"); 512 iMaximum = qMax(iMaximum, m_strRAMInfoLabelTitle.length()); 513 m_strRAMInfoLabelTotal = QApplication::translate("UIVMInformationDialog", "Total"); 514 iMaximum = qMax(iMaximum, m_strRAMInfoLabelTotal.length()); 515 m_strRAMInfoLabelFree = QApplication::translate("UIVMInformationDialog", "Free"); 516 iMaximum = qMax(iMaximum, m_strRAMInfoLabelFree.length()); 517 m_strRAMInfoLabelUsed = QApplication::translate("UIVMInformationDialog", "Used"); 518 iMaximum = qMax(iMaximum, m_strRAMInfoLabelUsed.length()); 519 m_strNetInfoLabelTitle = QApplication::translate("UIVMInformationDialog", "Network"); 520 iMaximum = qMax(iMaximum, m_strNetInfoLabelTitle.length()); 521 m_strNetInfoLabelReceived = QApplication::translate("UIVMInformationDialog", "Received"); 522 iMaximum = qMax(iMaximum, m_strNetInfoLabelReceived.length()); 523 m_strNetInfoLabelTransmitted = QApplication::translate("UIVMInformationDialog", "Transmitted"); 524 iMaximum = qMax(iMaximum, m_strNetInfoLabelTransmitted.length()); 525 m_strNetInfoLabelMaximum = QApplication::translate("UIVMInformationDialog", "Maximum"); 526 iMaximum = qMax(iMaximum, m_strNetInfoLabelMaximum.length()); 527 528 /* Compute the maximum label string length and set it as a fixed width to labels to prevent always changing widths: */ 529 /* Add m_iDecimalCount plus 3 characters for the number and 2 for unit string: */ 530 iMaximum += (iDecimalCount + 5); 531 if (!m_infoLabels.isEmpty()) 532 { 533 QLabel *pLabel = m_infoLabels.begin().value(); 534 if (pLabel) 535 { 536 QFontMetrics labelFontMetric(pLabel->font()); 537 int iWidth = iMaximum * labelFontMetric.width('x'); 538 foreach (QLabel *pInfoLabel, m_infoLabels) 539 pInfoLabel->setFixedWidth(iWidth); 540 } 541 } 542 543 } 544 545 void UIInformationRuntime::prepareObjects() 546 { 547 m_pMainLayout = new QGridLayout(this); 548 if (m_pMainLayout) 549 { 550 m_pMainLayout->setSpacing(10); 551 } 552 553 m_pTimer = new QTimer(this); 554 if (m_pTimer) 555 { 556 connect(m_pTimer, &QTimer::timeout, this, &UIInformationRuntime::sltTimeout); 557 m_pTimer->start(1000 * iPeriod); 558 } 559 560 QStringList chartOder; 561 chartOder << m_strCPUMetricName << m_strRAMMetricName << m_strDiskMetricName << m_strNetMetricName; 562 int iRow = 0; 563 foreach (const QString &strMetricName, chartOder) 564 { 565 if (!m_subMetrics.contains(strMetricName)) 566 continue; 567 QLabel *pLabel = new QLabel; 568 pLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); 569 m_pMainLayout->addWidget(pLabel, iRow, 0); 570 m_infoLabels.insert(strMetricName, pLabel); 571 572 UIChart *pChart = new UIChart(this, &(m_subMetrics[strMetricName])); 573 m_charts.insert(strMetricName, pChart); 574 pChart->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); 575 m_pMainLayout->addWidget(pChart, iRow, 1); 576 ++iRow; 577 } 578 579 /* Configure charts: */ 580 if (m_charts.contains(m_strNetMetricName) && m_charts[m_strNetMetricName]) 581 { 582 m_charts[m_strNetMetricName]->setDrawPieChart(false); 583 m_charts[m_strNetMetricName]->setUseGradientLineColor(false); 584 } 585 if (m_charts.contains(m_strCPUMetricName) && m_charts[m_strCPUMetricName]) 586 m_charts[m_strCPUMetricName]->setUseGradientLineColor(false); 587 if (m_charts.contains(m_strRAMMetricName) && m_charts[m_strRAMMetricName]) 588 m_charts[m_strRAMMetricName]->setUseGradientLineColor(false); 589 590 QWidget *bottomSpacerWidget = new QWidget(this); 591 bottomSpacerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); 592 bottomSpacerWidget->setVisible(true); 593 // QPalette pal = bottomSpacerWidget->palette(); 594 // pal.setColor(QPalette::Background, Qt::green); 595 // bottomSpacerWidget->setAutoFillBackground(true); 596 // bottomSpacerWidget->setPalette(pal); 597 598 m_pMainLayout->addWidget(bottomSpacerWidget, iRow, 0, 1, 2); 599 } 600 601 void UIInformationRuntime::sltTimeout() 602 { 603 604 if (m_performanceMonitor.isNull()) 605 return; 606 QVector<QString> allNames;// = new ArrayList<IUnknown>(); 607 QVector<CUnknown> allObjects;// = new ArrayList<IUnknown>(); 608 609 QVector<QString> aReturnNames; 610 QVector<CUnknown> aReturnObjects; 611 QVector<QString> aReturnUnits; 612 QVector<ULONG> aReturnScales; 613 QVector<ULONG> aReturnSequenceNumbers; 614 QVector<ULONG> aReturnDataIndices; 615 QVector<ULONG> aReturnDataLengths; 616 617 QVector<LONG> returnData = m_performanceMonitor.QueryMetricsData(m_nameList, 618 m_objectList, 619 aReturnNames, 620 aReturnObjects, 621 aReturnUnits, 622 aReturnScales, 623 aReturnSequenceNumbers, 624 aReturnDataIndices, 625 aReturnDataLengths); 626 quint64 iTotalRAM = 0; 627 quint64 iFreeRAM = 0; 628 ULONG iReceiveRate = 0; 629 ULONG iTransmitRate = 0; 630 631 for (int i = 0; i < aReturnNames.size(); ++i) 632 { 633 if (aReturnDataLengths[i] == 0) 634 continue; 635 /* Read the last of the return data disregarding the rest since we are caching the data in GUI side: */ 636 float fData = returnData[aReturnDataIndices[i] + aReturnDataLengths[i] - 1] / (float)aReturnScales[i]; 637 if (aReturnNames[i].contains("RAM", Qt::CaseInsensitive) && !aReturnNames[i].contains(":")) 638 { 639 if (aReturnNames[i].contains("Total", Qt::CaseInsensitive)) 640 iTotalRAM = (quint64)fData; 641 if (aReturnNames[i].contains("Free", Qt::CaseInsensitive)) 642 iFreeRAM = (quint64)fData; 643 } 644 else if (aReturnNames[i].contains("Net/Rate", Qt::CaseInsensitive) && !aReturnNames[i].contains(":")) 645 { 646 if (aReturnNames[i].contains("Rx", Qt::CaseInsensitive)) 647 iReceiveRate = fData; 648 if (aReturnNames[i].contains("Tx", Qt::CaseInsensitive)) 649 iTransmitRate = fData; 650 } 651 } 652 653 (void)iReceiveRate; 654 (void)iTransmitRate; 655 /* Update the CPU load chart with values we get from IMachineDebugger::getCPULoad(..): */ 656 if (m_subMetrics.contains(m_strCPUMetricName)) 657 { 658 ULONG aPctExecuting; 659 ULONG aPctHalted; 660 ULONG aPctOther; 661 m_machineDebugger.GetCPULoad(0x7fffffff, aPctExecuting, aPctHalted, aPctOther); 662 updateCPUGraphsAndMetric(aPctExecuting, aPctOther); 663 } 664 665 if (m_subMetrics.contains(m_strRAMMetricName)) 666 updateRAMGraphsAndMetric(iTotalRAM, iFreeRAM); 667 if (m_subMetrics.contains(m_strNetMetricName)) 668 updateNewGraphsAndMetric(iReceiveRate, iTransmitRate); 669 670 } 671 672 void UIInformationRuntime::sltGuestAdditionsStateChange() 673 { 674 bool fGuestAdditionsAvailable = guestAdditionsAvailable(6 /* minimum major version */); 675 if (m_fGuestAdditionsAvailable == fGuestAdditionsAvailable) 676 return; 677 m_fGuestAdditionsAvailable = fGuestAdditionsAvailable; 678 enableDisableGuestAdditionDependedWidgets(m_fGuestAdditionsAvailable); 679 } 680 681 void UIInformationRuntime::preparePerformaceCollector() 682 { 683 m_performanceMonitor = uiCommon().virtualBox().GetPerformanceCollector(); 684 m_machineDebugger = m_console.GetDebugger(); 685 686 if (m_performanceMonitor.isNull()) 687 return; 688 689 // m_nameList << "Guest/RAM/Usage*"; 690 m_nameList << "Guest/RAM/Usage*"; 691 m_nameList << "Net/Rate*"; 692 693 694 m_objectList = QVector<CUnknown>(m_nameList.size(), CUnknown()); 695 m_performanceMonitor.SetupMetrics(m_nameList, m_objectList, iPeriod, iMetricSetupCount); 696 { 697 QVector<CPerformanceMetric> metrics = m_performanceMonitor.GetMetrics(m_nameList, m_objectList); 698 for (int i = 0; i < metrics.size(); ++i) 699 { 700 QString strName(metrics[i].GetMetricName()); 701 if (!strName.contains(':')) 702 { 703 if (strName.contains("RAM", Qt::CaseInsensitive) && strName.contains("Free", Qt::CaseInsensitive)) 704 { 705 UISubMetric newMetric(m_strRAMMetricName, metrics[i].GetUnit(), iMaximumQueueSize); 706 newMetric.setRequiresGuestAdditions(true); 707 m_subMetrics.insert(m_strRAMMetricName, newMetric); 708 } 709 else if (strName.contains("Net", Qt::CaseInsensitive)) 710 { 711 UISubMetric newMetric(m_strNetMetricName, metrics[i].GetUnit(), iMaximumQueueSize); 712 newMetric.setRequiresGuestAdditions(true); 713 m_subMetrics.insert(m_strNetMetricName, newMetric); 714 } 715 } 716 } 717 } 718 m_subMetrics.insert(m_strCPUMetricName, UISubMetric(m_strCPUMetricName, "%", iMaximumQueueSize)); 719 } 720 721 bool UIInformationRuntime::guestAdditionsAvailable(int iMinimumMajorVersion) 722 { 723 if (m_comGuest.isNull()) 724 return false; 725 bool fGuestAdditionsStatus = m_comGuest.GetAdditionsStatus(m_comGuest.GetAdditionsRunLevel()); 726 if (fGuestAdditionsStatus) 727 { 728 QStringList versionStrings = m_comGuest.GetAdditionsVersion().split('.', QString::SkipEmptyParts); 729 if (!versionStrings.isEmpty()) 730 { 731 bool fConvert = false; 732 int iMajorVersion = versionStrings[0].toInt(&fConvert); 733 if (fConvert && iMajorVersion >= iMinimumMajorVersion) 734 return true; 735 } 736 } 737 return false; 738 } 739 740 void UIInformationRuntime::enableDisableGuestAdditionDependedWidgets(bool fEnable) 741 { 742 for (QMap<QString, UISubMetric>::const_iterator iterator = m_subMetrics.begin(); 743 iterator != m_subMetrics.end(); ++iterator) 744 { 745 if (!iterator.value().requiresGuestAdditions()) 746 continue; 747 if (m_charts.contains(iterator.key()) && m_charts[iterator.key()]) 748 { 749 m_charts[iterator.key()]->setEnabled(fEnable); 750 m_charts[iterator.key()]->update(); 751 } 752 if (m_infoLabels.contains(iterator.key()) && m_infoLabels[iterator.key()]) 753 { 754 m_infoLabels[iterator.key()]->setEnabled(fEnable); 755 m_infoLabels[iterator.key()]->update(); 756 } 757 } 758 } 759 760 void UIInformationRuntime::updateCPUGraphsAndMetric(ULONG iExecutingPercentage, ULONG iOtherPercentage) 761 { 762 UISubMetric &CPUMetric = m_subMetrics[m_strCPUMetricName]; 763 CPUMetric.addData(0, iExecutingPercentage); 764 CPUMetric.addData(1, iOtherPercentage); 765 CPUMetric.setMaximum(100); 766 if (m_infoLabels.contains(m_strCPUMetricName) && m_infoLabels[m_strCPUMetricName]) 767 { 768 QString strInfo; 769 QString strReceiveColor; 770 if (m_infoLabels[m_strCPUMetricName]->isEnabled()) 771 strInfo = QString("<b>%1</b></b><br/><font color=\"%2\">%3: %4%5</font><br/><font color=\"%6\">%7: %8%9</font>") 772 .arg(m_strCPUInfoLabelTitle) 773 .arg(dataColorString(m_strCPUMetricName, 0)) 774 .arg(m_strCPUInfoLabelGuest).arg(QString::number(iExecutingPercentage)).arg(CPUMetric.unit()) 775 .arg(dataColorString(m_strCPUMetricName, 1)) 776 .arg(m_strCPUInfoLabelVMM).arg(QString::number(iOtherPercentage)).arg(CPUMetric.unit()); 777 else 778 strInfo = QString("<b>%1</b><br/>%2%3").arg(m_strCPUInfoLabelTitle).arg("--").arg("%"); 779 m_infoLabels[m_strCPUMetricName]->setText(strInfo); 780 } 781 782 if (m_charts.contains(m_strCPUMetricName)) 783 m_charts[m_strCPUMetricName]->update(); 784 } 785 786 void UIInformationRuntime::updateRAMGraphsAndMetric(quint64 iTotalRAM, quint64 iFreeRAM) 787 { 788 UISubMetric &RAMMetric = m_subMetrics[m_strRAMMetricName]; 789 RAMMetric.setMaximum(iTotalRAM); 790 RAMMetric.addData(0, iTotalRAM - iFreeRAM); 791 if (m_infoLabels.contains(m_strRAMMetricName) && m_infoLabels[m_strRAMMetricName]) 792 { 793 QString strInfo; 794 if (m_infoLabels[m_strRAMMetricName]->isEnabled()) 795 strInfo = QString("<b>%1</b><br/>%2: %3<br/>%4: %5<br/>%6: %7").arg(m_strRAMInfoLabelTitle).arg(m_strRAMInfoLabelTotal).arg(uiCommon().formatSize(_1K * iTotalRAM, iDecimalCount)) 796 .arg(m_strRAMInfoLabelFree).arg(uiCommon().formatSize(_1K * (iFreeRAM), iDecimalCount)) 797 .arg(m_strRAMInfoLabelUsed).arg(uiCommon().formatSize(_1K * (iTotalRAM - iFreeRAM), iDecimalCount)); 798 else 799 strInfo = QString("<b>%1</b><br/>%2: %3<br/>%4: %5<br/>%6: %7").arg(m_strRAMInfoLabelTitle).arg(m_strRAMInfoLabelTotal).arg("---").arg(m_strRAMInfoLabelFree).arg("---").arg(m_strRAMInfoLabelUsed).arg("---"); 800 m_infoLabels[m_strRAMMetricName]->setText(strInfo); 801 } 802 if (m_charts.contains(m_strRAMMetricName)) 803 m_charts[m_strRAMMetricName]->update(); 804 } 805 806 void UIInformationRuntime::updateNewGraphsAndMetric(ULONG iReceiveRate, ULONG iTransmitRate) 807 { 808 UISubMetric &NetMetric = m_subMetrics[m_strNetMetricName]; 809 810 NetMetric.addData(0, iReceiveRate); 811 NetMetric.addData(1, iTransmitRate); 812 813 ULONG iMaximum = qMax(NetMetric.maximum(), (ULONG)qMax(iReceiveRate, iTransmitRate)); 814 NetMetric.setMaximum(iMaximum); 815 816 if (m_infoLabels.contains(m_strNetMetricName) && m_infoLabels[m_strNetMetricName]) 817 { 818 QString strInfo; 819 QString strReceiveColor; 820 if (m_infoLabels[m_strNetMetricName]->isEnabled()) 821 strInfo = QString("<b>%1</b></b><br/><font color=\"%2\">%3: %4</font><br/><font color=\"%5\">%6: %7</font><br/>%8: %9") 822 .arg(m_strNetInfoLabelTitle) 823 .arg(dataColorString(m_strNetMetricName, 0)) 824 .arg(m_strNetInfoLabelReceived).arg(uiCommon().formatSize((quint64)iReceiveRate, iDecimalCount)) 825 .arg(dataColorString(m_strNetMetricName, 1)) 826 .arg(m_strNetInfoLabelTransmitted).arg(uiCommon().formatSize((quint64)iTransmitRate, iDecimalCount)) 827 .arg(m_strNetInfoLabelMaximum).arg(uiCommon().formatSize((quint64)iMaximum, iDecimalCount)); 828 else 829 strInfo = QString("<b>%1</b><br/>%2: %3<br/>%4: %5<br/>%6: %7").arg(m_strNetInfoLabelTitle).arg(m_strNetInfoLabelReceived).arg("---").arg(m_strNetInfoLabelTransmitted).arg("---"); 830 m_infoLabels[m_strNetMetricName]->setText(strInfo); 831 } 832 if (m_charts.contains(m_strNetMetricName)) 833 m_charts[m_strNetMetricName]->update(); 834 835 } 836 837 QString UIInformationRuntime::dataColorString(const QString &strChartName, int iDataIndex) 838 { 839 if (!m_charts.contains(strChartName)) 840 return QColor(Qt::red).name(QColor::HexRgb); 841 UIChart *pChart = m_charts[strChartName]; 842 if (!pChart) 843 return QColor(Qt::red).name(QColor::HexRgb); 844 return pChart->dataSeriesColor(iDataIndex).name(QColor::HexRgb); 75 845 } 76 846 … … 214 984 return textTable; 215 985 } 986 987 #include "UIInformationRuntime.moc" -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIInformationRuntime.h
r80379 r80381 24 24 /* Qt includes: */ 25 25 #include <QWidget> 26 #include <QMap> 27 #include <QQueue> 28 26 29 27 30 /* COM includes: */ 28 31 #include "COMEnums.h" 32 #include "CConsole.h" 33 #include "CGuest.h" 29 34 #include "CMachine.h" 30 #include "CConsole.h" 35 #include "CMachineDebugger.h" 36 #include "CPerformanceCollector.h" 31 37 32 38 /* GUI includes: */ … … 35 41 36 42 /* Forward declarations: */ 37 class QVBoxLayout; 38 class UIInformationView; 39 class UIInformationModel; 40 class UIVMItem; 43 class QTimer; 44 class QGridLayout; 45 class QLabel; 46 class UIChart; 47 class UISession; 41 48 49 class UISubMetric 50 { 51 public: 42 52 53 UISubMetric(const QString &strName, const QString &strUnit, int iMaximumQueueSize); 54 UISubMetric(); 55 const QString &name() const; 56 57 void setMaximum(ULONG iMaximum); 58 ULONG maximum() const; 59 60 void setUnit(QString strUnit); 61 const QString &unit() const; 62 63 void addData(int iDataSeriesIndex, ULONG fData); 64 const QQueue<ULONG> *data(int iDataSeriesIndex) const; 65 66 bool requiresGuestAdditions() const; 67 void setRequiresGuestAdditions(bool fRequiresGAs); 68 69 private: 70 71 QString m_strName; 72 QString m_strUnit; 73 ULONG m_iMaximum; 74 QQueue<ULONG> m_data[2]; 75 int m_iMaximumQueueSize; 76 bool m_fRequiresGuestAdditions; 77 }; 78 79 /** UIInformationRuntime class displays some high level performance metric of the guest system. 80 * The values are read in certain periods and cached in the GUI side. Currently we draw some line charts 81 * and pie charts (where applicable) alongside with some text. */ 43 82 class UIInformationRuntime : public QIWithRetranslateUI<QWidget> 44 83 { … … 47 86 public: 48 87 49 UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console); 88 /** Constructs information-tab passing @a pParent to the QWidget base-class constructor. 89 * @param machine is machine reference. 90 * @param console is machine console reference. */ 91 UIInformationRuntime(QWidget *pParent, const CMachine &machine, const CConsole &console, const UISession *pSession); 92 ~UIInformationRuntime(); 50 93 51 94 protected: 95 void retranslateUi(); 52 96 53 void retranslateUi() /* override */; 54 void createTableItems() /* override */; 97 private slots: 98 99 void sltTimeout(); 100 void sltGuestAdditionsStateChange(); 55 101 56 102 private: 103 104 /** Prepares layout. */ 105 void prepareObjects(); 106 void preparePerformaceCollector(); 107 bool guestAdditionsAvailable(int iMinimumMajorVersion); 108 void enableDisableGuestAdditionDependedWidgets(bool fEnable); 109 void updateCPUGraphsAndMetric(ULONG iLoadPercentage, ULONG iOtherPercentage); 110 void updateRAMGraphsAndMetric(quint64 iTotalRAM, quint64 iFreeRAM); 111 void updateNewGraphsAndMetric(ULONG iReceiveRate, ULONG iTransmitRate); 112 QString dataColorString(const QString &strChartName, int iDataIndex); 57 113 UITextTable runTimeAttributes(); 58 114 115 bool m_fGuestAdditionsAvailable; 116 /** Holds the machine instance. */ 59 117 CMachine m_machine; 118 /** Holds the console instance. */ 60 119 CConsole m_console; 120 CGuest m_comGuest; 121 122 CPerformanceCollector m_performanceMonitor; 123 CMachineDebugger m_machineDebugger; 124 /** Holds the instance of layout we create. */ 125 QGridLayout *m_pMainLayout; 126 QTimer *m_pTimer; 127 128 QVector<QString> m_nameList; 129 QVector<CUnknown> m_objectList; 130 131 QMap<QString, UISubMetric> m_subMetrics; 132 QMap<QString,UIChart*> m_charts; 133 QMap<QString,QLabel*> m_infoLabels; 134 135 /** @name These metric names are used for map keys to identify metrics. 136 * @{ */ 137 QString m_strCPUMetricName; 138 QString m_strRAMMetricName; 139 QString m_strDiskMetricName; 140 QString m_strNetMetricName; 141 /** @} */ 61 142 62 143 /** @name Cached translated string. 63 * @{ */ 64 QString m_strRuntimeTitle; 144 * @{ */ 145 /** CPU info label strings. */ 146 QString m_strCPUInfoLabelTitle; 147 QString m_strCPUInfoLabelGuest; 148 QString m_strCPUInfoLabelVMM; 149 /** RAM usage info label strings. */ 150 QString m_strRAMInfoLabelTitle; 151 QString m_strRAMInfoLabelTotal; 152 QString m_strRAMInfoLabelFree; 153 QString m_strRAMInfoLabelUsed; 154 /** Net traffic info label strings. */ 155 QString m_strNetInfoLabelTitle; 156 QString m_strNetInfoLabelReceived; 157 QString m_strNetInfoLabelTransmitted; 158 QString m_strNetInfoLabelMaximum; 65 159 /** @} */ 160 66 161 67 162 }; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.cpp
r80369 r80381 36 36 #include "UIInformationConfiguration.h" 37 37 #include "UIInformationRuntime.h" 38 #include "UIPerformanceMonitor.h"39 38 #include "UIGuestProcessControlWidget.h" 40 39 #include "UIMachine.h" … … 239 238 /* Create Runtime Information tab: */ 240 239 UIInformationRuntime *pInformationRuntimeWidget = 241 new UIInformationRuntime(this, m_pMachineWindow->machine(), m_pMachineWindow->console() );240 new UIInformationRuntime(this, m_pMachineWindow->machine(), m_pMachineWindow->console(), m_pMachineWindow->uisession()); 242 241 if (pInformationRuntimeWidget) 243 242 { … … 260 259 m_tabs.insert(2, pGuestProcessControlWidget); 261 260 m_pTabWidget->addTab(m_tabs.value(2), QString()); 262 }263 264 UIPerformanceMonitor *pPerformanceMonitor =265 new UIPerformanceMonitor(this, m_pMachineWindow->machine(), m_pMachineWindow->console(), m_pMachineWindow->uisession());266 if (pPerformanceMonitor)267 {268 m_tabs.insert(3, pPerformanceMonitor);269 m_pTabWidget->addTab(m_tabs.value(3), QString());270 261 } 271 262
Note:
See TracChangeset
for help on using the changeset viewer.