VirtualBox

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

Last change on this file was 104393, checked in by vboxsync, 8 weeks ago

FE/Qt. bugref:10622. Using new UITranslationEventListener in the UIActionPool class.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 76.8 KB
Line 
1/* $Id: UIVMActivityOverviewWidget.cpp 104393 2024-04-22 13:02:56Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIVMActivityOverviewWidget class implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2023 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 <QAbstractTableModel>
30#include <QApplication>
31#include <QCheckBox>
32#include <QHeaderView>
33#include <QItemDelegate>
34#include <QLabel>
35#include <QMenuBar>
36#include <QPainter>
37#include <QPushButton>
38#include <QTableView>
39#include <QTimer>
40#include <QVBoxLayout>
41#include <QSortFilterProxyModel>
42
43/* GUI includes: */
44#include "QIDialogButtonBox.h"
45#include "QIToolBar.h"
46#include "UIActionPoolManager.h"
47#include "UICloudEntityKey.h"
48#include "UICloudNetworkingStuff.h"
49#include "UICommon.h"
50#include "UIConverter.h"
51#include "UIExtraDataDefs.h"
52#include "UIExtraDataManager.h"
53#include "UIGlobalSession.h"
54#include "UIIconPool.h"
55#include "UIMessageCenter.h"
56#include "UITranslator.h"
57#include "UITranslationEventListener.h"
58#include "UIVirtualBoxEventHandler.h"
59#include "UIVirtualMachineItemCloud.h"
60#include "UIVMActivityMonitor.h"
61#include "UIVMActivityOverviewWidget.h"
62
63#ifdef VBOX_WS_MAC
64# include "UIWindowMenuManager.h"
65#endif /* VBOX_WS_MAC */
66
67/* COM includes: */
68#include "CCloudClient.h"
69#include "CConsole.h"
70#include "CMachine.h"
71#include "CMachineDebugger.h"
72#include "CPerformanceMetric.h"
73
74struct ResourceColumn
75{
76 QString m_strName;
77 bool m_fEnabled;
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 UIVMActivityOverviewHostStats definition. *
119*********************************************************************************************************************************/
120/** A simple container to store host related performance values. */
121class UIVMActivityOverviewHostStats
122{
123
124public:
125
126 UIVMActivityOverviewHostStats();
127 quint64 m_iCPUUserLoad;
128 quint64 m_iCPUKernelLoad;
129 quint64 m_iCPUFreq;
130 quint64 m_iRAMTotal;
131 quint64 m_iRAMFree;
132 quint64 m_iFSTotal;
133 quint64 m_iFSFree;
134};
135
136
137/*********************************************************************************************************************************
138* Class UIVMActivityOverviewHostStatsWidget definition. *
139*********************************************************************************************************************************/
140/** A container QWidget to layout host stats. related widgets. */
141class UIVMActivityOverviewHostStatsWidget : public QWidget
142{
143
144 Q_OBJECT;
145
146public:
147
148 UIVMActivityOverviewHostStatsWidget(QWidget *pParent = 0);
149 void setHostStats(const UIVMActivityOverviewHostStats &hostStats);
150
151private slots:
152
153 void sltRetranslateUI();
154
155private:
156
157 void prepare();
158 void addVerticalLine(QHBoxLayout *pLayout);
159 void updateLabels();
160
161 UIVMActivityOverviewDoughnutChart *m_pHostCPUChart;
162 UIVMActivityOverviewDoughnutChart *m_pHostRAMChart;
163 UIVMActivityOverviewDoughnutChart *m_pHostFSChart;
164 QLabel *m_pCPUTitleLabel;
165 QLabel *m_pCPUUserLabel;
166 QLabel *m_pCPUKernelLabel;
167 QLabel *m_pCPUTotalLabel;
168 QLabel *m_pRAMTitleLabel;
169 QLabel *m_pRAMUsedLabel;
170 QLabel *m_pRAMFreeLabel;
171 QLabel *m_pRAMTotalLabel;
172 QLabel *m_pFSTitleLabel;
173 QLabel *m_pFSUsedLabel;
174 QLabel *m_pFSFreeLabel;
175 QLabel *m_pFSTotalLabel;
176 QColor m_CPUUserColor;
177 QColor m_CPUKernelColor;
178 QColor m_RAMFreeColor;
179 QColor m_RAMUsedColor;
180 UIVMActivityOverviewHostStats m_hostStats;
181};
182
183
184/*********************************************************************************************************************************
185* Class UIVMActivityOverviewTableView definition. *
186*********************************************************************************************************************************/
187/** A QTableView extension so manage the column width a bit better than what Qt offers out of box. */
188class UIVMActivityOverviewTableView : public QTableView
189{
190 Q_OBJECT;
191
192signals:
193
194 void sigSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
195
196public:
197
198 UIVMActivityOverviewTableView(QWidget *pParent = 0);
199 void setMinimumColumnWidths(const QMap<int, int>& widths);
200 void updateColumVisibility();
201 int selectedItemIndex() const;
202 bool hasSelection() const;
203
204protected:
205
206 virtual void resizeEvent(QResizeEvent *pEvent) RT_OVERRIDE;
207 virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) RT_OVERRIDE;
208 virtual void mousePressEvent(QMouseEvent *pEvent) RT_OVERRIDE;
209
210private slots:
211
212
213
214private:
215
216 /** Resizes all the columns in response to resizeEvent. Columns cannot be narrower than m_minimumColumnWidths values. */
217 void resizeHeaders();
218 /** Value is in pixels. Columns cannot be narrower than this width. */
219 QMap<int, int> m_minimumColumnWidths;
220};
221
222
223/*********************************************************************************************************************************
224 * Class UIActivityOverviewItem definition. *
225 *********************************************************************************************************************************/
226/** Each instance of UIActivityOverviewItem corresponds to a vm. they are owned my the model. */
227class UIActivityOverviewItem : public QObject
228{
229
230 Q_OBJECT;
231
232public:
233
234 UIActivityOverviewItem(QObject *pParent, const QUuid &uid, const QString &strVMName);
235
236 UIActivityOverviewItem();
237 virtual ~UIActivityOverviewItem();
238 bool operator==(const UIActivityOverviewItem& other) const;
239 int columnLength(int iColumnIndex) const;
240 const QUuid &machineId() const;
241
242 virtual QString machineStateString() const = 0;
243 virtual bool isRunning() const = 0;
244 virtual bool isCloudVM() const = 0;
245 virtual void setMachineState(int iState) = 0;
246
247 QString columnData(int iColumnIndex) const;
248
249 quint64 m_uTotalRAM;
250 quint64 m_uFreeRAM;
251 quint64 m_uUsedRAM;
252 float m_fRAMUsagePercentage;
253
254protected:
255
256 QUuid m_VMuid;
257 QString m_strVMName;
258
259 /** The strings of each column for the item. We update this during performance query
260 * instead of model's data function to know the string length earlier. */
261 QMap<int, QString> m_columnData;
262};
263
264Q_DECLARE_METATYPE(UIActivityOverviewItem);
265
266/*********************************************************************************************************************************
267 * Class UIActivityOverviewItemLocal definition. *
268 *********************************************************************************************************************************/
269/* A UIActivityOverviewItem derivation to show local vms in the table view: */
270class UIActivityOverviewItemLocal : public UIActivityOverviewItem
271{
272 Q_OBJECT;
273public:
274
275 UIActivityOverviewItemLocal(QObject *pParent, const QUuid &uid, const QString &strVMName);
276 UIActivityOverviewItemLocal();
277 ~UIActivityOverviewItemLocal();
278
279 bool isWithGuestAdditions();
280 void resetDebugger();
281 void updateColumnData();
282
283 virtual bool isRunning() const RT_OVERRIDE;
284 virtual bool isCloudVM() const RT_OVERRIDE;
285 virtual QString machineStateString() const RT_OVERRIDE;
286 virtual void setMachineState(int iState) RT_OVERRIDE;
287
288private:
289
290 CSession m_comSession;
291 CGuest m_comGuest;
292 KMachineState m_enmMachineState;
293 quint64 m_uVMExitTotal;
294 quint64 m_uDiskWriteTotal;
295 quint64 m_uDiskReadTotal;
296 quint64 m_uNetworkDownTotal;
297 quint64 m_uNetworkUpTotal;
298 CMachineDebugger m_comDebugger;
299};
300
301/*********************************************************************************************************************************
302 * Class UIActivityOverviewItemCloud definition. *
303 *********************************************************************************************************************************/
304/* A UIActivityOverviewItem derivation to show cloud vms in the table view: */
305class UIActivityOverviewItemCloud : public UIActivityOverviewItem
306{
307 Q_OBJECT;
308public:
309
310 UIActivityOverviewItemCloud(QObject *pParent, const QUuid &uid, const QString &strVMName, CCloudMachine &comCloudMachine);
311
312 UIActivityOverviewItemCloud();
313 ~UIActivityOverviewItemCloud();
314 void updateMachineState();
315 virtual bool isRunning() const RT_OVERRIDE;
316 virtual bool isCloudVM() const RT_OVERRIDE;
317 virtual QString machineStateString() const RT_OVERRIDE;
318 virtual void setMachineState(int iState) RT_OVERRIDE;
319
320protected:
321
322private slots:
323
324 void sltTimeout();
325 void sltMetricNameListingComplete(QVector<QString> metricNameList);
326 void sltMetricDataReceived(KMetricType enmMetricType,
327 const QVector<QString> &data, const QVector<QString> &timeStamps);
328private:
329
330 void getMetricList();
331 void resetColumData();
332
333 QTimer *m_pTimer;
334 CCloudMachine m_comCloudMachine;
335 KCloudMachineState m_enmMachineState;
336 QVector<KMetricType> m_availableMetricTypes;
337};
338
339
340/*********************************************************************************************************************************
341* Class UIVMActivityOverviewProxyModel definition. *
342*********************************************************************************************************************************/
343class UIActivityOverviewProxyModel : public QSortFilterProxyModel
344{
345
346 Q_OBJECT;
347
348public:
349
350 UIActivityOverviewProxyModel(QObject *parent = 0);
351 void dataUpdate();
352 void setNotRunningVMVisibility(bool fShow);
353 void setCloudVMVisibility(bool fShow);
354
355protected:
356
357 virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const RT_OVERRIDE;
358 bool filterAcceptsRow(int iSourceRow, const QModelIndex &sourceParent) const RT_OVERRIDE;
359
360private:
361
362 bool m_fShowNotRunningVMs;
363 bool m_fShowCloudVMs;
364};
365
366
367/*********************************************************************************************************************************
368* Class UIActivityOverviewModel definition. *
369*********************************************************************************************************************************/
370class UIActivityOverviewModel : public QAbstractTableModel
371{
372 Q_OBJECT;
373
374signals:
375
376 void sigDataUpdate();
377 void sigHostStatsUpdate(const UIVMActivityOverviewHostStats &stats);
378
379public:
380
381 UIActivityOverviewModel(QObject *parent = 0);
382 int rowCount(const QModelIndex &parent = QModelIndex()) const RT_OVERRIDE;
383 int columnCount(const QModelIndex &parent = QModelIndex()) const RT_OVERRIDE;
384 QVariant data(const QModelIndex &index, int role) const RT_OVERRIDE;
385 void clearData();
386 QVariant headerData(int section, Qt::Orientation orientation, int role) const RT_OVERRIDE;
387 void setColumnCaptions(const QMap<int, QString>& captions);
388 void setColumnVisible(const QMap<int, bool>& columnVisible);
389 bool columnVisible(int iColumnId) const;
390 void setShouldUpdate(bool fShouldUpdate);
391 const QMap<int, int> dataLengths() const;
392 QUuid itemUid(int iIndex);
393 int itemIndex(const QUuid &uid);
394 bool isVMRunning(int rowIndex) const;
395 bool isCloudVM(int rowIndex) const;
396 void setCloudMachineItems(const QList<UIVirtualMachineItemCloud*> &cloudItems);
397
398private slots:
399
400 void sltMachineStateChanged(const QUuid &uId, const KMachineState state);
401 void sltMachineRegistered(const QUuid &uId, bool fRegistered);
402 void sltLocalVMUpdateTimeout();
403
404private:
405
406 void initialize();
407 void initializeItems();
408 void setupPerformanceCollector();
409 void queryPerformanceCollector();
410 void addItem(const QUuid& uMachineId, const QString& strMachineName, KMachineState enmState);
411 void removeItem(const QUuid& uMachineId);
412 void getHostRAMStats();
413
414 QVector<UIActivityOverviewItem*> m_itemList;
415 QMap<int, QString> m_columnTitles;
416 QTimer *m_pLocalVMUpdateTimer;
417
418 /** @name The following are used during UIPerformanceCollector::QueryMetricsData(..)
419 * @{ */
420 QVector<QString> m_nameList;
421 QVector<CUnknown> m_objectList;
422 /** @} */
423 CPerformanceCollector m_performanceCollector;
424 QMap<int, bool> m_columnVisible;
425 UIVMActivityOverviewHostStats m_hostStats;
426 /** Maximum length of string length of data displayed in column. Updated in UIActivityOverviewModel::data(..). */
427 mutable QMap<int, int> m_columnDataMaxLength;
428};
429
430
431/*********************************************************************************************************************************
432* UIVMActivityOverviewDelegate definition. *
433*********************************************************************************************************************************/
434/** A QItemDelegate child class to disable dashed lines drawn around selected cells in QTableViews */
435class UIVMActivityOverviewDelegate : public QItemDelegate
436{
437
438 Q_OBJECT;
439
440public:
441
442 UIVMActivityOverviewDelegate(QObject *pParent = 0)
443 : QItemDelegate(pParent){}
444
445protected:
446
447 virtual void drawFocus ( QPainter * /*painter*/, const QStyleOptionViewItem & /*option*/, const QRect & /*rect*/ ) const RT_OVERRIDE RT_FINAL {}
448};
449
450
451/*********************************************************************************************************************************
452* Class UIVMActivityOverviewDoughnutChart implementation. *
453*********************************************************************************************************************************/
454UIVMActivityOverviewDoughnutChart::UIVMActivityOverviewDoughnutChart(QWidget *pParent /* = 0 */)
455 :QWidget(pParent)
456 , m_iData0(0)
457 , m_iData1(0)
458 , m_iDataMaximum(0)
459 , m_iMargin(3)
460{
461}
462
463void UIVMActivityOverviewDoughnutChart::updateData(quint64 iData0, quint64 iData1)
464{
465 m_iData0 = iData0;
466 m_iData1 = iData1;
467 update();
468}
469
470void UIVMActivityOverviewDoughnutChart::setChartColors(const QColor &color0, const QColor &color1)
471{
472 m_color0 = color0;
473 m_color1 = color1;
474}
475
476void UIVMActivityOverviewDoughnutChart::setChartCenterString(const QString &strCenter)
477{
478 m_strCenter = strCenter;
479}
480
481void UIVMActivityOverviewDoughnutChart::setDataMaximum(quint64 iMax)
482{
483 m_iDataMaximum = iMax;
484}
485
486void UIVMActivityOverviewDoughnutChart::paintEvent(QPaintEvent *pEvent)
487{
488 QWidget::paintEvent(pEvent);
489
490 QPainter painter(this);
491 painter.setRenderHint(QPainter::Antialiasing);
492
493 int iFrameHeight = height()- 2 * m_iMargin;
494 QRectF outerRect = QRectF(QPoint(m_iMargin,m_iMargin), QSize(iFrameHeight, iFrameHeight));
495 QRectF innerRect = UIMonitorCommon::getScaledRect(outerRect, 0.6f, 0.6f);
496 UIMonitorCommon::drawCombinedDoughnutChart(m_iData0, m_color0,
497 m_iData1, m_color1,
498 painter, m_iDataMaximum,
499 outerRect, innerRect, 80);
500 if (!m_strCenter.isEmpty())
501 {
502 float mul = 1.f / 1.4f;
503 QRectF textRect = UIMonitorCommon::getScaledRect(innerRect, mul, mul);
504 painter.setPen(Qt::black);
505 painter.drawText(textRect, Qt::AlignCenter, m_strCenter);
506 }
507}
508
509
510/*********************************************************************************************************************************
511* Class UIVMActivityOverviewHostStatsWidget implementation. *
512*********************************************************************************************************************************/
513
514UIVMActivityOverviewHostStatsWidget::UIVMActivityOverviewHostStatsWidget(QWidget *pParent /* = 0 */)
515 : QWidget(pParent)
516 , m_pHostCPUChart(0)
517 , m_pHostRAMChart(0)
518 , m_pHostFSChart(0)
519 , m_pCPUTitleLabel(0)
520 , m_pCPUUserLabel(0)
521 , m_pCPUKernelLabel(0)
522 , m_pCPUTotalLabel(0)
523 , m_pRAMTitleLabel(0)
524 , m_pRAMUsedLabel(0)
525 , m_pRAMFreeLabel(0)
526 , m_pRAMTotalLabel(0)
527 , m_pFSTitleLabel(0)
528 , m_pFSUsedLabel(0)
529 , m_pFSFreeLabel(0)
530 , m_pFSTotalLabel(0)
531 , m_CPUUserColor(Qt::red)
532 , m_CPUKernelColor(Qt::blue)
533 , m_RAMFreeColor(Qt::blue)
534 , m_RAMUsedColor(Qt::red)
535{
536 prepare();
537 sltRetranslateUI();
538 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
539 this, &UIVMActivityOverviewHostStatsWidget::sltRetranslateUI);
540}
541
542void UIVMActivityOverviewHostStatsWidget::setHostStats(const UIVMActivityOverviewHostStats &hostStats)
543{
544 m_hostStats = hostStats;
545 if (m_pHostCPUChart)
546 {
547 m_pHostCPUChart->updateData(m_hostStats.m_iCPUUserLoad, m_hostStats.m_iCPUKernelLoad);
548 QString strCenter = QString("%1\nMHz").arg(m_hostStats.m_iCPUFreq);
549 m_pHostCPUChart->setChartCenterString(strCenter);
550 }
551 if (m_pHostRAMChart)
552 {
553 quint64 iUsedRAM = m_hostStats.m_iRAMTotal - m_hostStats.m_iRAMFree;
554 m_pHostRAMChart->updateData(iUsedRAM, m_hostStats.m_iRAMFree);
555 m_pHostRAMChart->setDataMaximum(m_hostStats.m_iRAMTotal);
556 if (m_hostStats.m_iRAMTotal != 0)
557 {
558 quint64 iUsedRamPer = 100 * (iUsedRAM / (float) m_hostStats.m_iRAMTotal);
559 QString strCenter = QString("%1%\n%2").arg(iUsedRamPer).arg(UIVMActivityOverviewWidget::tr("Used"));
560 m_pHostRAMChart->setChartCenterString(strCenter);
561 }
562 }
563 if (m_pHostFSChart)
564 {
565 quint64 iUsedFS = m_hostStats.m_iFSTotal - m_hostStats.m_iFSFree;
566 m_pHostFSChart->updateData(iUsedFS, m_hostStats.m_iFSFree);
567 m_pHostFSChart->setDataMaximum(m_hostStats.m_iFSTotal);
568 if (m_hostStats.m_iFSTotal != 0)
569 {
570 quint64 iUsedFSPer = 100 * (iUsedFS / (float) m_hostStats.m_iFSTotal);
571 QString strCenter = QString("%1%\n%2").arg(iUsedFSPer).arg(UIVMActivityOverviewWidget::tr("Used"));
572 m_pHostFSChart->setChartCenterString(strCenter);
573 }
574 }
575
576 updateLabels();
577}
578
579void UIVMActivityOverviewHostStatsWidget::sltRetranslateUI()
580{
581 updateLabels();
582}
583
584void UIVMActivityOverviewHostStatsWidget::addVerticalLine(QHBoxLayout *pLayout)
585{
586 QFrame *pLine = new QFrame;
587 pLine->setFrameShape(QFrame::VLine);
588 pLine->setFrameShadow(QFrame::Sunken);
589 pLayout->addWidget(pLine);
590}
591
592void UIVMActivityOverviewHostStatsWidget::prepare()
593{
594 QHBoxLayout *pLayout = new QHBoxLayout;
595 setLayout(pLayout);
596 int iMinimumSize = 3 * QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
597
598 /* CPU Stuff: */
599 {
600 /* Host CPU Labels: */
601 QWidget *pCPULabelContainer = new QWidget;
602 pCPULabelContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
603 pLayout->addWidget(pCPULabelContainer);
604 QVBoxLayout *pCPULabelsLayout = new QVBoxLayout;
605 pCPULabelsLayout->setContentsMargins(0, 0, 0, 0);
606 pCPULabelContainer->setLayout(pCPULabelsLayout);
607 m_pCPUTitleLabel = new QLabel;
608 pCPULabelsLayout->addWidget(m_pCPUTitleLabel);
609 m_pCPUUserLabel = new QLabel;
610 pCPULabelsLayout->addWidget(m_pCPUUserLabel);
611 m_pCPUKernelLabel = new QLabel;
612 pCPULabelsLayout->addWidget(m_pCPUKernelLabel);
613 m_pCPUTotalLabel = new QLabel;
614 pCPULabelsLayout->addWidget(m_pCPUTotalLabel);
615 pCPULabelsLayout->setAlignment(Qt::AlignTop);
616 pCPULabelsLayout->setSpacing(0);
617 /* Host CPU chart widget: */
618 m_pHostCPUChart = new UIVMActivityOverviewDoughnutChart;
619 if (m_pHostCPUChart)
620 {
621 m_pHostCPUChart->setMinimumSize(iMinimumSize, iMinimumSize);
622 m_pHostCPUChart->setDataMaximum(100);
623 pLayout->addWidget(m_pHostCPUChart);
624 m_pHostCPUChart->setChartColors(m_CPUUserColor, m_CPUKernelColor);
625 }
626 }
627 addVerticalLine(pLayout);
628 /* RAM Stuff: */
629 {
630 QWidget *pRAMLabelContainer = new QWidget;
631 pRAMLabelContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
632
633 pLayout->addWidget(pRAMLabelContainer);
634 QVBoxLayout *pRAMLabelsLayout = new QVBoxLayout;
635 pRAMLabelsLayout->setContentsMargins(0, 0, 0, 0);
636 pRAMLabelsLayout->setSpacing(0);
637 pRAMLabelContainer->setLayout(pRAMLabelsLayout);
638 m_pRAMTitleLabel = new QLabel;
639 pRAMLabelsLayout->addWidget(m_pRAMTitleLabel);
640 m_pRAMUsedLabel = new QLabel;
641 pRAMLabelsLayout->addWidget(m_pRAMUsedLabel);
642 m_pRAMFreeLabel = new QLabel;
643 pRAMLabelsLayout->addWidget(m_pRAMFreeLabel);
644 m_pRAMTotalLabel = new QLabel;
645 pRAMLabelsLayout->addWidget(m_pRAMTotalLabel);
646
647 m_pHostRAMChart = new UIVMActivityOverviewDoughnutChart;
648 if (m_pHostRAMChart)
649 {
650 m_pHostRAMChart->setMinimumSize(iMinimumSize, iMinimumSize);
651 pLayout->addWidget(m_pHostRAMChart);
652 m_pHostRAMChart->setChartColors(m_RAMUsedColor, m_RAMFreeColor);
653 }
654 }
655 addVerticalLine(pLayout);
656 /* FS Stuff: */
657 {
658 QWidget *pFSLabelContainer = new QWidget;
659 pLayout->addWidget(pFSLabelContainer);
660 pFSLabelContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
661 QVBoxLayout *pFSLabelsLayout = new QVBoxLayout;
662 pFSLabelsLayout->setContentsMargins(0, 0, 0, 0);
663 pFSLabelsLayout->setSpacing(0);
664 pFSLabelContainer->setLayout(pFSLabelsLayout);
665 m_pFSTitleLabel = new QLabel;
666 pFSLabelsLayout->addWidget(m_pFSTitleLabel);
667 m_pFSUsedLabel = new QLabel;
668 pFSLabelsLayout->addWidget(m_pFSUsedLabel);
669 m_pFSFreeLabel = new QLabel;
670 pFSLabelsLayout->addWidget(m_pFSFreeLabel);
671 m_pFSTotalLabel = new QLabel;
672 pFSLabelsLayout->addWidget(m_pFSTotalLabel);
673
674 m_pHostFSChart = new UIVMActivityOverviewDoughnutChart;
675 if (m_pHostFSChart)
676 {
677 m_pHostFSChart->setMinimumSize(iMinimumSize, iMinimumSize);
678 pLayout->addWidget(m_pHostFSChart);
679 m_pHostFSChart->setChartColors(m_RAMUsedColor, m_RAMFreeColor);
680 }
681
682 }
683 pLayout->addStretch(2);
684}
685
686void UIVMActivityOverviewHostStatsWidget::updateLabels()
687{
688 if (m_pCPUTitleLabel)
689 m_pCPUTitleLabel->setText(QString("<b>%1</b>").arg(UIVMActivityOverviewWidget::tr("Host CPU Load")));
690 if (m_pCPUUserLabel)
691 {
692 QString strColor = QColor(m_CPUUserColor).name(QColor::HexRgb);
693 m_pCPUUserLabel->setText(QString("<font color=\"%1\">%2: %3%</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("User")).arg(QString::number(m_hostStats.m_iCPUUserLoad)));
694 }
695 if (m_pCPUKernelLabel)
696 {
697 QString strColor = QColor(m_CPUKernelColor).name(QColor::HexRgb);
698 m_pCPUKernelLabel->setText(QString("<font color=\"%1\">%2: %3%</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Kernel")).arg(QString::number(m_hostStats.m_iCPUKernelLoad)));
699 }
700 if (m_pCPUTotalLabel)
701 m_pCPUTotalLabel->setText(QString("%1: %2%").arg(UIVMActivityOverviewWidget::tr("Total")).arg(m_hostStats.m_iCPUUserLoad + m_hostStats.m_iCPUKernelLoad));
702 if (m_pRAMTitleLabel)
703 m_pRAMTitleLabel->setText(QString("<b>%1</b>").arg(UIVMActivityOverviewWidget::tr("Host RAM Usage")));
704 if (m_pRAMFreeLabel)
705 {
706 QString strRAM = UITranslator::formatSize(m_hostStats.m_iRAMFree);
707 QString strColor = QColor(m_RAMFreeColor).name(QColor::HexRgb);
708 m_pRAMFreeLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Free")).arg(strRAM));
709 }
710 if (m_pRAMUsedLabel)
711 {
712 QString strRAM = UITranslator::formatSize(m_hostStats.m_iRAMTotal - m_hostStats.m_iRAMFree);
713 QString strColor = QColor(m_RAMUsedColor).name(QColor::HexRgb);
714 m_pRAMUsedLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Used")).arg(strRAM));
715 }
716 if (m_pRAMTotalLabel)
717 {
718 QString strRAM = UITranslator::formatSize(m_hostStats.m_iRAMTotal);
719 m_pRAMTotalLabel->setText(QString("%1: %2").arg(UIVMActivityOverviewWidget::tr("Total")).arg(strRAM));
720 }
721 if (m_pFSTitleLabel)
722 m_pFSTitleLabel->setText(QString("<b>%1</b>").arg(UIVMActivityOverviewWidget::tr("Host File System")));
723 if (m_pFSFreeLabel)
724 {
725 QString strFS = UITranslator::formatSize(m_hostStats.m_iFSFree);
726 QString strColor = QColor(m_RAMFreeColor).name(QColor::HexRgb);
727 m_pFSFreeLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Free")).arg(strFS));
728 }
729 if (m_pFSUsedLabel)
730 {
731 QString strFS = UITranslator::formatSize(m_hostStats.m_iFSTotal - m_hostStats.m_iFSFree);
732 QString strColor = QColor(m_RAMUsedColor).name(QColor::HexRgb);
733 m_pFSUsedLabel->setText(QString("<font color=\"%1\">%2: %3</font>").arg(strColor).arg(UIVMActivityOverviewWidget::tr("Used")).arg(strFS));
734 }
735 if (m_pFSTotalLabel)
736 {
737 QString strFS = UITranslator::formatSize(m_hostStats.m_iFSTotal);
738 m_pFSTotalLabel->setText(QString("%1: %2").arg(UIVMActivityOverviewWidget::tr("Total")).arg(strFS));
739 }
740}
741
742
743
744/*********************************************************************************************************************************
745* Class UIVMActivityOverviewTableView implementation. *
746*********************************************************************************************************************************/
747
748UIVMActivityOverviewTableView::UIVMActivityOverviewTableView(QWidget *pParent /* = 0 */)
749 :QTableView(pParent)
750{
751}
752
753void UIVMActivityOverviewTableView::setMinimumColumnWidths(const QMap<int, int>& widths)
754{
755 m_minimumColumnWidths = widths;
756 resizeHeaders();
757}
758
759void UIVMActivityOverviewTableView::updateColumVisibility()
760{
761 UIActivityOverviewProxyModel *pProxyModel = qobject_cast<UIActivityOverviewProxyModel *>(model());
762 if (!pProxyModel)
763 return;
764 UIActivityOverviewModel *pModel = qobject_cast<UIActivityOverviewModel *>(pProxyModel->sourceModel());
765 QHeaderView *pHeader = horizontalHeader();
766
767 if (!pModel || !pHeader)
768 return;
769 for (int i = (int)VMActivityOverviewColumn_Name; i < (int)VMActivityOverviewColumn_Max; ++i)
770 {
771 if (!pModel->columnVisible(i))
772 pHeader->hideSection(i);
773 else
774 pHeader->showSection(i);
775 }
776 resizeHeaders();
777}
778
779int UIVMActivityOverviewTableView::selectedItemIndex() const
780{
781 UIActivityOverviewProxyModel *pModel = qobject_cast<UIActivityOverviewProxyModel*>(model());
782 if (!pModel)
783 return -1;
784
785 QItemSelectionModel *pSelectionModel = selectionModel();
786 if (!pSelectionModel)
787 return -1;
788 QModelIndexList selectedItemIndices = pSelectionModel->selectedRows();
789 if (selectedItemIndices.isEmpty())
790 return -1;
791
792 /* just use the the 1st index: */
793 QModelIndex modelIndex = pModel->mapToSource(selectedItemIndices[0]);
794
795 if (!modelIndex.isValid())
796 return -1;
797 return modelIndex.row();
798}
799
800bool UIVMActivityOverviewTableView::hasSelection() const
801{
802 if (!selectionModel())
803 return false;
804 return selectionModel()->hasSelection();
805}
806
807void UIVMActivityOverviewTableView::resizeEvent(QResizeEvent *pEvent)
808{
809 resizeHeaders();
810 QTableView::resizeEvent(pEvent);
811}
812
813void UIVMActivityOverviewTableView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
814{
815 emit sigSelectionChanged(selected, deselected);
816 QTableView::selectionChanged(selected, deselected);
817}
818
819void UIVMActivityOverviewTableView::mousePressEvent(QMouseEvent *pEvent)
820{
821 if (!indexAt(pEvent->position().toPoint()).isValid())
822 clearSelection();
823 QTableView::mousePressEvent(pEvent);
824}
825
826void UIVMActivityOverviewTableView::resizeHeaders()
827{
828 QHeaderView* pHeader = horizontalHeader();
829 if (!pHeader)
830 return;
831 int iSectionCount = pHeader->count();
832 int iHiddenSectionCount = pHeader->hiddenSectionCount();
833 int iWidth = width() / (iSectionCount - iHiddenSectionCount);
834 for (int i = 0; i < iSectionCount; ++i)
835 {
836 if (pHeader->isSectionHidden(i))
837 continue;
838 int iMinWidth = m_minimumColumnWidths.value((VMActivityOverviewColumn)i, 0);
839 pHeader->resizeSection(i, iWidth < iMinWidth ? iMinWidth : iWidth);
840 }
841}
842
843
844/*********************************************************************************************************************************
845* Class UIActivityOverviewItem implementation. *
846*********************************************************************************************************************************/
847UIActivityOverviewItem::UIActivityOverviewItem(QObject *pParent, const QUuid &uid, const QString &strVMName)
848 : QObject(pParent)
849 , m_uTotalRAM(0)
850 , m_uFreeRAM(0)
851 , m_uUsedRAM(0)
852 , m_fRAMUsagePercentage(0)
853 , m_VMuid(uid)
854 , m_strVMName(strVMName)
855{
856 m_columnData[VMActivityOverviewColumn_Name] = m_strVMName;
857}
858
859UIActivityOverviewItem::UIActivityOverviewItem()
860 : QObject()
861 , m_uTotalRAM(0)
862 , m_uFreeRAM(0)
863 , m_uUsedRAM(0)
864 , m_fRAMUsagePercentage(0)
865 , m_VMuid(QUuid())
866{
867}
868
869UIActivityOverviewItem::~UIActivityOverviewItem()
870{
871}
872
873bool UIActivityOverviewItem::operator==(const UIActivityOverviewItem& other) const
874{
875 if (m_VMuid == other.m_VMuid)
876 return true;
877 return false;
878}
879
880QString UIActivityOverviewItem::columnData(int iColumnIndex) const
881{
882 return m_columnData.value(iColumnIndex, QString());
883}
884
885int UIActivityOverviewItem::columnLength(int iColumnIndex) const
886{
887 return m_columnData.value(iColumnIndex, QString()).length();
888}
889
890const QUuid &UIActivityOverviewItem::machineId() const
891{
892 return m_VMuid;
893}
894
895
896/*********************************************************************************************************************************
897* Class UIVMActivityOverviewHostStats implementation. *
898*********************************************************************************************************************************/
899
900UIVMActivityOverviewHostStats::UIVMActivityOverviewHostStats()
901 : m_iCPUUserLoad(0)
902 , m_iCPUKernelLoad(0)
903 , m_iCPUFreq(0)
904 , m_iRAMTotal(0)
905 , m_iRAMFree(0)
906 , m_iFSTotal(0)
907 , m_iFSFree(0)
908{
909}
910
911
912/*********************************************************************************************************************************
913* Class UIActivityOverviewItemCloud implementation. *
914*********************************************************************************************************************************/
915
916UIActivityOverviewItemCloud::UIActivityOverviewItemCloud(QObject *pParent, const QUuid &uid, const QString &strVMName, CCloudMachine &comCloudMachine)
917 : UIActivityOverviewItem(pParent, uid, strVMName)
918 , m_comCloudMachine(comCloudMachine)
919{
920 updateMachineState();
921 m_pTimer = new QTimer(this);
922 if (m_pTimer)
923 {
924 connect(m_pTimer, &QTimer::timeout, this, &UIActivityOverviewItemCloud::sltTimeout);
925 m_pTimer->setInterval(60 * 1000);
926 }
927 resetColumData();
928}
929
930UIActivityOverviewItemCloud::UIActivityOverviewItemCloud()
931{
932}
933
934UIActivityOverviewItemCloud::~UIActivityOverviewItemCloud()
935{
936}
937
938void UIActivityOverviewItemCloud::updateMachineState()
939{
940 if (m_comCloudMachine.isOk())
941 setMachineState(m_comCloudMachine.GetState());
942}
943
944bool UIActivityOverviewItemCloud::isRunning() const
945{
946 return m_enmMachineState == KCloudMachineState_Running;
947}
948
949bool UIActivityOverviewItemCloud::isCloudVM() const
950{
951 return true;
952}
953
954QString UIActivityOverviewItemCloud::machineStateString() const
955{
956 if (!m_comCloudMachine.isOk())
957 return QString();
958 return gpConverter->toString(m_comCloudMachine.GetState());
959}
960
961void UIActivityOverviewItemCloud::sltTimeout()
962{
963 int iDataSize = 1;
964 foreach (const KMetricType &enmMetricType, m_availableMetricTypes)
965 {
966 UIProgressTaskReadCloudMachineMetricData *pTask = new UIProgressTaskReadCloudMachineMetricData(this, m_comCloudMachine,
967 enmMetricType, iDataSize);
968 connect(pTask, &UIProgressTaskReadCloudMachineMetricData::sigMetricDataReceived,
969 this, &UIActivityOverviewItemCloud::sltMetricDataReceived);
970 pTask->start();
971 }
972}
973
974void UIActivityOverviewItemCloud::sltMetricDataReceived(KMetricType enmMetricType,
975 const QVector<QString> &data, const QVector<QString> &timeStamps)
976{
977 Q_UNUSED(timeStamps);
978 AssertReturnVoid(!data.isEmpty());
979
980 if (data[0].toFloat() < 0)
981 return;
982
983 int iDecimalCount = 2;
984 QLocale locale;
985 if (enmMetricType == KMetricType_CpuUtilization)
986 {
987 //QString QLocale::toString(double i, char f = 'g', int prec = 6) const
988
989 // m_columnData[VMActivityOverviewColumn_CPUGuestLoad] =
990 // QString("%1%").arg(QString::number(data[0].toFloat(), 'f', iDecimalCount));
991
992 m_columnData[VMActivityOverviewColumn_CPUGuestLoad] =
993 QString("%1%").arg(locale.toString(data[0].toFloat(), 'f', iDecimalCount));
994}
995 else if (enmMetricType == KMetricType_MemoryUtilization)
996 {
997 if (m_uTotalRAM != 0)
998 {
999 quint64 uUsedRAM = (quint64)data[0].toFloat() * (m_uTotalRAM / 100.f);
1000 m_columnData[VMActivityOverviewColumn_RAMUsedAndTotal] =
1001 QString("%1/%2").arg(UITranslator::formatSize(_1K * uUsedRAM, iDecimalCount)).
1002 arg(UITranslator::formatSize(_1K * m_uTotalRAM, iDecimalCount));
1003 }
1004 m_columnData[VMActivityOverviewColumn_RAMUsedPercentage] =
1005 QString("%1%").arg(QString::number(data[0].toFloat(), 'f', iDecimalCount));
1006 }
1007 else if (enmMetricType == KMetricType_NetworksBytesOut)
1008 m_columnData[VMActivityOverviewColumn_NetworkUpRate] =
1009 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
1010 else if (enmMetricType == KMetricType_NetworksBytesIn)
1011 m_columnData[VMActivityOverviewColumn_NetworkDownRate] =
1012 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
1013 else if (enmMetricType == KMetricType_DiskBytesRead)
1014 m_columnData[VMActivityOverviewColumn_DiskIOReadRate] =
1015 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
1016 else if (enmMetricType == KMetricType_DiskBytesWritten)
1017 m_columnData[VMActivityOverviewColumn_DiskIOWriteRate] =
1018 UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount);
1019
1020 sender()->deleteLater();
1021}
1022
1023void UIActivityOverviewItemCloud::setMachineState(int iState)
1024{
1025 if (iState <= KCloudMachineState_Invalid || iState >= KCloudMachineState_Max)
1026 return;
1027 KCloudMachineState enmState = static_cast<KCloudMachineState>(iState);
1028 if (m_enmMachineState == enmState)
1029 return;
1030 m_enmMachineState = enmState;
1031 if (isRunning())
1032 {
1033 getMetricList();
1034 if (m_uTotalRAM == 0)
1035 m_uTotalRAM = UIMonitorCommon::determineTotalRAMAmount(m_comCloudMachine);
1036 }
1037 else
1038 {
1039 if (m_pTimer)
1040 m_pTimer->stop();
1041 }
1042}
1043
1044void UIActivityOverviewItemCloud::resetColumData()
1045{
1046 for (int i = (int) VMActivityOverviewColumn_CPUGuestLoad;
1047 i < (int)VMActivityOverviewColumn_Max; ++i)
1048 m_columnData[i] = UIVMActivityOverviewWidget::tr("N/A");
1049}
1050
1051void UIActivityOverviewItemCloud::getMetricList()
1052{
1053 if (!isRunning())
1054 return;
1055 UIProgressTaskReadCloudMachineMetricList *pReadListProgressTask =
1056 new UIProgressTaskReadCloudMachineMetricList(this, m_comCloudMachine);
1057 AssertPtrReturnVoid(pReadListProgressTask);
1058 connect(pReadListProgressTask, &UIProgressTaskReadCloudMachineMetricList::sigMetricListReceived,
1059 this, &UIActivityOverviewItemCloud::sltMetricNameListingComplete);
1060 pReadListProgressTask->start();
1061}
1062
1063void UIActivityOverviewItemCloud::sltMetricNameListingComplete(QVector<QString> metricNameList)
1064{
1065 AssertReturnVoid(m_pTimer);
1066 m_availableMetricTypes.clear();
1067 foreach (const QString &strName, metricNameList)
1068 m_availableMetricTypes << gpConverter->fromInternalString<KMetricType>(strName);
1069
1070 if (!m_availableMetricTypes.isEmpty())
1071 {
1072 /* Dont wait 60 secs: */
1073 sltTimeout();
1074 m_pTimer->start();
1075 }
1076 else
1077 {
1078 m_pTimer->stop();
1079 resetColumData();
1080 }
1081
1082 if (sender())
1083 sender()->deleteLater();
1084
1085}
1086
1087
1088/*********************************************************************************************************************************
1089* Class UIActivityOverviewItemLocal implementation. *
1090*********************************************************************************************************************************/
1091UIActivityOverviewItemLocal::UIActivityOverviewItemLocal(QObject *pParent, const QUuid &uid, const QString &strVMName)
1092 : UIActivityOverviewItem(pParent, uid, strVMName)
1093 , m_enmMachineState(KMachineState_Null)
1094 , m_uVMExitTotal(0)
1095 , m_uDiskWriteTotal(0)
1096 , m_uDiskReadTotal(0)
1097 , m_uNetworkDownTotal(0)
1098 , m_uNetworkUpTotal(0)
1099{
1100 if (m_enmMachineState == KMachineState_Running)
1101 resetDebugger();
1102}
1103
1104UIActivityOverviewItemLocal::UIActivityOverviewItemLocal()
1105 : m_enmMachineState(KMachineState_Null)
1106 , m_uVMExitTotal(0)
1107 , m_uDiskWriteTotal(0)
1108 , m_uDiskReadTotal(0)
1109 , m_uNetworkDownTotal(0)
1110 , m_uNetworkUpTotal(0)
1111{
1112}
1113
1114UIActivityOverviewItemLocal::~UIActivityOverviewItemLocal()
1115{
1116 if (!m_comSession.isNull())
1117 m_comSession.UnlockMachine();
1118}
1119
1120bool UIActivityOverviewItemLocal::isWithGuestAdditions()
1121{
1122 if (m_comGuest.isNull())
1123 return false;
1124 return m_comGuest.GetAdditionsStatus(m_comGuest.GetAdditionsRunLevel());
1125}
1126
1127void UIActivityOverviewItemLocal::resetDebugger()
1128{
1129 m_comSession = uiCommon().openSession(m_VMuid, KLockType_Shared);
1130 if (!m_comSession.isNull())
1131 {
1132 CConsole comConsole = m_comSession.GetConsole();
1133 if (!comConsole.isNull())
1134 {
1135 m_comGuest = comConsole.GetGuest();
1136 m_comDebugger = comConsole.GetDebugger();
1137 }
1138 }
1139}
1140
1141bool UIActivityOverviewItemLocal::isRunning() const
1142{
1143 return m_enmMachineState == KMachineState_Running;
1144}
1145
1146bool UIActivityOverviewItemLocal::isCloudVM() const
1147{
1148 return false;
1149}
1150
1151void UIActivityOverviewItemLocal::setMachineState(int iState)
1152{
1153 if (iState <= KMachineState_Null || iState >= KMachineState_Max)
1154 return;
1155 KMachineState enmState = static_cast<KMachineState>(iState);
1156 if (m_enmMachineState == enmState)
1157 return;
1158 m_enmMachineState = enmState;
1159 if (m_enmMachineState == KMachineState_Running)
1160 resetDebugger();
1161}
1162
1163void UIActivityOverviewItemLocal::updateColumnData()
1164{
1165 AssertReturnVoid(m_comDebugger.isOk());
1166
1167 int iDecimalCount = 2;
1168
1169 /* CPU Load: */
1170 ULONG aPctHalted;
1171 ULONG uCPUGuestLoad;
1172 ULONG uCPUVMMLoad;
1173 m_comDebugger.GetCPULoad(0x7fffffff, uCPUGuestLoad, aPctHalted, uCPUVMMLoad);
1174 m_columnData[VMActivityOverviewColumn_CPUGuestLoad] =
1175 QString("%1%").arg(QString::number(uCPUGuestLoad));
1176 m_columnData[VMActivityOverviewColumn_CPUVMMLoad] =
1177 QString("%1%").arg(QString::number(uCPUVMMLoad));
1178
1179 /* RAM Utilization: */
1180 if (isWithGuestAdditions())
1181 m_columnData[VMActivityOverviewColumn_RAMUsedAndTotal] =
1182 QString("%1/%2").arg(UITranslator::formatSize(_1K * m_uUsedRAM, iDecimalCount)).
1183 arg(UITranslator::formatSize(_1K * m_uTotalRAM, iDecimalCount));
1184 else
1185 m_columnData[VMActivityOverviewColumn_RAMUsedAndTotal] = UIVMActivityOverviewWidget::tr("N/A");
1186
1187 /* RAM Utilization %: */
1188 if (isWithGuestAdditions())
1189 m_columnData[VMActivityOverviewColumn_RAMUsedPercentage] =
1190 QString("%1%").arg(QString::number(m_fRAMUsagePercentage, 'f', 2));
1191 else
1192 m_columnData[VMActivityOverviewColumn_RAMUsedPercentage] = UIVMActivityOverviewWidget::tr("N/A");
1193
1194 /* Network rate: */
1195 quint64 uPrevDownTotal = m_uNetworkDownTotal;
1196 quint64 uPrevUpTotal = m_uNetworkUpTotal;
1197 UIMonitorCommon::getNetworkLoad(m_comDebugger, m_uNetworkDownTotal, m_uNetworkUpTotal);
1198 quint64 uNetworkDownRate = m_uNetworkDownTotal - uPrevDownTotal;
1199 quint64 uNetworkUpRate = m_uNetworkUpTotal - uPrevUpTotal;
1200 m_columnData[VMActivityOverviewColumn_NetworkUpRate] =
1201 QString("%1").arg(UITranslator::formatSize(uNetworkUpRate, iDecimalCount));
1202 m_columnData[VMActivityOverviewColumn_NetworkDownRate] =
1203 QString("%1").arg(UITranslator::formatSize(uNetworkDownRate, iDecimalCount));
1204 m_columnData[VMActivityOverviewColumn_NetworkUpTotal] =
1205 QString("%1").arg(UITranslator::formatSize(m_uNetworkUpTotal, iDecimalCount));
1206 m_columnData[VMActivityOverviewColumn_NetworkDownTotal] =
1207 QString("%1").arg(UITranslator::formatSize(m_uNetworkDownTotal, iDecimalCount));
1208
1209
1210 /* IO rate: */
1211 quint64 uPrevWriteTotal = m_uDiskWriteTotal;
1212 quint64 uPrevReadTotal = m_uDiskReadTotal;
1213 UIMonitorCommon::getDiskLoad(m_comDebugger, m_uDiskWriteTotal, m_uDiskReadTotal);
1214 quint64 uDiskWriteRate = m_uDiskWriteTotal - uPrevWriteTotal;
1215 quint64 uDiskReadRate = m_uDiskReadTotal - uPrevReadTotal;
1216 m_columnData[VMActivityOverviewColumn_DiskIOReadRate] =
1217 QString("%1").arg(UITranslator::formatSize(uDiskReadRate, iDecimalCount));
1218 m_columnData[VMActivityOverviewColumn_DiskIOWriteRate] =
1219 QString("%1").arg(UITranslator::formatSize(uDiskWriteRate, iDecimalCount));
1220 m_columnData[VMActivityOverviewColumn_DiskIOReadTotal] =
1221 QString("%1").arg(UITranslator::formatSize(m_uDiskReadTotal, iDecimalCount));
1222 m_columnData[VMActivityOverviewColumn_DiskIOWriteTotal] =
1223 QString("%1").arg(UITranslator::formatSize(m_uDiskWriteTotal, iDecimalCount));
1224
1225 /* VM Exits: */
1226 quint64 uPrevVMExitsTotal = m_uVMExitTotal;
1227 UIMonitorCommon::getVMMExitCount(m_comDebugger, m_uVMExitTotal);
1228 quint64 uVMExitRate = m_uVMExitTotal - uPrevVMExitsTotal;
1229 m_columnData[VMActivityOverviewColumn_VMExits] =
1230 QString("%1/%2").arg(UITranslator::addMetricSuffixToNumber(uVMExitRate)).
1231 arg(UITranslator::addMetricSuffixToNumber(m_uVMExitTotal));
1232}
1233
1234QString UIActivityOverviewItemLocal::machineStateString() const
1235{
1236 return gpConverter->toString(m_enmMachineState);
1237}
1238
1239
1240/*********************************************************************************************************************************
1241* Class UIVMActivityOverviewProxyModel implementation. *
1242*********************************************************************************************************************************/
1243UIActivityOverviewProxyModel::UIActivityOverviewProxyModel(QObject *parent /* = 0 */)
1244 :QSortFilterProxyModel(parent)
1245{
1246}
1247
1248void UIActivityOverviewProxyModel::dataUpdate()
1249{
1250 if (sourceModel())
1251 emit dataChanged(index(0,0), index(sourceModel()->rowCount(), sourceModel()->columnCount()));
1252 invalidate();
1253}
1254
1255void UIActivityOverviewProxyModel::setNotRunningVMVisibility(bool fShow)
1256{
1257 if (m_fShowNotRunningVMs == fShow)
1258 return;
1259 m_fShowNotRunningVMs = fShow;
1260 invalidateFilter();
1261}
1262
1263void UIActivityOverviewProxyModel::setCloudVMVisibility(bool fShow)
1264{
1265 if (m_fShowCloudVMs == fShow)
1266 return;
1267 m_fShowCloudVMs = fShow;
1268 invalidateFilter();
1269}
1270
1271bool UIActivityOverviewProxyModel::lessThan(const QModelIndex &sourceLeftIndex, const QModelIndex &sourceRightIndex) const
1272{
1273 UIActivityOverviewModel *pModel = qobject_cast<UIActivityOverviewModel*>(sourceModel());
1274 if (pModel)
1275 {
1276 /* Keep running vm always on top of the list: */
1277 bool fLeftRunning = pModel->isVMRunning(sourceLeftIndex.row());
1278 bool fRightRunning = pModel->isVMRunning(sourceRightIndex.row());
1279 if (fLeftRunning && !fRightRunning)
1280 {
1281 if (sortOrder() == Qt::AscendingOrder)
1282 return true;
1283 else
1284 return false;
1285 }
1286 if (!fLeftRunning && fRightRunning)
1287 {
1288 if (sortOrder() == Qt::AscendingOrder)
1289 return false;
1290 else
1291 return true;
1292 }
1293 }
1294 return QSortFilterProxyModel::lessThan(sourceLeftIndex, sourceRightIndex);
1295}
1296
1297bool UIActivityOverviewProxyModel::filterAcceptsRow(int iSourceRow, const QModelIndex &sourceParent) const
1298{
1299 Q_UNUSED(sourceParent);
1300 if (m_fShowNotRunningVMs && m_fShowCloudVMs)
1301 return true;
1302 UIActivityOverviewModel *pModel = qobject_cast<UIActivityOverviewModel*>(sourceModel());
1303 if (!pModel)
1304 return true;
1305
1306 if (!m_fShowNotRunningVMs && !pModel->isVMRunning(iSourceRow))
1307 return false;
1308 if (!m_fShowCloudVMs && pModel->isCloudVM(iSourceRow))
1309 return false;
1310 return true;
1311}
1312
1313
1314/*********************************************************************************************************************************
1315* Class UIActivityOverviewModel implementation. *
1316*********************************************************************************************************************************/
1317UIActivityOverviewModel::UIActivityOverviewModel(QObject *parent /*= 0*/)
1318 :QAbstractTableModel(parent)
1319 , m_pLocalVMUpdateTimer(new QTimer(this))
1320{
1321 initialize();
1322}
1323
1324void UIActivityOverviewModel::initialize()
1325{
1326 for (int i = 0; i < (int)VMActivityOverviewColumn_Max; ++i)
1327 m_columnDataMaxLength[i] = 0;
1328
1329 initializeItems();
1330 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange,
1331 this, &UIActivityOverviewModel::sltMachineStateChanged);
1332 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineRegistered,
1333 this, &UIActivityOverviewModel::sltMachineRegistered);
1334 if (m_pLocalVMUpdateTimer)
1335 {
1336 connect(m_pLocalVMUpdateTimer, &QTimer::timeout, this, &UIActivityOverviewModel::sltLocalVMUpdateTimeout);
1337 m_pLocalVMUpdateTimer->start(1000);
1338 }
1339}
1340
1341int UIActivityOverviewModel::rowCount(const QModelIndex &parent /* = QModelIndex() */) const
1342{
1343 Q_UNUSED(parent);
1344 return m_itemList.size();
1345}
1346
1347int UIActivityOverviewModel::columnCount(const QModelIndex &parent /* = QModelIndex() */) const
1348{
1349 Q_UNUSED(parent);
1350 return VMActivityOverviewColumn_Max;
1351}
1352
1353void UIActivityOverviewModel::setShouldUpdate(bool fShouldUpdate)
1354{
1355 if (m_pLocalVMUpdateTimer)
1356 {
1357 if (fShouldUpdate)
1358 m_pLocalVMUpdateTimer->start();
1359 else
1360 m_pLocalVMUpdateTimer->stop();
1361 }
1362}
1363
1364const QMap<int, int> UIActivityOverviewModel::dataLengths() const
1365{
1366 return m_columnDataMaxLength;
1367}
1368
1369QUuid UIActivityOverviewModel::itemUid(int iIndex)
1370{
1371 if (iIndex >= m_itemList.size() || !m_itemList[iIndex])
1372 return QUuid();
1373 return m_itemList[iIndex]->machineId();
1374}
1375
1376int UIActivityOverviewModel::itemIndex(const QUuid &uid)
1377{
1378 for (int i = 0; i < m_itemList.size(); ++i)
1379 {
1380 if (!m_itemList[i])
1381 continue;
1382 if (m_itemList[i]->machineId() == uid)
1383 return i;
1384 }
1385 return -1;
1386}
1387
1388bool UIActivityOverviewModel::isVMRunning(int rowIndex) const
1389{
1390 if (rowIndex >= m_itemList.size() || rowIndex < 0 || !m_itemList[rowIndex])
1391 return false;
1392 return m_itemList[rowIndex]->isRunning();
1393}
1394
1395bool UIActivityOverviewModel::isCloudVM(int rowIndex) const
1396{
1397 if (rowIndex >= m_itemList.size() || rowIndex < 0 || !m_itemList[rowIndex])
1398 return false;
1399 return m_itemList[rowIndex]->isCloudVM();
1400}
1401
1402void UIActivityOverviewModel::setCloudMachineItems(const QList<UIVirtualMachineItemCloud*> &cloudItems)
1403{
1404 QVector<QUuid> newIds;
1405 foreach (const UIVirtualMachineItemCloud* pItem, cloudItems)
1406 {
1407 if (!pItem)
1408 continue;
1409 QUuid id = pItem->machineId();
1410 if (id.isNull())
1411 continue;
1412 newIds << id;
1413 }
1414 QVector<UIActivityOverviewItem*> originalItemList = m_itemList;
1415
1416 /* Remove m_itemList items that are not in @cloudItems: */
1417 QMutableVectorIterator<UIActivityOverviewItem*> iterator(m_itemList);
1418 while (iterator.hasNext())
1419 {
1420 UIActivityOverviewItem *pItem = iterator.next();
1421 if (!pItem->isCloudVM())
1422 continue;
1423 if (pItem && !newIds.contains(pItem->machineId()))
1424 iterator.remove();
1425 }
1426
1427 /* Add items that are not in m_itemList: */
1428 foreach (const UIVirtualMachineItemCloud* pItem, cloudItems)
1429 {
1430 if (!pItem)
1431 continue;
1432 CCloudMachine comMachine = pItem->machine();
1433 if (!comMachine.isOk())
1434 continue;
1435 QUuid id = comMachine.GetId();
1436 /* Linearly search for the vm with th same id. I cannot make QVector::contain work since we store pointers: */
1437 bool fFound = false;
1438 for (int i = 0; i < m_itemList.size() && !fFound; ++i)
1439 {
1440 if (m_itemList[i] && m_itemList[i]->machineId() == id)
1441 fFound = true;
1442 }
1443 if (!fFound)
1444 m_itemList.append(new UIActivityOverviewItemCloud(this, id, comMachine.GetName(), comMachine));
1445 }
1446
1447 /* Update cloud machine states: */
1448 for (int i = 0; i < m_itemList.size(); ++i)
1449 {
1450 if (!m_itemList[i] || !m_itemList[i]->isCloudVM())
1451 continue;
1452 UIActivityOverviewItemCloud *pItem = qobject_cast<UIActivityOverviewItemCloud*>(m_itemList[i]);
1453 if (!pItem)
1454 continue;
1455 pItem->updateMachineState();
1456 }
1457}
1458
1459QVariant UIActivityOverviewModel::data(const QModelIndex &index, int role) const
1460{
1461 if (!isVMRunning(index.row()))
1462 {
1463 if (role == Qt::FontRole)
1464 {
1465 QFont font = qApp->font();
1466 font.setItalic(true);
1467 return font;
1468 }
1469 if (role == Qt::ForegroundRole)
1470 {
1471 /* For some reason QColor::lighter(..) is not working here: */
1472 QColor color = qApp->palette().color(QPalette::Active, QPalette::WindowText);
1473 int h, s, l;
1474 color.getHsl(&h, &s, &l);
1475 l = 100;
1476 return QColor::fromHsl(h, s, l);
1477 }
1478 }
1479 if (!index.isValid() || role != Qt::DisplayRole || index.row() >= rowCount())
1480 return QVariant();
1481
1482 UIActivityOverviewItem *pItem = m_itemList[index.row()];
1483 AssertPtrReturn(pItem, QVariant());
1484
1485 if (index.column() == VMActivityOverviewColumn_Name)
1486 return pItem->columnData(index.column());
1487
1488 if (!pItem->isRunning())
1489 return pItem->machineStateString();
1490
1491 return pItem->columnData(index.column());
1492}
1493
1494void UIActivityOverviewModel::clearData()
1495{
1496 /* We have a request to detach COM stuff,
1497 * first of all we are removing all the items,
1498 * this will detach COM wrappers implicitly: */
1499 qDeleteAll(m_itemList);
1500 m_itemList.clear();
1501 /* Detaching perf. collector finally,
1502 * please do not use it after all: */
1503 m_performanceCollector.detach();
1504}
1505
1506QVariant UIActivityOverviewModel::headerData(int section, Qt::Orientation orientation, int role) const
1507{
1508 if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
1509 return m_columnTitles.value((VMActivityOverviewColumn)section, QString());;
1510 return QVariant();
1511}
1512
1513void UIActivityOverviewModel::setColumnCaptions(const QMap<int, QString>& captions)
1514{
1515 m_columnTitles = captions;
1516}
1517
1518void UIActivityOverviewModel::initializeItems()
1519{
1520 foreach (const CMachine &comMachine, gpGlobalSession->virtualBox().GetMachines())
1521 {
1522 if (!comMachine.isNull())
1523 addItem(comMachine.GetId(), comMachine.GetName(), comMachine.GetState());
1524 }
1525 setupPerformanceCollector();
1526}
1527
1528void UIActivityOverviewModel::sltMachineStateChanged(const QUuid &uId, const KMachineState state)
1529{
1530 int iIndex = itemIndex(uId);
1531 if (iIndex != -1 && iIndex < m_itemList.size())
1532 {
1533 UIActivityOverviewItemLocal *pItem = qobject_cast<UIActivityOverviewItemLocal*>(m_itemList[iIndex]);
1534 if (pItem)
1535 {
1536 pItem->setMachineState(state);
1537 if (state == KMachineState_Running)
1538 pItem->resetDebugger();
1539 }
1540 }
1541}
1542
1543void UIActivityOverviewModel::sltMachineRegistered(const QUuid &uId, bool fRegistered)
1544{
1545 if (fRegistered)
1546 {
1547 CMachine comMachine = gpGlobalSession->virtualBox().FindMachine(uId.toString());
1548 if (!comMachine.isNull())
1549 addItem(uId, comMachine.GetName(), comMachine.GetState());
1550 }
1551 else
1552 removeItem(uId);
1553 emit sigDataUpdate();
1554}
1555
1556void UIActivityOverviewModel::getHostRAMStats()
1557{
1558 CHost comHost = gpGlobalSession->host();
1559 m_hostStats.m_iRAMTotal = _1M * (quint64)comHost.GetMemorySize();
1560 m_hostStats.m_iRAMFree = _1M * (quint64)comHost.GetMemoryAvailable();
1561}
1562
1563void UIActivityOverviewModel::sltLocalVMUpdateTimeout()
1564{
1565 /* Host's RAM usage is obtained from IHost not from IPerformanceCollector: */
1566 getHostRAMStats();
1567
1568 /* Use IPerformanceCollector to update VM RAM usage and Host CPU and file IO stats: */
1569 queryPerformanceCollector();
1570
1571 for (int i = 0; i < m_itemList.size(); ++i)
1572 {
1573 UIActivityOverviewItemLocal *pItem = qobject_cast<UIActivityOverviewItemLocal*>(m_itemList[i]);
1574 if (!pItem || !pItem->isRunning())
1575 continue;
1576 pItem->updateColumnData();
1577 }
1578
1579 for (int i = 0; i < (int)VMActivityOverviewColumn_Max; ++i)
1580 {
1581 for (int j = 0; j < m_itemList.size(); ++j)
1582 if (m_columnDataMaxLength.value(i, 0) < m_itemList[j]->columnLength(i))
1583 m_columnDataMaxLength[i] = m_itemList[j]->columnLength(i);
1584 }
1585
1586 emit sigDataUpdate();
1587 emit sigHostStatsUpdate(m_hostStats);
1588}
1589
1590void UIActivityOverviewModel::setupPerformanceCollector()
1591{
1592 m_nameList.clear();
1593 m_objectList.clear();
1594 /* Initialize and configure CPerformanceCollector: */
1595 const ULONG iPeriod = 1;
1596 const int iMetricSetupCount = 1;
1597 if (m_performanceCollector.isNull())
1598 m_performanceCollector = gpGlobalSession->virtualBox().GetPerformanceCollector();
1599 for (int i = 0; i < m_itemList.size(); ++i)
1600 m_nameList << "Guest/RAM/Usage*";
1601 /* This is for the host: */
1602 m_nameList << "CPU*";
1603 m_nameList << "FS*";
1604 m_objectList = QVector<CUnknown>(m_nameList.size(), CUnknown());
1605 m_performanceCollector.SetupMetrics(m_nameList, m_objectList, iPeriod, iMetricSetupCount);
1606}
1607
1608void UIActivityOverviewModel::queryPerformanceCollector()
1609{
1610 QVector<QString> aReturnNames;
1611 QVector<CUnknown> aReturnObjects;
1612 QVector<QString> aReturnUnits;
1613 QVector<ULONG> aReturnScales;
1614 QVector<ULONG> aReturnSequenceNumbers;
1615 QVector<ULONG> aReturnDataIndices;
1616 QVector<ULONG> aReturnDataLengths;
1617
1618 QVector<LONG> returnData = m_performanceCollector.QueryMetricsData(m_nameList,
1619 m_objectList,
1620 aReturnNames,
1621 aReturnObjects,
1622 aReturnUnits,
1623 aReturnScales,
1624 aReturnSequenceNumbers,
1625 aReturnDataIndices,
1626 aReturnDataLengths);
1627 /* Parse the result we get from CPerformanceCollector to get respective values: */
1628 for (int i = 0; i < aReturnNames.size(); ++i)
1629 {
1630 if (aReturnDataLengths[i] == 0)
1631 continue;
1632 /* Read the last of the return data disregarding the rest since we are caching the data in GUI side: */
1633 float fData = returnData[aReturnDataIndices[i] + aReturnDataLengths[i] - 1] / (float)aReturnScales[i];
1634 if (aReturnNames[i].contains("RAM", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
1635 {
1636 if (aReturnNames[i].contains("Total", Qt::CaseInsensitive) || aReturnNames[i].contains("Free", Qt::CaseInsensitive))
1637 {
1638 {
1639 CMachine comMachine = (CMachine)aReturnObjects[i];
1640 if (comMachine.isNull())
1641 continue;
1642 int iIndex = itemIndex(comMachine.GetId());
1643 if (iIndex == -1 || iIndex >= m_itemList.size() || !m_itemList[iIndex])
1644 continue;
1645
1646 if (aReturnNames[i].contains("Total", Qt::CaseInsensitive))
1647 m_itemList[iIndex]->m_uTotalRAM = fData;
1648 else
1649 m_itemList[iIndex]->m_uFreeRAM = fData;
1650 }
1651 }
1652 }
1653 else if (aReturnNames[i].contains("CPU/Load/User", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
1654 {
1655 CHost comHost = (CHost)aReturnObjects[i];
1656 if (!comHost.isNull())
1657 m_hostStats.m_iCPUUserLoad = fData;
1658 }
1659 else if (aReturnNames[i].contains("CPU/Load/Kernel", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
1660 {
1661 CHost comHost = (CHost)aReturnObjects[i];
1662 if (!comHost.isNull())
1663 m_hostStats.m_iCPUKernelLoad = fData;
1664 }
1665 else if (aReturnNames[i].contains("CPU/MHz", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
1666 {
1667 CHost comHost = (CHost)aReturnObjects[i];
1668 if (!comHost.isNull())
1669 m_hostStats.m_iCPUFreq = fData;
1670 }
1671 else if (aReturnNames[i].contains("FS", Qt::CaseInsensitive) &&
1672 aReturnNames[i].contains("Total", Qt::CaseInsensitive) &&
1673 !aReturnNames[i].contains(":"))
1674 {
1675 CHost comHost = (CHost)aReturnObjects[i];
1676 if (!comHost.isNull())
1677 m_hostStats.m_iFSTotal = _1M * fData;
1678 }
1679 else if (aReturnNames[i].contains("FS", Qt::CaseInsensitive) &&
1680 aReturnNames[i].contains("Free", Qt::CaseInsensitive) &&
1681 !aReturnNames[i].contains(":"))
1682 {
1683 CHost comHost = (CHost)aReturnObjects[i];
1684 if (!comHost.isNull())
1685 m_hostStats.m_iFSFree = _1M * fData;
1686 }
1687 }
1688 for (int i = 0; i < m_itemList.size(); ++i)
1689 {
1690 if (!m_itemList[i] || m_itemList[i]->isCloudVM())
1691 continue;
1692 m_itemList[i]->m_uUsedRAM = m_itemList[i]->m_uTotalRAM - m_itemList[i]->m_uFreeRAM;
1693 if (m_itemList[i]->m_uTotalRAM != 0)
1694 m_itemList[i]->m_fRAMUsagePercentage = 100.f * (m_itemList[i]->m_uUsedRAM / (float)m_itemList[i]->m_uTotalRAM);
1695 }
1696}
1697
1698void UIActivityOverviewModel::addItem(const QUuid& uMachineId, const QString& strMachineName, KMachineState enmState)
1699{
1700 UIActivityOverviewItemLocal *pItem = new UIActivityOverviewItemLocal(this, uMachineId, strMachineName);
1701 pItem->setMachineState(enmState);
1702 m_itemList.append(pItem);
1703}
1704
1705void UIActivityOverviewModel::removeItem(const QUuid& uMachineId)
1706{
1707 int iIndex = itemIndex(uMachineId);
1708 if (iIndex == -1)
1709 return;
1710 delete m_itemList[iIndex];
1711 m_itemList.remove(iIndex);
1712}
1713
1714void UIActivityOverviewModel::setColumnVisible(const QMap<int, bool>& columnVisible)
1715{
1716 m_columnVisible = columnVisible;
1717}
1718
1719bool UIActivityOverviewModel::columnVisible(int iColumnId) const
1720{
1721 return m_columnVisible.value(iColumnId, true);
1722}
1723
1724
1725/*********************************************************************************************************************************
1726* Class UIVMActivityOverviewWidget implementation. *
1727*********************************************************************************************************************************/
1728
1729UIVMActivityOverviewWidget::UIVMActivityOverviewWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
1730 bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
1731 : QWidget(pParent)
1732 , m_enmEmbedding(enmEmbedding)
1733 , m_pActionPool(pActionPool)
1734 , m_fShowToolbar(fShowToolbar)
1735 , m_pToolBar(0)
1736 , m_pTableView(0)
1737 , m_pProxyModel(0)
1738 , m_pModel(0)
1739 , m_pColumnVisibilityToggleMenu(0)
1740 , m_pHostStatsWidget(0)
1741 , m_fIsCurrentTool(true)
1742 , m_iSortIndicatorWidth(0)
1743 , m_fShowNotRunningVMs(false)
1744 , m_fShowCloudVMs(true)
1745{
1746 prepare();
1747}
1748
1749QMenu *UIVMActivityOverviewWidget::menu() const
1750{
1751 return NULL;
1752}
1753
1754QMenu *UIVMActivityOverviewWidget::columnVisiblityToggleMenu() const
1755{
1756 return m_pColumnVisibilityToggleMenu;
1757}
1758
1759bool UIVMActivityOverviewWidget::isCurrentTool() const
1760{
1761 return m_fIsCurrentTool;
1762}
1763
1764void UIVMActivityOverviewWidget::setIsCurrentTool(bool fIsCurrentTool)
1765{
1766 m_fIsCurrentTool = fIsCurrentTool;
1767 if (m_pModel)
1768 m_pModel->setShouldUpdate(fIsCurrentTool);
1769}
1770
1771void UIVMActivityOverviewWidget::setCloudMachineItems(const QList<UIVirtualMachineItemCloud*> &cloudItems)
1772{
1773 if (m_pModel)
1774 m_pModel->setCloudMachineItems(cloudItems);
1775}
1776
1777void UIVMActivityOverviewWidget::sltRetranslateUI()
1778{
1779 m_columnTitles[VMActivityOverviewColumn_Name] = UIVMActivityOverviewWidget::tr("VM Name");
1780 m_columnTitles[VMActivityOverviewColumn_CPUGuestLoad] = UIVMActivityOverviewWidget::tr("CPU Guest");
1781 m_columnTitles[VMActivityOverviewColumn_CPUVMMLoad] = UIVMActivityOverviewWidget::tr("CPU VMM");
1782 m_columnTitles[VMActivityOverviewColumn_RAMUsedAndTotal] = UIVMActivityOverviewWidget::tr("RAM Used/Total");
1783 m_columnTitles[VMActivityOverviewColumn_RAMUsedPercentage] = UIVMActivityOverviewWidget::tr("RAM %");
1784 m_columnTitles[VMActivityOverviewColumn_NetworkUpRate] = UIVMActivityOverviewWidget::tr("Network Up Rate");
1785 m_columnTitles[VMActivityOverviewColumn_NetworkDownRate] = UIVMActivityOverviewWidget::tr("Network Down Rate");
1786 m_columnTitles[VMActivityOverviewColumn_NetworkUpTotal] = UIVMActivityOverviewWidget::tr("Network Up Total");
1787 m_columnTitles[VMActivityOverviewColumn_NetworkDownTotal] = UIVMActivityOverviewWidget::tr("Network Down Total");
1788 m_columnTitles[VMActivityOverviewColumn_DiskIOReadRate] = UIVMActivityOverviewWidget::tr("Disk Read Rate");
1789 m_columnTitles[VMActivityOverviewColumn_DiskIOWriteRate] = UIVMActivityOverviewWidget::tr("Disk Write Rate");
1790 m_columnTitles[VMActivityOverviewColumn_DiskIOReadTotal] = UIVMActivityOverviewWidget::tr("Disk Read Total");
1791 m_columnTitles[VMActivityOverviewColumn_DiskIOWriteTotal] = UIVMActivityOverviewWidget::tr("Disk Write Total");
1792 m_columnTitles[VMActivityOverviewColumn_VMExits] = UIVMActivityOverviewWidget::tr("VM Exits");
1793
1794 updateColumnsMenu();
1795
1796 if (m_pModel)
1797 m_pModel->setColumnCaptions(m_columnTitles);
1798
1799 computeMinimumColumnWidths();
1800}
1801
1802void UIVMActivityOverviewWidget::showEvent(QShowEvent *pEvent)
1803{
1804 if (m_pVMActivityMonitorAction && m_pTableView)
1805 m_pVMActivityMonitorAction->setEnabled(m_pTableView->hasSelection());
1806
1807 QWidget::showEvent(pEvent);
1808}
1809
1810void UIVMActivityOverviewWidget::prepare()
1811{
1812 /* Try to guest the sort indicator's width: */
1813 int iIndicatorMargin = 3;
1814 QIcon sortIndicator = qApp->QApplication::style()->standardIcon(QStyle::SP_TitleBarUnshadeButton);
1815 QList<QSize> iconSizes = sortIndicator.availableSizes();
1816 foreach(const QSize &msize, iconSizes)
1817 m_iSortIndicatorWidth = qMax(m_iSortIndicatorWidth, msize.width());
1818 if (m_iSortIndicatorWidth == 0)
1819 m_iSortIndicatorWidth = 20;
1820 m_iSortIndicatorWidth += 2 * iIndicatorMargin;
1821
1822 prepareWidgets();
1823 loadSettings();
1824 prepareActions();
1825 sltRetranslateUI();
1826 updateModelColumVisibilityCache();
1827 uiCommon().setHelpKeyword(this, "vm-activity-overview-widget");
1828 connect(&uiCommon(), &UICommon::sigAskToCommitData,
1829 this, &UIVMActivityOverviewWidget::sltSaveSettings);
1830 connect(&uiCommon(), &UICommon::sigAskToDetachCOM,
1831 this, &UIVMActivityOverviewWidget::sltClearCOMData);
1832 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
1833 this, &UIVMActivityOverviewWidget::sltRetranslateUI);
1834 sltCloudVMVisibility(m_fShowCloudVMs);
1835}
1836
1837void UIVMActivityOverviewWidget::prepareWidgets()
1838{
1839 /* Create main-layout: */
1840 new QVBoxLayout(this);
1841 if (!layout())
1842 return;
1843 /* Configure layout: */
1844 layout()->setContentsMargins(0, 0, 0, 0);
1845#ifdef VBOX_WS_MAC
1846 layout()->setSpacing(10);
1847#else
1848 layout()->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
1849#endif
1850
1851 if (m_fShowToolbar)
1852 prepareToolBar();
1853
1854 m_pHostStatsWidget = new UIVMActivityOverviewHostStatsWidget;
1855 if (m_pHostStatsWidget)
1856 layout()->addWidget(m_pHostStatsWidget);
1857
1858 m_pModel = new UIActivityOverviewModel(this);
1859 m_pProxyModel = new UIActivityOverviewProxyModel(this);
1860 m_pTableView = new UIVMActivityOverviewTableView();
1861 if (m_pTableView && m_pModel && m_pProxyModel)
1862 {
1863 layout()->addWidget(m_pTableView);
1864 m_pProxyModel->setSourceModel(m_pModel);
1865 m_pProxyModel->setNotRunningVMVisibility(m_fShowNotRunningVMs);
1866 m_pProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
1867 m_pTableView->setModel(m_pProxyModel);
1868 m_pTableView->setItemDelegate(new UIVMActivityOverviewDelegate(this));
1869 m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
1870 m_pTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
1871 m_pTableView->setShowGrid(false);
1872 m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);
1873 m_pTableView->horizontalHeader()->setHighlightSections(false);
1874 m_pTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
1875 m_pTableView->verticalHeader()->setVisible(false);
1876 m_pTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
1877 /* Minimize the row height: */
1878 m_pTableView->verticalHeader()->setDefaultSectionSize(m_pTableView->verticalHeader()->minimumSectionSize());
1879 m_pTableView->setAlternatingRowColors(true);
1880 m_pTableView->setSortingEnabled(true);
1881 m_pTableView->sortByColumn(0, Qt::AscendingOrder);
1882
1883 connect(m_pModel, &UIActivityOverviewModel::sigDataUpdate,
1884 this, &UIVMActivityOverviewWidget::sltHandleDataUpdate);
1885 connect(m_pModel, &UIActivityOverviewModel::sigHostStatsUpdate,
1886 this, &UIVMActivityOverviewWidget::sltHandleHostStatsUpdate);
1887 connect(m_pTableView, &UIVMActivityOverviewTableView::customContextMenuRequested,
1888 this, &UIVMActivityOverviewWidget::sltHandleTableContextMenuRequest);
1889 connect(m_pTableView, &UIVMActivityOverviewTableView::sigSelectionChanged,
1890 this, &UIVMActivityOverviewWidget::sltHandleTableSelectionChanged);
1891 updateModelColumVisibilityCache();
1892 }
1893}
1894
1895void UIVMActivityOverviewWidget::updateColumnsMenu()
1896{
1897 UIMenu *pMenu = m_pActionPool->action(UIActionIndexMN_M_VMActivityOverview_M_Columns)->menu();
1898 if (!pMenu)
1899 return;
1900 pMenu->clear();
1901 for (int i = 0; i < VMActivityOverviewColumn_Max; ++i)
1902 {
1903 QAction *pAction = pMenu->addAction(m_columnTitles[i]);
1904 pAction->setCheckable(true);
1905 if (i == (int)VMActivityOverviewColumn_Name)
1906 pAction->setEnabled(false);
1907 pAction->setData(i);
1908 pAction->setChecked(columnVisible(i));
1909 connect(pAction, &QAction::toggled, this, &UIVMActivityOverviewWidget::sltHandleColumnAction);
1910 }
1911}
1912
1913void UIVMActivityOverviewWidget::prepareActions()
1914{
1915 updateColumnsMenu();
1916 m_pVMActivityMonitorAction =
1917 m_pActionPool->action(UIActionIndexMN_M_VMActivityOverview_S_SwitchToMachineActivity);
1918
1919 if (m_pVMActivityMonitorAction)
1920 connect(m_pVMActivityMonitorAction, &QAction::triggered, this, &UIVMActivityOverviewWidget::sltHandleShowVMActivityMonitor);
1921}
1922
1923void UIVMActivityOverviewWidget::prepareToolBar()
1924{
1925 /* Create toolbar: */
1926 m_pToolBar = new QIToolBar(parentWidget());
1927 AssertPtrReturnVoid(m_pToolBar);
1928 {
1929 /* Configure toolbar: */
1930 const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
1931 m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
1932 m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
1933
1934#ifdef VBOX_WS_MAC
1935 /* Check whether we are embedded into a stack: */
1936 if (m_enmEmbedding == EmbedTo_Stack)
1937 {
1938 /* Add into layout: */
1939 layout()->addWidget(m_pToolBar);
1940 }
1941#else
1942 /* Add into layout: */
1943 layout()->addWidget(m_pToolBar);
1944#endif
1945 }
1946}
1947
1948void UIVMActivityOverviewWidget::loadSettings()
1949{
1950 /* Load the list of hidden columns: */
1951 QStringList hiddenColumnList = gEDataManager->VMActivityOverviewHiddenColumnList();
1952 for (int i = (int)VMActivityOverviewColumn_Name; i < (int)VMActivityOverviewColumn_Max; ++i)
1953 m_columnVisible[i] = true;
1954 foreach(const QString& strColumn, hiddenColumnList)
1955 setColumnVisible((int)gpConverter->fromInternalString<VMActivityOverviewColumn>(strColumn), false);
1956 /* Load other options: */
1957 sltNotRunningVMVisibility(gEDataManager->VMActivityOverviewShowAllMachines());
1958}
1959
1960void UIVMActivityOverviewWidget::sltSaveSettings()
1961{
1962 /* Save the list of hidden columns: */
1963 QStringList hiddenColumnList;
1964 for (int i = 0; i < m_columnVisible.size(); ++i)
1965 {
1966 if (!columnVisible(i))
1967 hiddenColumnList << gpConverter->toInternalString((VMActivityOverviewColumn) i);
1968 }
1969 gEDataManager->setVMActivityOverviewHiddenColumnList(hiddenColumnList);
1970 gEDataManager->setVMActivityOverviewShowAllMachines(m_fShowNotRunningVMs);
1971}
1972
1973void UIVMActivityOverviewWidget::sltClearCOMData()
1974{
1975 if (m_pModel)
1976 m_pModel->clearData();
1977}
1978
1979void UIVMActivityOverviewWidget::sltToggleColumnSelectionMenu(bool fChecked)
1980{
1981 (void)fChecked;
1982 if (!m_pColumnVisibilityToggleMenu)
1983 return;
1984 m_pColumnVisibilityToggleMenu->exec(this->mapToGlobal(QPoint(0,0)));
1985}
1986
1987void UIVMActivityOverviewWidget::sltHandleColumnAction(bool fChecked)
1988{
1989 QAction* pSender = qobject_cast<QAction*>(sender());
1990 if (!pSender)
1991 return;
1992 setColumnVisible(pSender->data().toInt(), fChecked);
1993}
1994
1995void UIVMActivityOverviewWidget::sltHandleHostStatsUpdate(const UIVMActivityOverviewHostStats &stats)
1996{
1997 if (m_pHostStatsWidget)
1998 m_pHostStatsWidget->setHostStats(stats);
1999}
2000
2001void UIVMActivityOverviewWidget::sltHandleDataUpdate()
2002{
2003 computeMinimumColumnWidths();
2004 if (m_pProxyModel)
2005 m_pProxyModel->dataUpdate();
2006}
2007
2008void UIVMActivityOverviewWidget::sltHandleTableContextMenuRequest(const QPoint &pos)
2009{
2010 if (!m_pTableView)
2011 return;
2012
2013 QMenu menu;
2014 if (m_pVMActivityMonitorAction)
2015 menu.addAction(m_pVMActivityMonitorAction);
2016 menu.addSeparator();
2017
2018 QAction *pHideNotRunningAction =
2019 menu.addAction(UIVMActivityOverviewWidget::tr("List all virtual machines"));
2020 pHideNotRunningAction->setCheckable(true);
2021 pHideNotRunningAction->setChecked(m_fShowNotRunningVMs);
2022 connect(pHideNotRunningAction, &QAction::triggered,
2023 this, &UIVMActivityOverviewWidget::sltNotRunningVMVisibility);
2024
2025 QAction *pShowCloudVMsAction =
2026 menu.addAction(UIVMActivityOverviewWidget::tr("Show cloud virtual machines"));
2027 pShowCloudVMsAction->setCheckable(true);
2028 pShowCloudVMsAction->setChecked(m_fShowCloudVMs);
2029 connect(pShowCloudVMsAction, &QAction::triggered,
2030 this, &UIVMActivityOverviewWidget::sltCloudVMVisibility);
2031
2032 menu.exec(m_pTableView->mapToGlobal(pos));
2033}
2034
2035void UIVMActivityOverviewWidget::sltHandleTableSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
2036{
2037 Q_UNUSED(deselected);
2038 if (!m_pVMActivityMonitorAction || !m_pModel || !m_pProxyModel)
2039 return;
2040
2041 if (selected.indexes().empty())
2042 {
2043 m_pVMActivityMonitorAction->setEnabled(false);
2044 return;
2045 }
2046 int iMachineIndex = m_pProxyModel->mapToSource(selected.indexes()[0]).row();
2047 if (!m_pModel->isVMRunning(iMachineIndex))
2048 {
2049 m_pVMActivityMonitorAction->setEnabled(false);
2050 return;
2051 }
2052 m_pVMActivityMonitorAction->setEnabled(true);
2053}
2054
2055void UIVMActivityOverviewWidget::sltHandleShowVMActivityMonitor()
2056{
2057 if (!m_pTableView || !m_pModel)
2058 return;
2059 const QUuid uMachineId = m_pModel->itemUid(m_pTableView->selectedItemIndex());
2060 if (uMachineId.isNull())
2061 return;
2062 emit sigSwitchToMachineActivityPane(uMachineId);
2063}
2064
2065void UIVMActivityOverviewWidget::sltNotRunningVMVisibility(bool fShow)
2066{
2067 m_fShowNotRunningVMs = fShow;
2068 if (m_pProxyModel)
2069 m_pProxyModel->setNotRunningVMVisibility(m_fShowNotRunningVMs);
2070}
2071
2072void UIVMActivityOverviewWidget::sltCloudVMVisibility(bool fShow)
2073{
2074 m_fShowCloudVMs = fShow;
2075 if (m_pProxyModel)
2076 m_pProxyModel->setCloudVMVisibility(m_fShowCloudVMs);
2077}
2078
2079void UIVMActivityOverviewWidget::setColumnVisible(int iColumnId, bool fVisible)
2080{
2081 if (m_columnVisible.contains(iColumnId) && m_columnVisible[iColumnId] == fVisible)
2082 return;
2083 m_columnVisible[iColumnId] = fVisible;
2084 updateModelColumVisibilityCache();
2085}
2086
2087void UIVMActivityOverviewWidget::updateModelColumVisibilityCache()
2088{
2089 if (m_pModel)
2090 m_pModel->setColumnVisible(m_columnVisible);
2091 /* Notify the table view for the changed column visibility: */
2092 if (m_pTableView)
2093 m_pTableView->updateColumVisibility();
2094}
2095
2096void UIVMActivityOverviewWidget::computeMinimumColumnWidths()
2097{
2098 if (!m_pTableView || !m_pModel)
2099 return;
2100 QFontMetrics fontMetrics(m_pTableView->font());
2101 const QMap<int, int> &columnDataStringLengths = m_pModel->dataLengths();
2102 QMap<int, int> columnWidthsInPixels;
2103 for (int i = 0; i < (int)VMActivityOverviewColumn_Max; ++i)
2104 {
2105 int iColumnStringWidth = columnDataStringLengths.value(i, 0);
2106 int iColumnTitleWidth = m_columnTitles.value(i, QString()).length();
2107 int iMax = iColumnStringWidth > iColumnTitleWidth ? iColumnStringWidth : iColumnTitleWidth;
2108#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
2109 columnWidthsInPixels[i] = iMax * fontMetrics.horizontalAdvance('x') +
2110#else
2111 columnWidthsInPixels[i] = iMax * fontMetrics.width('x') +
2112#endif
2113 QApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin) +
2114 QApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin) +
2115 m_iSortIndicatorWidth;
2116 }
2117 m_pTableView->setMinimumColumnWidths(columnWidthsInPixels);
2118}
2119
2120bool UIVMActivityOverviewWidget::columnVisible(int iColumnId) const
2121{
2122 return m_columnVisible.value(iColumnId, true);
2123}
2124
2125#include "UIVMActivityOverviewWidget.moc"
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use