VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/activity/UIMonitorCommon.cpp@ 100347

Last change on this file since 100347 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: UIMonitorCommon.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMonitorCommon class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-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 <QPainter>
30#include <QPainterPath>
31#include <QPainterPathStroker>
32#include <QXmlStreamReader>
33
34
35/* GUI includes: */
36#include "UICommon.h"
37#include "UIMonitorCommon.h"
38
39/* COM includes: */
40#include "CMachineDebugger.h"
41#include "CPerformanceCollector.h"
42
43/* static */
44void UIMonitorCommon::getNetworkLoad(CMachineDebugger &debugger, quint64 &uOutNetworkReceived, quint64 &uOutNetworkTransmitted)
45{
46 uOutNetworkReceived = 0;
47 uOutNetworkTransmitted = 0;
48 QVector<UIDebuggerMetricData> xmlData = getAndParseStatsFromDebugger(debugger, "/Public/NetAdapter/*/Bytes*");
49 foreach (const UIDebuggerMetricData &data, xmlData)
50 {
51 if (data.m_strName.endsWith("BytesReceived"))
52 uOutNetworkReceived += data.m_counter;
53 else if (data.m_strName.endsWith("BytesTransmitted"))
54 uOutNetworkTransmitted += data.m_counter;
55 else
56 AssertMsgFailed(("name=%s\n", data.m_strName.toLocal8Bit().data()));
57 }
58}
59
60/* static */
61void UIMonitorCommon::getDiskLoad(CMachineDebugger &debugger, quint64 &uOutDiskWritten, quint64 &uOutDiskRead)
62{
63 uOutDiskWritten = 0;
64 uOutDiskRead = 0;
65 QVector<UIDebuggerMetricData> xmlData = getAndParseStatsFromDebugger(debugger, "/Public/Storage/*/Port*/Bytes*");
66 foreach (const UIDebuggerMetricData &data, xmlData)
67 {
68 if (data.m_strName.endsWith("BytesWritten"))
69 uOutDiskWritten += data.m_counter;
70 else if (data.m_strName.endsWith("BytesRead"))
71 uOutDiskRead += data.m_counter;
72 else
73 AssertMsgFailed(("name=%s\n", data.m_strName.toLocal8Bit().data()));
74 }
75}
76
77/* static */
78void UIMonitorCommon::getVMMExitCount(CMachineDebugger &debugger, quint64 &uOutVMMExitCount)
79{
80 uOutVMMExitCount = 0;
81 QVector<UIDebuggerMetricData> xmlData = getAndParseStatsFromDebugger(debugger, "/PROF/CPU*/EM/RecordedExits");
82 foreach (const UIDebuggerMetricData &data, xmlData)
83 {
84 if (data.m_strName.endsWith("RecordedExits"))
85 uOutVMMExitCount += data.m_counter;
86 else
87 AssertMsgFailed(("name=%s\n", data.m_strName.toLocal8Bit().data()));
88 }
89}
90
91
92/* static */
93QVector<UIDebuggerMetricData> UIMonitorCommon::getAndParseStatsFromDebugger(CMachineDebugger &debugger, const QString &strQuery)
94{
95 QVector<UIDebuggerMetricData> xmlData;
96 if (strQuery.isEmpty())
97 return xmlData;
98 QString strStats = debugger.GetStats(strQuery, false);
99 QXmlStreamReader xmlReader;
100 xmlReader.addData(strStats);
101 if (xmlReader.readNextStartElement())
102 {
103 while (xmlReader.readNextStartElement())
104 {
105 if (xmlReader.name() == QLatin1String("Counter"))
106 {
107 QXmlStreamAttributes attributes = xmlReader.attributes();
108 quint64 iCounter = attributes.value("c").toULongLong();
109 xmlData.push_back(UIDebuggerMetricData(attributes.value("name").toString(), iCounter));
110 }
111 else if (xmlReader.name() == QLatin1String("U64"))
112 {
113 QXmlStreamAttributes attributes = xmlReader.attributes();
114 quint64 iCounter = attributes.value("val").toULongLong();
115 xmlData.push_back(UIDebuggerMetricData(attributes.value("name").toString(), iCounter));
116 }
117 xmlReader.skipCurrentElement();
118 }
119 }
120 return xmlData;
121}
122
123/* static */
124void UIMonitorCommon::getRAMLoad(CPerformanceCollector &comPerformanceCollector, QVector<QString> &nameList,
125 QVector<CUnknown>& objectList, quint64 &iOutTotalRAM, quint64 &iOutFreeRAM)
126{
127 iOutTotalRAM = 0;
128 iOutFreeRAM = 0;
129 QVector<QString> aReturnNames;
130 QVector<CUnknown> aReturnObjects;
131 QVector<QString> aReturnUnits;
132 QVector<ULONG> aReturnScales;
133 QVector<ULONG> aReturnSequenceNumbers;
134 QVector<ULONG> aReturnDataIndices;
135 QVector<ULONG> aReturnDataLengths;
136 /* Make a query to CPerformanceCollector to fetch some metrics (e.g RAM usage): */
137 QVector<LONG> returnData = comPerformanceCollector.QueryMetricsData(nameList,
138 objectList,
139 aReturnNames,
140 aReturnObjects,
141 aReturnUnits,
142 aReturnScales,
143 aReturnSequenceNumbers,
144 aReturnDataIndices,
145 aReturnDataLengths);
146 /* Parse the result we get from CPerformanceCollector to get respective values: */
147 for (int i = 0; i < aReturnNames.size(); ++i)
148 {
149 if (aReturnDataLengths[i] == 0)
150 continue;
151 /* Read the last of the return data disregarding the rest since we are caching the data in GUI side: */
152 float fData = returnData[aReturnDataIndices[i] + aReturnDataLengths[i] - 1] / (float)aReturnScales[i];
153 if (aReturnNames[i].contains("RAM", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
154 {
155 if (aReturnNames[i].contains("Total", Qt::CaseInsensitive))
156 iOutTotalRAM = (quint64)fData;
157 if (aReturnNames[i].contains("Free", Qt::CaseInsensitive))
158 iOutFreeRAM = (quint64)fData;
159 }
160 }
161}
162
163/* static */
164QPainterPath UIMonitorCommon::doughnutSlice(const QRectF &outerRectangle, const QRectF &innerRectangle, float fStartAngle, float fSweepAngle)
165{
166 QPainterPath subPath1;
167 subPath1.moveTo(outerRectangle.center());
168 subPath1.arcTo(outerRectangle, fStartAngle,
169 -1.f * fSweepAngle);
170 subPath1.closeSubpath();
171
172 QPainterPath subPath2;
173 subPath2.moveTo(innerRectangle.center());
174 subPath2.arcTo(innerRectangle, fStartAngle,
175 -1.f * fSweepAngle);
176 subPath2.closeSubpath();
177
178 return subPath1.subtracted(subPath2);
179}
180
181/* static */
182QPainterPath UIMonitorCommon::wholeArc(const QRectF &rectangle)
183{
184 QPainterPath arc;
185 arc.addEllipse(rectangle);
186 return arc;
187}
188
189/* static */
190void UIMonitorCommon::drawCombinedDoughnutChart(quint64 data1, const QColor &data1Color,
191 quint64 data2, const QColor &data2Color,
192 QPainter &painter, quint64 iMaximum,
193 const QRectF &chartRect, const QRectF &innerRect, int iOverlayAlpha)
194{
195 (void)data2;
196 (void)data2Color;
197 (void)iOverlayAlpha;
198 /* Draw two arcs. one for the inner the other for the outer circle: */
199 painter.setPen(QPen(QColor(100, 100, 100, iOverlayAlpha), 1));
200 painter.drawArc(chartRect, 0, 3600 * 16);
201 painter.drawArc(innerRect, 0, 3600 * 16);
202
203 /* Draw a translucent white background: */
204 QPainterPath background = wholeArc(chartRect).subtracted(wholeArc(innerRect));
205 painter.setPen(Qt::NoPen);
206 painter.setBrush(QColor(255, 255, 255, iOverlayAlpha));
207 painter.drawPath(background);
208
209 /* Draw a doughnut slice for the first data series: */
210 float fAngle = 360.f * data1 / (float)iMaximum;
211 painter.setBrush(data1Color);
212 painter.drawPath(doughnutSlice(chartRect, innerRect, 90, fAngle));
213
214 float fAngle2 = 360.f * data2 / (float)iMaximum;
215 painter.setBrush(data2Color);
216 painter.drawPath(doughnutSlice(chartRect, innerRect, 90 - fAngle, fAngle2));
217}
218
219/* static */
220QRectF UIMonitorCommon::getScaledRect(const QRectF &outerFrame, float fScaleX, float fScaleY)
221{
222 if (!outerFrame.isValid())
223 return QRectF();
224 QPointF center = outerFrame.center();
225 float iWidth = fScaleX * outerFrame.width();
226 float iHeight = fScaleY * outerFrame.height();
227 return QRectF(QPointF(center.x() - 0.5 * iWidth, center.y() - 0.5 * iHeight),
228 QSizeF(iWidth, iHeight));
229}
230
231/* static */
232void UIMonitorCommon::drawDoughnutChart(QPainter &painter, quint64 iMaximum, quint64 data,
233 const QRectF &chartRect, const QRectF &innerRect, int iOverlayAlpha, const QColor &color)
234{
235 /* Draw a whole non-filled circle: */
236 painter.setPen(QPen(QColor(100, 100, 100, iOverlayAlpha), 1));
237 painter.drawArc(chartRect, 0, 3600 * 16);
238 painter.drawArc(innerRect, 0, 3600 * 16);
239
240 /* Draw a white filled circle and the arc for data: */
241 QPainterPath background = UIMonitorCommon::wholeArc(chartRect).subtracted(UIMonitorCommon::wholeArc(innerRect));
242 painter.setPen(Qt::NoPen);
243 painter.setBrush(QColor(255, 255, 255, iOverlayAlpha));
244 painter.drawPath(background);
245
246 /* Draw the doughnut slice for the data: */
247 float fAngle = 360.f * data / (float)iMaximum;
248 painter.setBrush(color);
249 painter.drawPath(UIMonitorCommon::doughnutSlice(chartRect, innerRect, 90, fAngle));
250}
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