VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/activity/overview/UIVMActivityOverviewWidget.cpp

Last change on this file was 106061, checked in by vboxsync, 2 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 51.5 KB
Line 
1/* $Id: UIVMActivityOverviewWidget.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIVMActivityOverviewWidget class implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QApplication>
30#include <QCheckBox>
31#include <QHeaderView>
32#include <QItemDelegate>
33#include <QLabel>
34#include <QMenuBar>
35#include <QPainter>
36#include <QPushButton>
37#include <QTimer>
38#include <QVBoxLayout>
39
40/* GUI includes: */
41#include "QIDialogButtonBox.h"
42#include "QIToolBar.h"
43#include "UIActionPoolManager.h"
44#include "UICloudEntityKey.h"
45#include "UICloudNetworkingStuff.h"
46#include "UICommon.h"
47#include "UIConverter.h"
48#include "UIExtraDataDefs.h"
49#include "UIExtraDataManager.h"
50#include "UIGlobalSession.h"
51#include "UIIconPool.h"
52#include "UILocalMachineStuff.h"
53#include "UIMessageCenter.h"
54#include "UITranslator.h"
55#include "UITranslationEventListener.h"
56#include "UIVirtualBoxEventHandler.h"
57#include "UIVirtualMachineItemCloud.h"
58#include "UIVMActivityMonitor.h"
59#include "UIVMActivityOverviewWidget.h"
60#include "UIVMActivityOverviewModelView.h"
61
62#ifdef VBOX_WS_MAC
63# include "UIWindowMenuManager.h"
64#endif /* VBOX_WS_MAC */
65
66/* COM includes: */
67#include "CCloudClient.h"
68#include "CConsole.h"
69#include "CMachine.h"
70#include "CMachineDebugger.h"
71#include "CPerformanceMetric.h"
72
73struct ResourceColumn
74{
75 QString m_strName;
76 bool m_fEnabled;
77};
78
79
80/** Draws a doughnut shaped chart for the passed data values and can have a text drawn in the center. */
81
82
83/*********************************************************************************************************************************
84* Class UIVMActivityOverviewDoughnutChart definition. *
85*********************************************************************************************************************************/
86
87class UIVMActivityOverviewDoughnutChart : public QWidget
88{
89
90 Q_OBJECT;
91
92public:
93
94 UIVMActivityOverviewDoughnutChart(QWidget *pParent = 0);
95 void updateData(quint64 iData0, quint64 iData1);
96 void setChartColors(const QColor &color0, const QColor &color1);
97 void setChartCenterString(const QString &strCenter);
98 void setDataMaximum(quint64 iMax);
99
100protected:
101
102 virtual void paintEvent(QPaintEvent *pEvent) RT_OVERRIDE;
103
104private:
105
106 quint64 m_iData0;
107 quint64 m_iData1;
108 quint64 m_iDataMaximum;
109 int m_iMargin;
110 QColor m_color0;
111 QColor m_color1;
112 /** If not empty this text is drawn at the center of the doughnut chart. */
113 QString m_strCenter;
114};
115
116
117/*********************************************************************************************************************************
118* Class UIVMActivityOverviewHostStatsWidget definition. *
119*********************************************************************************************************************************/
120/** A container QWidget to layout host stats. related widgets. */
121class UIVMActivityOverviewHostStatsWidget : public QWidget
122{
123
124 Q_OBJECT;
125
126public:
127
128 UIVMActivityOverviewHostStatsWidget(QWidget *pParent = 0);
129 void setHostStats(const UIVMActivityOverviewHostStats &hostStats);
130
131private slots:
132
133 void sltRetranslateUI();
134
135private:
136
137 void prepare();
138 void addVerticalLine(QHBoxLayout *pLayout);
139 void updateLabels();
140
141 UIVMActivityOverviewDoughnutChart *m_pHostCPUChart;
142 UIVMActivityOverviewDoughnutChart *m_pHostRAMChart;
143 UIVMActivityOverviewDoughnutChart *m_pHostFSChart;
144 QLabel *m_pCPUTitleLabel;
145 QLabel *m_pCPUUserLabel;
146 QLabel *m_pCPUKernelLabel;
147 QLabel *m_pCPUTotalLabel;
148 QLabel *m_pRAMTitleLabel;
149 QLabel *m_pRAMUsedLabel;
150 QLabel *m_pRAMFreeLabel;
151 QLabel *m_pRAMTotalLabel;
152 QLabel *m_pFSTitleLabel;
153 QLabel *m_pFSUsedLabel;
154 QLabel *m_pFSFreeLabel;
155 QLabel *m_pFSTotalLabel;
156 QColor m_CPUUserColor;
157 QColor m_CPUKernelColor;
158 QColor m_RAMFreeColor;
159 QColor m_RAMUsedColor;
160 UIVMActivityOverviewHostStats m_hostStats;
161};
162
163
164/*********************************************************************************************************************************
165 * Class UIVMActivityOverviewItem definition. *
166 *********************************************************************************************************************************/
167/** Each instance of UIVMActivityOverviewItem corresponds to a vm. they are owned my the model. */
168class UIVMActivityOverviewItem : public QObject
169{
170
171 Q_OBJECT;
172
173public:
174
175 UIVMActivityOverviewItem(QObject *pParent, const QUuid &uid, const QString &strVMName);
176
177 UIVMActivityOverviewItem();
178 virtual ~UIVMActivityOverviewItem();
179 bool operator==(const UIVMActivityOverviewItem& other) const;
180 int columnLength(int iColumnIndex) const;
181 const QUuid &machineId() const;
182
183 virtual QString machineStateString() const = 0;
184 virtual bool isRunning() const = 0;
185 virtual bool isCloudVM() const = 0;
186 virtual void setMachineState(int iState) = 0;
187
188 QString columnData(int iColumnIndex) const;
189
190 quint64 m_uTotalRAM;
191 quint64 m_uFreeRAM;
192 quint64 m_uUsedRAM;
193 float m_fRAMUsagePercentage;
194
195protected:
196
197 QUuid m_VMuid;
198 QString m_strVMName;
199
200 /** The strings of each column for the item. We update this during performance query
201 * instead of model's data function to know the string length earlier. */
202 QMap<int, QString> m_columnData;
203};
204
205Q_DECLARE_METATYPE(UIVMActivityOverviewItem);
206
207
208/*********************************************************************************************************************************
209* Class UIVMActivityOverviewItemLocal definition. *
210*********************************************************************************************************************************/
211/* A UIVMActivityOverviewItem derivation to show local vms in the table view: */
212class UIVMActivityOverviewItemLocal : public UIVMActivityOverviewItem
213{
214 Q_OBJECT;
215public:
216
217 UIVMActivityOverviewItemLocal(QObject *pParent, const QUuid &uid, const QString &strVMName);
218 UIVMActivityOverviewItemLocal();
219 ~UIVMActivityOverviewItemLocal();
220
221 bool isWithGuestAdditions();
222 void resetDebugger();
223 void updateColumnData();
224
225 virtual bool isRunning() const RT_OVERRIDE;
226 virtual bool isCloudVM() const RT_OVERRIDE;
227 virtual QString machineStateString() const RT_OVERRIDE;
228 virtual void setMachineState(int iState) RT_OVERRIDE;
229
230private:
231
232 CSession m_comSession;
233 CGuest m_comGuest;
234 KMachineState m_enmMachineState;
235 quint64 m_uVMExitTotal;
236 quint64 m_uDiskWriteTotal;
237 quint64 m_uDiskReadTotal;
238 quint64 m_uNetworkDownTotal;
239 quint64 m_uNetworkUpTotal;
240 CMachineDebugger m_comDebugger;
241};
242
243
244/*********************************************************************************************************************************
245* Class UIVMActivityOverviewItemCloud definition. *
246*********************************************************************************************************************************/
247/* A UIVMActivityOverviewItem derivation to show cloud vms in the table view: */
248class UIVMActivityOverviewItemCloud : public UIVMActivityOverviewItem
249{
250 Q_OBJECT;
251public:
252
253 UIVMActivityOverviewItemCloud(QObject *pParent, const QUuid &uid, const QString &strVMName, CCloudMachine &comCloudMachine);
254
255 UIVMActivityOverviewItemCloud();
256 ~UIVMActivityOverviewItemCloud();
257 void updateMachineState();
258 virtual bool isRunning() const RT_OVERRIDE;
259 virtual bool isCloudVM() const RT_OVERRIDE;
260 virtual QString machineStateString() const RT_OVERRIDE;
261 virtual void setMachineState(int iState) RT_OVERRIDE;
262
263protected:
264
265private slots:
266
267 void sltTimeout();
268 void sltMetricNameListingComplete(QVector<QString> metricNameList);
269 void sltMetricDataReceived(KMetricType enmMetricType,
270 const QVector<QString> &data, const QVector<QString> &timeStamps);
271private:
272
273 void getMetricList();
274 void resetColumData();
275
276 QTimer *m_pTimer;
277 CCloudMachine m_comCloudMachine;
278 KCloudMachineState m_enmMachineState;
279 QVector<KMetricType> m_availableMetricTypes;
280};
281
282
283/*********************************************************************************************************************************
284* UIVMActivityOverviewDelegate definition. *
285*********************************************************************************************************************************/
286/** A QItemDelegate child class to disable dashed lines drawn around selected cells in QTableViews */
287class UIVMActivityOverviewDelegate : public QItemDelegate
288{
289
290 Q_OBJECT;
291
292public:
293
294 UIVMActivityOverviewDelegate(QObject *pParent = 0)
295 : QItemDelegate(pParent){}
296
297protected:
298
299 virtual void drawFocus ( QPainter * /*painter*/, const QStyleOptionViewItem & /*option*/, const QRect & /*rect*/ ) const RT_OVERRIDE RT_FINAL {}
300};
301
302
303/*********************************************************************************************************************************
304* Class UIVMActivityOverviewDoughnutChart implementation. *
305*********************************************************************************************************************************/
306UIVMActivityOverviewDoughnutChart::UIVMActivityOverviewDoughnutChart(QWidget *pParent /* = 0 */)
307 :QWidget(pParent)
308 , m_iData0(0)
309 , m_iData1(0)
310 , m_iDataMaximum(0)
311 , m_iMargin(3)
312{
313}
314
315void UIVMActivityOverviewDoughnutChart::updateData(quint64 iData0, quint64 iData1)
316{
317 m_iData0 = iData0;
318 m_iData1 = iData1;
319 update();
320}
321
322void UIVMActivityOverviewDoughnutChart::setChartColors(const QColor &color0, const QColor &color1)
323{
324 m_color0 = color0;
325 m_color1 = color1;
326}
327
328void UIVMActivityOverviewDoughnutChart::setChartCenterString(const QString &strCenter)
329{
330 m_strCenter = strCenter;
331}
332
333void UIVMActivityOverviewDoughnutChart::setDataMaximum(quint64 iMax)
334{
335 m_iDataMaximum = iMax;
336}
337
338void UIVMActivityOverviewDoughnutChart::paintEvent(QPaintEvent *pEvent)
339{
340 QWidget::paintEvent(pEvent);
341
342 QPainter painter(this);
343 painter.setRenderHint(QPainter::Antialiasing);
344
345 int iFrameHeight = height()- 2 * m_iMargin;
346 QRectF outerRect = QRectF(QPoint(m_iMargin,m_iMargin), QSize(iFrameHeight, iFrameHeight));
347 QRectF innerRect = UIMonitorCommon::getScaledRect(outerRect, 0.6f, 0.6f);
348 UIMonitorCommon::drawCombinedDoughnutChart(m_iData0, m_color0,
349 m_iData1, m_color1,
350 painter, m_iDataMaximum,
351 outerRect, innerRect, 80);
352 if (!m_strCenter.isEmpty())
353 {
354 float mul = 1.f / 1.4f;
355 QRectF textRect = UIMonitorCommon::getScaledRect(innerRect, mul, mul);
356 painter.setPen(Qt::black);
357 painter.drawText(textRect, Qt::AlignCenter, m_strCenter);
358 }
359}
360
361
362/*********************************************************************************************************************************
363* Class UIVMActivityOverviewHostStatsWidget implementation. *
364*********************************************************************************************************************************/
365
366UIVMActivityOverviewHostStatsWidget::UIVMActivityOverviewHostStatsWidget(QWidget *pParent /* = 0 */)
367 : QWidget(pParent)
368 , m_pHostCPUChart(0)
369 , m_pHostRAMChart(0)
370 , m_pHostFSChart(0)
371 , m_pCPUTitleLabel(0)
372 , m_pCPUUserLabel(0)
373 , m_pCPUKernelLabel(0)
374 , m_pCPUTotalLabel(0)
375 , m_pRAMTitleLabel(0)
376 , m_pRAMUsedLabel(0)
377 , m_pRAMFreeLabel(0)
378 , m_pRAMTotalLabel(0)
379 , m_pFSTitleLabel(0)
380 , m_pFSUsedLabel(0)
381 , m_pFSFreeLabel(0)
382 , m_pFSTotalLabel(0)
383 , m_CPUUserColor(Qt::red)
384 , m_CPUKernelColor(Qt::blue)
385 , m_RAMFreeColor(Qt::blue)
386 , m_RAMUsedColor(Qt::red)
387{
388 prepare();
389 sltRetranslateUI();
390 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
391 this, &UIVMActivityOverviewHostStatsWidget::sltRetranslateUI);
392}
393
394void UIVMActivityOverviewHostStatsWidget::setHostStats(const UIVMActivityOverviewHostStats &hostStats)
395{
396 m_hostStats = hostStats;
397 if (m_pHostCPUChart)
398 {
399 m_pHostCPUChart->updateData(m_hostStats.m_iCPUUserLoad, m_hostStats.m_iCPUKernelLoad);
400 QString strCenter = QString("%1\nMHz").arg(m_hostStats.m_iCPUFreq);
401 m_pHostCPUChart->setChartCenterString(strCenter);
402 }
403 if (m_pHostRAMChart)
404 {
405 quint64 iUsedRAM = m_hostStats.m_iRAMTotal - m_hostStats.m_iRAMFree;
406 m_pHostRAMChart->updateData(iUsedRAM, m_hostStats.m_iRAMFree);
407 m_pHostRAMChart->setDataMaximum(m_hostStats.m_iRAMTotal);
408 if (m_hostStats.m_iRAMTotal != 0)
409 {
410 quint64 iUsedRamPer = 100 * (iUsedRAM / (float) m_hostStats.m_iRAMTotal);
411 QString strCenter = QString("%1%\n%2").arg(iUsedRamPer).arg(UIVMActivityOverviewWidget::tr("Used"));
412 m_pHostRAMChart->setChartCenterString(strCenter);
413 }
414 }
415 if (m_pHostFSChart)
416 {
417 quint64 iUsedFS = m_hostStats.m_iFSTotal - m_hostStats.m_iFSFree;
418 m_pHostFSChart->updateData(iUsedFS, m_hostStats.m_iFSFree);
419 m_pHostFSChart->setDataMaximum(m_hostStats.m_iFSTotal);
420 if (m_hostStats.m_iFSTotal != 0)
421 {
422 quint64 iUsedFSPer = 100 * (iUsedFS / (float) m_hostStats.m_iFSTotal);
423 QString strCenter = QString("%1%\n%2").arg(iUsedFSPer).arg(UIVMActivityOverviewWidget::tr("Used"));
424 m_pHostFSChart->setChartCenterString(strCenter);
425 }
426 }
427
428 updateLabels();
429}
430
431void UIVMActivityOverviewHostStatsWidget::sltRetranslateUI()
432{
433 updateLabels();
434}
435
436void UIVMActivityOverviewHostStatsWidget::addVerticalLine(QHBoxLayout *pLayout)
437{
438 QFrame *pLine = new QFrame;
439 pLine->setFrameShape(QFrame::VLine);
440 pLine->setFrameShadow(QFrame::Sunken);
441 pLayout->addWidget(pLine);
442}
443
444void UIVMActivityOverviewHostStatsWidget::prepare()
445{
446 QHBoxLayout *pMainLayout = new QHBoxLayout;
447 setLayout(pMainLayout);
448 int iMinimumSize = 3 * QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
449
450 /* CPU Stuff: */
451 {
452 /* Host CPU Labels: */
453 QHBoxLayout *pCPULayout = new QHBoxLayout;
454 QWidget *pCPULabelContainer = new QWidget;
455 pCPULabelContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
456 pCPULayout->addWidget(pCPULabelContainer);
457 QVBoxLayout *pCPULabelsLayout = new QVBoxLayout;
458 pCPULabelsLayout->setContentsMargins(0, 0, 0, 0);
459 pCPULabelContainer->setLayout(pCPULabelsLayout);
460 m_pCPUTitleLabel = new QLabel;
461 pCPULabelsLayout->addWidget(m_pCPUTitleLabel);
462 m_pCPUUserLabel = new QLabel;
463 pCPULabelsLayout->addWidget(m_pCPUUserLabel);
464 m_pCPUKernelLabel = new QLabel;
465 pCPULabelsLayout->addWidget(m_pCPUKernelLabel);
466 m_pCPUTotalLabel = new QLabel;
467 pCPULabelsLayout->addWidget(m_pCPUTotalLabel);
468 pCPULabelsLayout->setAlignment(Qt::AlignTop);
469 pCPULabelsLayout->setSpacing(0);
470
471 /* Host CPU chart widget: */
472 m_pHostCPUChart = new UIVMActivityOverviewDoughnutChart;
473 if (m_pHostCPUChart)
474 {
475 m_pHostCPUChart->setMinimumSize(iMinimumSize, iMinimumSize);
476 m_pHostCPUChart->setDataMaximum(100);
477 pCPULayout->addWidget(m_pHostCPUChart);
478 m_pHostCPUChart->setChartColors(m_CPUUserColor, m_CPUKernelColor);
479 }
480 pMainLayout->addLayout(pCPULayout);
481 }
482 addVerticalLine(pMainLayout);
483 /* RAM Stuff: */
484 {
485 QHBoxLayout *pRAMLayout = new QHBoxLayout;
486 QWidget *pRAMLabelContainer = new QWidget;
487 pRAMLabelContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
488
489 pRAMLayout->addWidget(pRAMLabelContainer);
490 QVBoxLayout *pRAMLabelsLayout = new QVBoxLayout;
491 pRAMLabelsLayout->setContentsMargins(0, 0, 0, 0);
492 pRAMLabelsLayout->setSpacing(0);
493 pRAMLabelContainer->setLayout(pRAMLabelsLayout);
494 m_pRAMTitleLabel = new QLabel;
495 pRAMLabelsLayout->addWidget(m_pRAMTitleLabel);
496 m_pRAMUsedLabel = new QLabel;
497 pRAMLabelsLayout->addWidget(m_pRAMUsedLabel);
498 m_pRAMFreeLabel = new QLabel;
499 pRAMLabelsLayout->addWidget(m_pRAMFreeLabel);
500 m_pRAMTotalLabel = new QLabel;
501 pRAMLabelsLayout->addWidget(m_pRAMTotalLabel);
502
503 m_pHostRAMChart = new UIVMActivityOverviewDoughnutChart;
504 if (m_pHostRAMChart)
505 {
506 m_pHostRAMChart->setMinimumSize(iMinimumSize, iMinimumSize);
507 pRAMLayout->addWidget(m_pHostRAMChart);
508 m_pHostRAMChart->setChartColors(m_RAMUsedColor, m_RAMFreeColor);
509 }
510 pMainLayout->addLayout(pRAMLayout);
511 }
512
513 addVerticalLine(pMainLayout);
514 /* FS Stuff: */
515 {
516 QHBoxLayout *pFSLayout = new QHBoxLayout;
517 QWidget *pFSLabelContainer = new QWidget;
518 pFSLayout->addWidget(pFSLabelContainer);
519 pFSLabelContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
520 QVBoxLayout *pFSLabelsLayout = new QVBoxLayout;
521 pFSLabelsLayout->setContentsMargins(0, 0, 0, 0);
522 pFSLabelsLayout->setSpacing(0);
523 pFSLabelContainer->setLayout(pFSLabelsLayout);
524 m_pFSTitleLabel = new QLabel;
525 pFSLabelsLayout->addWidget(m_pFSTitleLabel);
526 m_pFSUsedLabel = new QLabel;
527 pFSLabelsLayout->addWidget(m_pFSUsedLabel);
528 m_pFSFreeLabel = new QLabel;
529 pFSLabelsLayout->addWidget(m_pFSFreeLabel);
530 m_pFSTotalLabel = new QLabel;
531 pFSLabelsLayout->addWidget(m_pFSTotalLabel);
532
533 m_pHostFSChart = new UIVMActivityOverviewDoughnutChart;
534 if (m_pHostFSChart)
535 {
536 m_pHostFSChart->setMinimumSize(iMinimumSize, iMinimumSize);
537 pFSLayout->addWidget(m_pHostFSChart);
538 m_pHostFSChart->setChartColors(m_RAMUsedColor, m_RAMFreeColor);
539 }
540 pMainLayout->addLayout(pFSLayout);
541 }
542 pMainLayout->addStretch(2);
543}
544
545void UIVMActivityOverviewHostStatsWidget::updateLabels()
546{
547 if (m_pCPUTitleLabel)
548 m_pCPUTitleLabel->setText(QString("<b>%1</b>").arg(UIVMActivityOverviewWidget::tr("Host CPU Load")));
549 if (m_pCPUUserLabel)
550 {
551 QString strColor = QColor(m_CPUUserColor).name(QColor::HexRgb);
552 m_pCPUUserLabel->setText(QString("<font color=\"%1\">%2: %3%</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("User")).arg(QString::number(m_hostStats.m_iCPUUserLoad)));
553 }
554 if (m_pCPUKernelLabel)
555 {
556 QString strColor = QColor(m_CPUKernelColor).name(QColor::HexRgb);
557 m_pCPUKernelLabel->setText(QString("<font color=\"%1\">%2: %3%</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Kernel")).arg(QString::number(m_hostStats.m_iCPUKernelLoad)));
558 }
559 if (m_pCPUTotalLabel)
560 m_pCPUTotalLabel->setText(QString("%1: %2%").arg(UIVMActivityOverviewWidget::tr("Total")).arg(m_hostStats.m_iCPUUserLoad + m_hostStats.m_iCPUKernelLoad));
561 if (m_pRAMTitleLabel)
562 m_pRAMTitleLabel->setText(QString("<b>%1</b>").arg(UIVMActivityOverviewWidget::tr("Host RAM Usage")));
563 if (m_pRAMFreeLabel)
564 {
565 QString strRAM = UITranslator::formatSize(m_hostStats.m_iRAMFree);
566 QString strColor = QColor(m_RAMFreeColor).name(QColor::HexRgb);
567 m_pRAMFreeLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Free")).arg(strRAM));
568 }
569 if (m_pRAMUsedLabel)
570 {
571 QString strRAM = UITranslator::formatSize(m_hostStats.m_iRAMTotal - m_hostStats.m_iRAMFree);
572 QString strColor = QColor(m_RAMUsedColor).name(QColor::HexRgb);
573 m_pRAMUsedLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Used")).arg(strRAM));
574 }
575 if (m_pRAMTotalLabel)
576 {
577 QString strRAM = UITranslator::formatSize(m_hostStats.m_iRAMTotal);
578 m_pRAMTotalLabel->setText(QString("%1: %2").arg(UIVMActivityOverviewWidget::tr("Total")).arg(strRAM));
579 }
580 if (m_pFSTitleLabel)
581 m_pFSTitleLabel->setText(QString("<b>%1</b>").arg(UIVMActivityOverviewWidget::tr("Host File System")));
582 if (m_pFSFreeLabel)
583 {
584 QString strFS = UITranslator::formatSize(m_hostStats.m_iFSFree);
585 QString strColor = QColor(m_RAMFreeColor).name(QColor::HexRgb);
586 m_pFSFreeLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Free")).arg(strFS));
587 }
588 if (m_pFSUsedLabel)
589 {
590 QString strFS = UITranslator::formatSize(m_hostStats.m_iFSTotal - m_hostStats.m_iFSFree);
591 QString strColor = QColor(m_RAMUsedColor).name(QColor::HexRgb);
592 m_pFSUsedLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Used")).arg(strFS));
593 }
594 if (m_pFSTotalLabel)
595 {
596 QString strFS = UITranslator::formatSize(m_hostStats.m_iFSTotal);
597 m_pFSTotalLabel->setText(QString("%1: %2").arg(UIVMActivityOverviewWidget::tr("Total")).arg(strFS));
598 }
599}
600
601
602/*********************************************************************************************************************************
603* Class UIVMActivityOverviewItem implementation. *
604*********************************************************************************************************************************/
605UIVMActivityOverviewItem::UIVMActivityOverviewItem(QObject *pParent, const QUuid &uid, const QString &strVMName)
606 : QObject(pParent)
607 , m_uTotalRAM(0)
608 , m_uFreeRAM(0)
609 , m_uUsedRAM(0)
610 , m_fRAMUsagePercentage(0)
611 , m_VMuid(uid)
612 , m_strVMName(strVMName)
613{
614 m_columnData[VMActivityOverviewColumn_Name] = m_strVMName;
615}
616
617UIVMActivityOverviewItem::UIVMActivityOverviewItem()
618 : QObject()
619 , m_uTotalRAM(0)
620 , m_uFreeRAM(0)
621 , m_uUsedRAM(0)
622 , m_fRAMUsagePercentage(0)
623 , m_VMuid(QUuid())
624{
625}
626
627UIVMActivityOverviewItem::~UIVMActivityOverviewItem()
628{
629}
630
631bool UIVMActivityOverviewItem::operator==(const UIVMActivityOverviewItem& other) const
632{
633 if (m_VMuid == other.m_VMuid)
634 return true;
635 return false;
636}
637
638QString UIVMActivityOverviewItem::columnData(int iColumnIndex) const
639{
640 return m_columnData.value(iColumnIndex, QString());
641}
642
643int UIVMActivityOverviewItem::columnLength(int iColumnIndex) const
644{
645 return m_columnData.value(iColumnIndex, QString()).length();
646}
647
648const QUuid &UIVMActivityOverviewItem::machineId() const
649{
650 return m_VMuid;
651}
652
653
654/*********************************************************************************************************************************
655* Class UIVMActivityOverviewHostStats implementation. *
656*********************************************************************************************************************************/
657
658UIVMActivityOverviewHostStats::UIVMActivityOverviewHostStats()
659 : m_iCPUUserLoad(0)
660 , m_iCPUKernelLoad(0)
661 , m_iCPUFreq(0)
662 , m_iRAMTotal(0)
663 , m_iRAMFree(0)
664 , m_iFSTotal(0)
665 , m_iFSFree(0)
666{
667}
668
669
670/*********************************************************************************************************************************
671* Class UIVMActivityOverviewItemCloud implementation. *
672*********************************************************************************************************************************/
673
674UIVMActivityOverviewItemCloud::UIVMActivityOverviewItemCloud(QObject *pParent, const QUuid &uid, const QString &strVMName, CCloudMachine &comCloudMachine)
675 : UIVMActivityOverviewItem(pParent, uid, strVMName)
676 , m_comCloudMachine(comCloudMachine)
677{
678 updateMachineState();
679 m_pTimer = new QTimer(this);
680 if (m_pTimer)
681 {
682 connect(m_pTimer, &QTimer::timeout, this, &UIVMActivityOverviewItemCloud::sltTimeout);
683 m_pTimer->setInterval(60 * 1000);
684 }
685 resetColumData();
686}
687
688UIVMActivityOverviewItemCloud::UIVMActivityOverviewItemCloud()
689{
690}
691
692UIVMActivityOverviewItemCloud::~UIVMActivityOverviewItemCloud()
693{
694}
695
696void UIVMActivityOverviewItemCloud::updateMachineState()
697{
698 if (m_comCloudMachine.isOk())
699 setMachineState(m_comCloudMachine.GetState());
700}
701
702bool UIVMActivityOverviewItemCloud::isRunning() const
703{
704 return m_enmMachineState == KCloudMachineState_Running;
705}
706
707bool UIVMActivityOverviewItemCloud::isCloudVM() const
708{
709 return true;
710}
711
712QString UIVMActivityOverviewItemCloud::machineStateString() const
713{
714 if (!m_comCloudMachine.isOk())
715 return QString();
716 return gpConverter->toString(m_comCloudMachine.GetState());
717}
718
719void UIVMActivityOverviewItemCloud::sltTimeout()
720{
721 int iDataSize = 1;
722 foreach (const KMetricType &enmMetricType, m_availableMetricTypes)
723 {
724 UIProgressTaskReadCloudMachineMetricData *pTask = new UIProgressTaskReadCloudMachineMetricData(this, m_comCloudMachine,
725 enmMetricType, iDataSize);
726 connect(pTask, &UIProgressTaskReadCloudMachineMetricData::sigMetricDataReceived,
727 this, &UIVMActivityOverviewItemCloud::sltMetricDataReceived);
728 pTask->start();
729 }
730}
731
732void UIVMActivityOverviewItemCloud::sltMetricDataReceived(KMetricType enmMetricType,
733 const QVector<QString> &data, const QVector<QString> &timeStamps)
734{
735 Q_UNUSED(timeStamps);
736 if (data.isEmpty())
737 return;
738
739 if (data[0].toFloat() < 0)
740 return;
741
742 int iDecimalCount = 2;
743 QLocale locale;
744 if (enmMetricType == KMetricType_CpuUtilization)
745 {
746 //QString QLocale::toString(double i, char f = 'g', int prec = 6) const
747
748 // m_columnData[VMActivityOverviewColumn_CPUGuestLoad] =
749 // QString("%1%").arg(QString::number(data[0].toFloat(), 'f', iDecimalCount));
750
751 m_columnData[VMActivityOverviewColumn_CPUGuestLoad] =
752 QString("%1%").arg(locale.toString(data[0].toFloat(), 'f', iDecimalCount));
753}
754 else if (enmMetricType == KMetricType_MemoryUtilization)
755 {
756 if (m_uTotalRAM != 0)
757 {
758 quint64 uUsedRAM = (quint64)data[0].toFloat() * (m_uTotalRAM / 100.f);
759 m_columnData[VMActivityOverviewColumn_RAMUsedAndTotal] =
760 QString("%1/%2").arg(UITranslator::formatSize(_1K * uUsedRAM, iDecimalCount)).
761 arg(UITranslator::formatSize(_1K * m_uTotalRAM, iDecimalCount));
762 }
763 m_columnData[VMActivityOverviewColumn_RAMUsedPercentage] =
764 QString("%1%").arg(QString::number(data[0].toFloat(), 'f', iDecimalCount));
765 }
766 else if (enmMetricType == KMetricType_NetworksBytesOut)
767 m_columnData[VMActivityOverviewColumn_NetworkUpRate] =
768 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
769 else if (enmMetricType == KMetricType_NetworksBytesIn)
770 m_columnData[VMActivityOverviewColumn_NetworkDownRate] =
771 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
772 else if (enmMetricType == KMetricType_DiskBytesRead)
773 m_columnData[VMActivityOverviewColumn_DiskIOReadRate] =
774 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
775 else if (enmMetricType == KMetricType_DiskBytesWritten)
776 m_columnData[VMActivityOverviewColumn_DiskIOWriteRate] =
777 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
778
779 sender()->deleteLater();
780}
781
782void UIVMActivityOverviewItemCloud::setMachineState(int iState)
783{
784 if (iState <= KCloudMachineState_Invalid || iState >= KCloudMachineState_Max)
785 return;
786 KCloudMachineState enmState = static_cast<KCloudMachineState>(iState);
787 if (m_enmMachineState == enmState)
788 return;
789 m_enmMachineState = enmState;
790 if (isRunning())
791 {
792 getMetricList();
793 if (m_uTotalRAM == 0)
794 m_uTotalRAM = UIMonitorCommon::determineTotalRAMAmount(m_comCloudMachine);
795 }
796 else
797 {
798 if (m_pTimer)
799 m_pTimer->stop();
800 }
801}
802
803void UIVMActivityOverviewItemCloud::resetColumData()
804{
805 for (int i = (int) VMActivityOverviewColumn_CPUGuestLoad;
806 i < (int)VMActivityOverviewColumn_Max; ++i)
807 m_columnData[i] = UIVMActivityOverviewWidget::tr("N/A");
808}
809
810void UIVMActivityOverviewItemCloud::getMetricList()
811{
812 if (!isRunning())
813 return;
814 UIProgressTaskReadCloudMachineMetricList *pReadListProgressTask =
815 new UIProgressTaskReadCloudMachineMetricList(this, m_comCloudMachine);
816 AssertPtrReturnVoid(pReadListProgressTask);
817 connect(pReadListProgressTask, &UIProgressTaskReadCloudMachineMetricList::sigMetricListReceived,
818 this, &UIVMActivityOverviewItemCloud::sltMetricNameListingComplete);
819 pReadListProgressTask->start();
820}
821
822void UIVMActivityOverviewItemCloud::sltMetricNameListingComplete(QVector<QString> metricNameList)
823{
824 AssertReturnVoid(m_pTimer);
825 m_availableMetricTypes.clear();
826 foreach (const QString &strName, metricNameList)
827 m_availableMetricTypes << gpConverter->fromInternalString<KMetricType>(strName);
828
829 if (!m_availableMetricTypes.isEmpty())
830 {
831 /* Dont wait 60 secs: */
832 sltTimeout();
833 m_pTimer->start();
834 }
835 else
836 {
837 m_pTimer->stop();
838 resetColumData();
839 }
840
841 if (sender())
842 sender()->deleteLater();
843
844}
845
846
847/*********************************************************************************************************************************
848* Class UIVMActivityOverviewItemLocal implementation. *
849*********************************************************************************************************************************/
850UIVMActivityOverviewItemLocal::UIVMActivityOverviewItemLocal(QObject *pParent, const QUuid &uid, const QString &strVMName)
851 : UIVMActivityOverviewItem(pParent, uid, strVMName)
852 , m_enmMachineState(KMachineState_Null)
853 , m_uVMExitTotal(0)
854 , m_uDiskWriteTotal(0)
855 , m_uDiskReadTotal(0)
856 , m_uNetworkDownTotal(0)
857 , m_uNetworkUpTotal(0)
858{
859 if (m_enmMachineState == KMachineState_Running)
860 resetDebugger();
861}
862
863UIVMActivityOverviewItemLocal::UIVMActivityOverviewItemLocal()
864 : m_enmMachineState(KMachineState_Null)
865 , m_uVMExitTotal(0)
866 , m_uDiskWriteTotal(0)
867 , m_uDiskReadTotal(0)
868 , m_uNetworkDownTotal(0)
869 , m_uNetworkUpTotal(0)
870{
871}
872
873UIVMActivityOverviewItemLocal::~UIVMActivityOverviewItemLocal()
874{
875 if (!m_comSession.isNull())
876 m_comSession.UnlockMachine();
877}
878
879bool UIVMActivityOverviewItemLocal::isWithGuestAdditions()
880{
881 if (m_comGuest.isNull())
882 return false;
883 return m_comGuest.GetAdditionsStatus(m_comGuest.GetAdditionsRunLevel());
884}
885
886void UIVMActivityOverviewItemLocal::resetDebugger()
887{
888 m_comSession = openSession(m_VMuid, KLockType_Shared);
889 if (!m_comSession.isNull())
890 {
891 CConsole comConsole = m_comSession.GetConsole();
892 if (!comConsole.isNull())
893 {
894 m_comGuest = comConsole.GetGuest();
895 m_comDebugger = comConsole.GetDebugger();
896 }
897 }
898}
899
900bool UIVMActivityOverviewItemLocal::isRunning() const
901{
902 return m_enmMachineState == KMachineState_Running;
903}
904
905bool UIVMActivityOverviewItemLocal::isCloudVM() const
906{
907 return false;
908}
909
910void UIVMActivityOverviewItemLocal::setMachineState(int iState)
911{
912 if (iState <= KMachineState_Null || iState >= KMachineState_Max)
913 return;
914 KMachineState enmState = static_cast<KMachineState>(iState);
915 if (m_enmMachineState == enmState)
916 return;
917 m_enmMachineState = enmState;
918 if (m_enmMachineState == KMachineState_Running)
919 resetDebugger();
920}
921
922void UIVMActivityOverviewItemLocal::updateColumnData()
923{
924 AssertReturnVoid(m_comDebugger.isOk());
925
926 int iDecimalCount = 2;
927
928 /* CPU Load: */
929 ULONG aPctHalted;
930 ULONG uCPUGuestLoad;
931 ULONG uCPUVMMLoad;
932 m_comDebugger.GetCPULoad(0x7fffffff, uCPUGuestLoad, aPctHalted, uCPUVMMLoad);
933 m_columnData[VMActivityOverviewColumn_CPUGuestLoad] =
934 QString("%1%").arg(QString::number(uCPUGuestLoad));
935 m_columnData[VMActivityOverviewColumn_CPUVMMLoad] =
936 QString("%1%").arg(QString::number(uCPUVMMLoad));
937
938 /* RAM Utilization: */
939 if (isWithGuestAdditions())
940 m_columnData[VMActivityOverviewColumn_RAMUsedAndTotal] =
941 QString("%1/%2").arg(UITranslator::formatSize(_1K * m_uUsedRAM, iDecimalCount)).
942 arg(UITranslator::formatSize(_1K * m_uTotalRAM, iDecimalCount));
943 else
944 m_columnData[VMActivityOverviewColumn_RAMUsedAndTotal] = UIVMActivityOverviewWidget::tr("N/A");
945
946 /* RAM Utilization %: */
947 if (isWithGuestAdditions())
948 m_columnData[VMActivityOverviewColumn_RAMUsedPercentage] =
949 QString("%1%").arg(QString::number(m_fRAMUsagePercentage, 'f', 2));
950 else
951 m_columnData[VMActivityOverviewColumn_RAMUsedPercentage] = UIVMActivityOverviewWidget::tr("N/A");
952
953 /* Network rate: */
954 quint64 uPrevDownTotal = m_uNetworkDownTotal;
955 quint64 uPrevUpTotal = m_uNetworkUpTotal;
956 UIMonitorCommon::getNetworkLoad(m_comDebugger, m_uNetworkDownTotal, m_uNetworkUpTotal);
957 quint64 uNetworkDownRate = m_uNetworkDownTotal - uPrevDownTotal;
958 quint64 uNetworkUpRate = m_uNetworkUpTotal - uPrevUpTotal;
959 m_columnData[VMActivityOverviewColumn_NetworkUpRate] =
960 QString("%1").arg(UITranslator::formatSize(uNetworkUpRate, iDecimalCount));
961 m_columnData[VMActivityOverviewColumn_NetworkDownRate] =
962 QString("%1").arg(UITranslator::formatSize(uNetworkDownRate, iDecimalCount));
963 m_columnData[VMActivityOverviewColumn_NetworkUpTotal] =
964 QString("%1").arg(UITranslator::formatSize(m_uNetworkUpTotal, iDecimalCount));
965 m_columnData[VMActivityOverviewColumn_NetworkDownTotal] =
966 QString("%1").arg(UITranslator::formatSize(m_uNetworkDownTotal, iDecimalCount));
967
968
969 /* IO rate: */
970 quint64 uPrevWriteTotal = m_uDiskWriteTotal;
971 quint64 uPrevReadTotal = m_uDiskReadTotal;
972 UIMonitorCommon::getDiskLoad(m_comDebugger, m_uDiskWriteTotal, m_uDiskReadTotal);
973 quint64 uDiskWriteRate = m_uDiskWriteTotal - uPrevWriteTotal;
974 quint64 uDiskReadRate = m_uDiskReadTotal - uPrevReadTotal;
975 m_columnData[VMActivityOverviewColumn_DiskIOReadRate] =
976 QString("%1").arg(UITranslator::formatSize(uDiskReadRate, iDecimalCount));
977 m_columnData[VMActivityOverviewColumn_DiskIOWriteRate] =
978 QString("%1").arg(UITranslator::formatSize(uDiskWriteRate, iDecimalCount));
979 m_columnData[VMActivityOverviewColumn_DiskIOReadTotal] =
980 QString("%1").arg(UITranslator::formatSize(m_uDiskReadTotal, iDecimalCount));
981 m_columnData[VMActivityOverviewColumn_DiskIOWriteTotal] =
982 QString("%1").arg(UITranslator::formatSize(m_uDiskWriteTotal, iDecimalCount));
983
984 /* VM Exits: */
985 quint64 uPrevVMExitsTotal = m_uVMExitTotal;
986 UIMonitorCommon::getVMMExitCount(m_comDebugger, m_uVMExitTotal);
987 quint64 uVMExitRate = m_uVMExitTotal - uPrevVMExitsTotal;
988 m_columnData[VMActivityOverviewColumn_VMExits] =
989 QString("%1/%2").arg(UITranslator::addMetricSuffixToNumber(uVMExitRate)).
990 arg(UITranslator::addMetricSuffixToNumber(m_uVMExitTotal));
991}
992
993QString UIVMActivityOverviewItemLocal::machineStateString() const
994{
995 return gpConverter->toString(m_enmMachineState);
996}
997
998
999/*********************************************************************************************************************************
1000* Class UIVMActivityOverviewWidget implementation. *
1001*********************************************************************************************************************************/
1002
1003UIVMActivityOverviewWidget::UIVMActivityOverviewWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
1004 bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
1005 : QWidget(pParent)
1006 , m_enmEmbedding(enmEmbedding)
1007 , m_pActionPool(pActionPool)
1008 , m_fShowToolbar(fShowToolbar)
1009 , m_pToolBar(0)
1010 , m_pTableView(0)
1011 , m_pProxyModel(0)
1012 , m_pModel(0)
1013 , m_pColumnVisibilityToggleMenu(0)
1014 , m_pHostStatsWidget(0)
1015 , m_fIsCurrentTool(true)
1016 , m_iSortIndicatorWidth(0)
1017 , m_fShowNotRunningVMs(false)
1018 , m_fShowCloudVMs(true)
1019{
1020 prepare();
1021}
1022
1023QMenu *UIVMActivityOverviewWidget::menu() const
1024{
1025 return NULL;
1026}
1027
1028QMenu *UIVMActivityOverviewWidget::columnVisiblityToggleMenu() const
1029{
1030 return m_pColumnVisibilityToggleMenu;
1031}
1032
1033bool UIVMActivityOverviewWidget::isCurrentTool() const
1034{
1035 return m_fIsCurrentTool;
1036}
1037
1038void UIVMActivityOverviewWidget::setIsCurrentTool(bool fIsCurrentTool)
1039{
1040 m_fIsCurrentTool = fIsCurrentTool;
1041 if (m_pModel)
1042 m_pModel->setShouldUpdate(fIsCurrentTool);
1043}
1044
1045void UIVMActivityOverviewWidget::setCloudMachineItems(const QList<UIVirtualMachineItemCloud*> &cloudItems)
1046{
1047 if (m_pModel)
1048 m_pModel->setCloudMachineItems(cloudItems);
1049}
1050
1051void UIVMActivityOverviewWidget::sltRetranslateUI()
1052{
1053 m_pTableView->setWhatsThis(tr("Lists all currently active virtual machines."));
1054
1055 m_columnTitles[VMActivityOverviewColumn_Name] = UIVMActivityOverviewWidget::tr("VM Name");
1056 m_columnTitles[VMActivityOverviewColumn_CPUGuestLoad] = UIVMActivityOverviewWidget::tr("CPU Guest");
1057 m_columnTitles[VMActivityOverviewColumn_CPUVMMLoad] = UIVMActivityOverviewWidget::tr("CPU VMM");
1058 m_columnTitles[VMActivityOverviewColumn_RAMUsedAndTotal] = UIVMActivityOverviewWidget::tr("RAM Used/Total");
1059 m_columnTitles[VMActivityOverviewColumn_RAMUsedPercentage] = UIVMActivityOverviewWidget::tr("RAM %");
1060 m_columnTitles[VMActivityOverviewColumn_NetworkUpRate] = UIVMActivityOverviewWidget::tr("Network Up Rate");
1061 m_columnTitles[VMActivityOverviewColumn_NetworkDownRate] = UIVMActivityOverviewWidget::tr("Network Down Rate");
1062 m_columnTitles[VMActivityOverviewColumn_NetworkUpTotal] = UIVMActivityOverviewWidget::tr("Network Up Total");
1063 m_columnTitles[VMActivityOverviewColumn_NetworkDownTotal] = UIVMActivityOverviewWidget::tr("Network Down Total");
1064 m_columnTitles[VMActivityOverviewColumn_DiskIOReadRate] = UIVMActivityOverviewWidget::tr("Disk Read Rate");
1065 m_columnTitles[VMActivityOverviewColumn_DiskIOWriteRate] = UIVMActivityOverviewWidget::tr("Disk Write Rate");
1066 m_columnTitles[VMActivityOverviewColumn_DiskIOReadTotal] = UIVMActivityOverviewWidget::tr("Disk Read Total");
1067 m_columnTitles[VMActivityOverviewColumn_DiskIOWriteTotal] = UIVMActivityOverviewWidget::tr("Disk Write Total");
1068 m_columnTitles[VMActivityOverviewColumn_VMExits] = UIVMActivityOverviewWidget::tr("VM Exits");
1069
1070 updateColumnsMenu();
1071
1072 if (m_pModel)
1073 m_pModel->setColumnCaptions(m_columnTitles);
1074
1075 computeMinimumColumnWidths();
1076}
1077
1078void UIVMActivityOverviewWidget::showEvent(QShowEvent *pEvent)
1079{
1080 if (m_pVMActivityMonitorAction && m_pTableView)
1081 m_pVMActivityMonitorAction->setEnabled(m_pTableView->hasSelection());
1082
1083 QWidget::showEvent(pEvent);
1084}
1085
1086void UIVMActivityOverviewWidget::prepare()
1087{
1088 /* Try to guest the sort indicator's width: */
1089 int iIndicatorMargin = 3;
1090 QIcon sortIndicator = qApp->QApplication::style()->standardIcon(QStyle::SP_TitleBarUnshadeButton);
1091 QList<QSize> iconSizes = sortIndicator.availableSizes();
1092 foreach(const QSize &msize, iconSizes)
1093 m_iSortIndicatorWidth = qMax(m_iSortIndicatorWidth, msize.width());
1094 if (m_iSortIndicatorWidth == 0)
1095 m_iSortIndicatorWidth = 20;
1096 m_iSortIndicatorWidth += 2 * iIndicatorMargin;
1097
1098 prepareWidgets();
1099 loadSettings();
1100 prepareActions();
1101 sltRetranslateUI();
1102 updateModelColumVisibilityCache();
1103 uiCommon().setHelpKeyword(this, "vm-activity-overview");
1104 connect(&uiCommon(), &UICommon::sigAskToCommitData,
1105 this, &UIVMActivityOverviewWidget::sltSaveSettings);
1106 connect(&uiCommon(), &UICommon::sigAskToDetachCOM,
1107 this, &UIVMActivityOverviewWidget::sltClearCOMData);
1108 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
1109 this, &UIVMActivityOverviewWidget::sltRetranslateUI);
1110 sltCloudVMVisibility(m_fShowCloudVMs);
1111}
1112
1113void UIVMActivityOverviewWidget::prepareWidgets()
1114{
1115 /* Create main-layout: */
1116 new QVBoxLayout(this);
1117 if (!layout())
1118 return;
1119 /* Configure layout: */
1120 layout()->setContentsMargins(0, 0, 0, 0);
1121#ifdef VBOX_WS_MAC
1122 layout()->setSpacing(10);
1123#else
1124 layout()->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
1125#endif
1126
1127 if (m_fShowToolbar)
1128 prepareToolBar();
1129
1130 m_pHostStatsWidget = new UIVMActivityOverviewHostStatsWidget;
1131 if (m_pHostStatsWidget)
1132 layout()->addWidget(m_pHostStatsWidget);
1133
1134 m_pProxyModel = new UIVMActivityOverviewProxyModel(this);
1135 m_pTableView = new UIVMActivityOverviewTableView(this);
1136 m_pModel = new UIVMActivityOverviewModel(this, m_pTableView);
1137 m_pProxyModel->setSourceModel(m_pModel);
1138 m_pProxyModel->setNotRunningVMVisibility(m_fShowNotRunningVMs);
1139 m_pProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
1140 m_pTableView->setModel(m_pProxyModel);
1141
1142 m_pTableView->setItemDelegate(new UIVMActivityOverviewDelegate(this));
1143 m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
1144 m_pTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
1145 m_pTableView->setShowGrid(false);
1146 m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
1147 m_pTableView->horizontalHeader()->setHighlightSections(false);
1148 m_pTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
1149 m_pTableView->verticalHeader()->setVisible(false);
1150 m_pTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
1151 /* Minimize the row height: */
1152 m_pTableView->verticalHeader()->setDefaultSectionSize(m_pTableView->verticalHeader()->minimumSectionSize());
1153 m_pTableView->setAlternatingRowColors(true);
1154 m_pTableView->setSortingEnabled(true);
1155 m_pTableView->sortByColumn(0, Qt::AscendingOrder);
1156
1157 connect(m_pTableView, &UIVMActivityOverviewTableView::customContextMenuRequested,
1158 this, &UIVMActivityOverviewWidget::sltHandleTableContextMenuRequest);
1159 connect(m_pTableView, &UIVMActivityOverviewTableView::sigSelectionChanged,
1160 this, &UIVMActivityOverviewWidget::sltHandleTableSelectionChanged);
1161 connect(m_pModel, &UIVMActivityOverviewModel::sigDataUpdate,
1162 this, &UIVMActivityOverviewWidget::sltHandleDataUpdate);
1163 connect(m_pModel, &UIVMActivityOverviewModel::sigHostStatsUpdate,
1164 this, &UIVMActivityOverviewWidget::sltHandleHostStatsUpdate);
1165
1166 updateModelColumVisibilityCache();
1167 layout()->addWidget(m_pTableView);
1168}
1169
1170void UIVMActivityOverviewWidget::updateColumnsMenu()
1171{
1172 UIMenu *pMenu = m_pActionPool->action(UIActionIndexMN_M_VMActivityOverview_M_Columns)->menu();
1173 if (!pMenu)
1174 return;
1175 pMenu->clear();
1176 for (int i = 0; i < VMActivityOverviewColumn_Max; ++i)
1177 {
1178 QAction *pAction = pMenu->addAction(m_columnTitles[i]);
1179 pAction->setCheckable(true);
1180 if (i == (int)VMActivityOverviewColumn_Name)
1181 pAction->setEnabled(false);
1182 pAction->setData(i);
1183 pAction->setChecked(columnVisible(i));
1184 connect(pAction, &QAction::toggled, this, &UIVMActivityOverviewWidget::sltHandleColumnAction);
1185 }
1186}
1187
1188void UIVMActivityOverviewWidget::prepareActions()
1189{
1190 updateColumnsMenu();
1191 m_pVMActivityMonitorAction =
1192 m_pActionPool->action(UIActionIndexMN_M_VMActivityOverview_S_SwitchToMachineActivity);
1193
1194 if (m_pVMActivityMonitorAction)
1195 connect(m_pVMActivityMonitorAction, &QAction::triggered, this, &UIVMActivityOverviewWidget::sltHandleShowVMActivityMonitor);
1196}
1197
1198void UIVMActivityOverviewWidget::prepareToolBar()
1199{
1200 /* Create toolbar: */
1201 m_pToolBar = new QIToolBar(parentWidget());
1202 AssertPtrReturnVoid(m_pToolBar);
1203 {
1204 /* Configure toolbar: */
1205 const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
1206 m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
1207 m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
1208
1209#ifdef VBOX_WS_MAC
1210 /* Check whether we are embedded into a stack: */
1211 if (m_enmEmbedding == EmbedTo_Stack)
1212 {
1213 /* Add into layout: */
1214 layout()->addWidget(m_pToolBar);
1215 }
1216#else
1217 /* Add into layout: */
1218 layout()->addWidget(m_pToolBar);
1219#endif
1220 }
1221}
1222
1223void UIVMActivityOverviewWidget::loadSettings()
1224{
1225 /* Load the list of hidden columns: */
1226 QStringList hiddenColumnList = gEDataManager->VMActivityOverviewHiddenColumnList();
1227 for (int i = (int)VMActivityOverviewColumn_Name; i < (int)VMActivityOverviewColumn_Max; ++i)
1228 m_columnVisible[i] = true;
1229 foreach(const QString& strColumn, hiddenColumnList)
1230 setColumnVisible((int)gpConverter->fromInternalString<VMActivityOverviewColumn>(strColumn), false);
1231 /* Load other options: */
1232 sltNotRunningVMVisibility(gEDataManager->VMActivityOverviewShowAllMachines());
1233}
1234
1235void UIVMActivityOverviewWidget::sltSaveSettings()
1236{
1237 /* Save the list of hidden columns: */
1238 QStringList hiddenColumnList;
1239 for (int i = 0; i < m_columnVisible.size(); ++i)
1240 {
1241 if (!columnVisible(i))
1242 hiddenColumnList << gpConverter->toInternalString((VMActivityOverviewColumn) i);
1243 }
1244 gEDataManager->setVMActivityOverviewHiddenColumnList(hiddenColumnList);
1245 gEDataManager->setVMActivityOverviewShowAllMachines(m_fShowNotRunningVMs);
1246}
1247
1248void UIVMActivityOverviewWidget::sltClearCOMData()
1249{
1250 if (m_pModel)
1251 m_pModel->clearData();
1252}
1253
1254void UIVMActivityOverviewWidget::sltToggleColumnSelectionMenu(bool fChecked)
1255{
1256 (void)fChecked;
1257 if (!m_pColumnVisibilityToggleMenu)
1258 return;
1259 m_pColumnVisibilityToggleMenu->exec(this->mapToGlobal(QPoint(0,0)));
1260}
1261
1262void UIVMActivityOverviewWidget::sltHandleColumnAction(bool fChecked)
1263{
1264 QAction* pSender = qobject_cast<QAction*>(sender());
1265 if (!pSender)
1266 return;
1267 setColumnVisible(pSender->data().toInt(), fChecked);
1268}
1269
1270void UIVMActivityOverviewWidget::sltHandleHostStatsUpdate(const UIVMActivityOverviewHostStats &stats)
1271{
1272 if (m_pHostStatsWidget)
1273 m_pHostStatsWidget->setHostStats(stats);
1274}
1275
1276void UIVMActivityOverviewWidget::sltHandleDataUpdate()
1277{
1278 computeMinimumColumnWidths();
1279 if (m_pProxyModel)
1280 m_pProxyModel->dataUpdate();
1281}
1282
1283void UIVMActivityOverviewWidget::sltHandleTableContextMenuRequest(const QPoint &pos)
1284{
1285 if (!m_pTableView)
1286 return;
1287
1288 QMenu menu;
1289 if (m_pVMActivityMonitorAction)
1290 menu.addAction(m_pVMActivityMonitorAction);
1291 menu.addSeparator();
1292
1293 QAction *pHideNotRunningAction =
1294 menu.addAction(UIVMActivityOverviewWidget::tr("List All Virtual Machines"));
1295 pHideNotRunningAction->setCheckable(true);
1296 pHideNotRunningAction->setChecked(m_fShowNotRunningVMs);
1297 connect(pHideNotRunningAction, &QAction::triggered,
1298 this, &UIVMActivityOverviewWidget::sltNotRunningVMVisibility);
1299
1300 QAction *pShowCloudVMsAction =
1301 menu.addAction(UIVMActivityOverviewWidget::tr("Show Cloud Virtual Machines"));
1302 pShowCloudVMsAction->setCheckable(true);
1303 pShowCloudVMsAction->setChecked(m_fShowCloudVMs);
1304 connect(pShowCloudVMsAction, &QAction::triggered,
1305 this, &UIVMActivityOverviewWidget::sltCloudVMVisibility);
1306
1307 menu.exec(m_pTableView->mapToGlobal(pos));
1308}
1309
1310void UIVMActivityOverviewWidget::sltHandleTableSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
1311{
1312 Q_UNUSED(deselected);
1313 if (!m_pVMActivityMonitorAction || !m_pModel || !m_pProxyModel)
1314 return;
1315
1316 if (selected.indexes().empty())
1317 {
1318 m_pVMActivityMonitorAction->setEnabled(false);
1319 return;
1320 }
1321 int iMachineIndex = m_pProxyModel->mapToSource(selected.indexes()[0]).row();
1322 if (!m_pModel->isVMRunning(iMachineIndex))
1323 {
1324 m_pVMActivityMonitorAction->setEnabled(false);
1325 return;
1326 }
1327 m_pVMActivityMonitorAction->setEnabled(true);
1328}
1329
1330void UIVMActivityOverviewWidget::sltHandleShowVMActivityMonitor()
1331{
1332 if (!m_pTableView || !m_pModel)
1333 return;
1334 const QUuid uMachineId = m_pModel->itemUid(m_pTableView->selectedItemIndex());
1335 if (uMachineId.isNull())
1336 return;
1337 emit sigSwitchToMachineActivityPane(uMachineId);
1338}
1339
1340void UIVMActivityOverviewWidget::sltNotRunningVMVisibility(bool fShow)
1341{
1342 m_fShowNotRunningVMs = fShow;
1343 if (m_pProxyModel)
1344 m_pProxyModel->setNotRunningVMVisibility(m_fShowNotRunningVMs);
1345}
1346
1347void UIVMActivityOverviewWidget::sltCloudVMVisibility(bool fShow)
1348{
1349 m_fShowCloudVMs = fShow;
1350 if (m_pProxyModel)
1351 m_pProxyModel->setCloudVMVisibility(m_fShowCloudVMs);
1352}
1353
1354void UIVMActivityOverviewWidget::setColumnVisible(int iColumnId, bool fVisible)
1355{
1356 if (m_columnVisible.contains(iColumnId) && m_columnVisible[iColumnId] == fVisible)
1357 return;
1358 m_columnVisible[iColumnId] = fVisible;
1359 updateModelColumVisibilityCache();
1360}
1361
1362void UIVMActivityOverviewWidget::updateModelColumVisibilityCache()
1363{
1364 if (m_pModel)
1365 m_pModel->setColumnVisible(m_columnVisible);
1366 /* Notify the table view for the changed column visibility: */
1367 if (m_pTableView)
1368 m_pTableView->updateColumVisibility();
1369}
1370
1371void UIVMActivityOverviewWidget::computeMinimumColumnWidths()
1372{
1373 if (!m_pTableView || !m_pModel)
1374 return;
1375 QFontMetrics fontMetrics(m_pTableView->font());
1376 const QMap<int, int> &columnDataStringLengths = m_pModel->dataLengths();
1377 QMap<int, int> columnWidthsInPixels;
1378 for (int i = 0; i < (int)VMActivityOverviewColumn_Max; ++i)
1379 {
1380 int iColumnStringWidth = columnDataStringLengths.value(i, 0);
1381 int iColumnTitleWidth = m_columnTitles.value(i, QString()).length();
1382 int iMax = iColumnStringWidth > iColumnTitleWidth ? iColumnStringWidth : iColumnTitleWidth;
1383 columnWidthsInPixels[i] = iMax * fontMetrics.horizontalAdvance('x')
1384 + QApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin)
1385 + QApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin)
1386 + m_iSortIndicatorWidth;
1387 }
1388 m_pTableView->setMinimumColumnWidths(columnWidthsInPixels);
1389}
1390
1391bool UIVMActivityOverviewWidget::columnVisible(int iColumnId) const
1392{
1393 return m_columnVisible.value(iColumnId, true);
1394}
1395
1396#include "UIVMActivityOverviewWidget.moc"
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