1 | /* $Id: UIVMActivityOverviewModelView.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBox Qt GUI - UIVMActivityOverviewModelView 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 <QHeaderView>
|
---|
31 | #include <QMouseEvent>
|
---|
32 | #include <QTimer>
|
---|
33 |
|
---|
34 | /* GUI includes: */
|
---|
35 | #include "UIConverter.h"
|
---|
36 | #include "UIExtraDataDefs.h"
|
---|
37 | #include "UIGlobalSession.h"
|
---|
38 | #include "UILocalMachineStuff.h"
|
---|
39 | #include "UIMonitorCommon.h"
|
---|
40 | #include "UITranslator.h"
|
---|
41 | #include "UIVirtualBoxEventHandler.h"
|
---|
42 | #include "UIVirtualMachineItemCloud.h"
|
---|
43 | #include "UIVMActivityOverviewModelView.h"
|
---|
44 |
|
---|
45 |
|
---|
46 | #ifdef VBOX_WS_MAC
|
---|
47 | # include "UIWindowMenuManager.h"
|
---|
48 | #endif /* VBOX_WS_MAC */
|
---|
49 |
|
---|
50 | /* COM includes: */
|
---|
51 | #include "CConsole.h"
|
---|
52 | #include "CGuest.h"
|
---|
53 | #include "CMachine.h"
|
---|
54 | #include "CMachineDebugger.h"
|
---|
55 | #include "CSession.h"
|
---|
56 | #include "KMetricType.h"
|
---|
57 |
|
---|
58 | /*********************************************************************************************************************************
|
---|
59 | * UIVMActivityOverviewCell definition. *
|
---|
60 | *********************************************************************************************************************************/
|
---|
61 |
|
---|
62 | class UIVMActivityOverviewCell : public QITableViewCell
|
---|
63 | {
|
---|
64 |
|
---|
65 | Q_OBJECT;
|
---|
66 |
|
---|
67 | public:
|
---|
68 |
|
---|
69 | UIVMActivityOverviewCell(QITableViewRow *pRow);
|
---|
70 | virtual QString text() const RT_OVERRIDE RT_FINAL;
|
---|
71 | int columnLength(int iColumnIndex) const;
|
---|
72 | void setText(const QString &strText);
|
---|
73 |
|
---|
74 | private:
|
---|
75 |
|
---|
76 | QString m_strText;
|
---|
77 | };
|
---|
78 |
|
---|
79 |
|
---|
80 | /*********************************************************************************************************************************
|
---|
81 | * UIVMActivityOverviewRow definition. *
|
---|
82 | *********************************************************************************************************************************/
|
---|
83 |
|
---|
84 | class UIVMActivityOverviewRow : public QITableViewRow
|
---|
85 | {
|
---|
86 |
|
---|
87 | Q_OBJECT;
|
---|
88 |
|
---|
89 | public:
|
---|
90 |
|
---|
91 | UIVMActivityOverviewRow(QITableView *pTableView, const QUuid &uMachineId,
|
---|
92 | const QString &strMachineName);
|
---|
93 |
|
---|
94 | const QUuid &machineId() const;
|
---|
95 |
|
---|
96 | virtual void setMachineState(int iState) = 0;
|
---|
97 | virtual bool isRunning() const = 0;
|
---|
98 | virtual bool isCloudVM() const = 0;
|
---|
99 |
|
---|
100 | virtual ~UIVMActivityOverviewRow();
|
---|
101 | virtual int childCount() const RT_OVERRIDE RT_FINAL;
|
---|
102 |
|
---|
103 | virtual QITableViewCell *childItem(int iIndex) const RT_OVERRIDE RT_FINAL;
|
---|
104 | int columnLength(int iColumnIndex) const;
|
---|
105 | QString cellText(int iColumn) const;
|
---|
106 | virtual QString machineStateString() const = 0;
|
---|
107 |
|
---|
108 | protected:
|
---|
109 | void updateCellText(int /*VMActivityOverviewColumn*/ iColumnIndex, const QString &strText);
|
---|
110 | QUuid m_uMachineId;
|
---|
111 | /* Key is VMActivityOverviewColumn enum item. */
|
---|
112 | QMap<int, UIVMActivityOverviewCell*> m_cells;
|
---|
113 |
|
---|
114 | QString m_strMachineName;
|
---|
115 | quint64 m_uTotalRAM;
|
---|
116 |
|
---|
117 | private:
|
---|
118 |
|
---|
119 | void initCells();
|
---|
120 | };
|
---|
121 |
|
---|
122 | /*********************************************************************************************************************************
|
---|
123 | * UIVMActivityOverviewRowLocal definition. *
|
---|
124 | *********************************************************************************************************************************/
|
---|
125 |
|
---|
126 | class UIVMActivityOverviewRowLocal : public UIVMActivityOverviewRow
|
---|
127 | {
|
---|
128 |
|
---|
129 | Q_OBJECT;
|
---|
130 |
|
---|
131 | public:
|
---|
132 |
|
---|
133 | UIVMActivityOverviewRowLocal(QITableView *pTableView, const QUuid &uMachineId,
|
---|
134 | const QString &strMachineName, KMachineState enmMachineState);
|
---|
135 | ~UIVMActivityOverviewRowLocal();
|
---|
136 | virtual void setMachineState(int iState) RT_OVERRIDE RT_FINAL;
|
---|
137 |
|
---|
138 | virtual bool isRunning() const RT_OVERRIDE RT_FINAL;
|
---|
139 | virtual bool isCloudVM() const RT_OVERRIDE RT_FINAL;
|
---|
140 | virtual QString machineStateString() const RT_OVERRIDE RT_FINAL;
|
---|
141 | void resetDebugger();
|
---|
142 | void updateCells();
|
---|
143 | bool isWithGuestAdditions();
|
---|
144 | void setTotalRAM(quint64 uTotalRAM);
|
---|
145 | void setFreeRAM(quint64 uFreeRAM);
|
---|
146 |
|
---|
147 | private:
|
---|
148 |
|
---|
149 | KMachineState m_enmMachineState;
|
---|
150 | CMachineDebugger m_comDebugger;
|
---|
151 | CSession m_comSession;
|
---|
152 | CGuest m_comGuest;
|
---|
153 | quint64 m_uFreeRAM;
|
---|
154 | quint64 m_uNetworkDownTotal;
|
---|
155 | quint64 m_uNetworkUpTotal;
|
---|
156 | quint64 m_uVMExitTotal;
|
---|
157 | quint64 m_uDiskWriteTotal;
|
---|
158 | quint64 m_uDiskReadTotal;
|
---|
159 | };
|
---|
160 |
|
---|
161 |
|
---|
162 | /*********************************************************************************************************************************
|
---|
163 | * UIVMActivityOverviewRowCloud definition. *
|
---|
164 | *********************************************************************************************************************************/
|
---|
165 |
|
---|
166 | /* A UIVMActivityOverviewItem derivation to show cloud vms in the table view: */
|
---|
167 | class UIVMActivityOverviewRowCloud : public UIVMActivityOverviewRow
|
---|
168 | {
|
---|
169 | Q_OBJECT;
|
---|
170 |
|
---|
171 | public:
|
---|
172 |
|
---|
173 | UIVMActivityOverviewRowCloud(QITableView *pTableView, const QUuid &uMachineId,
|
---|
174 | const QString &strMachineName, CCloudMachine &comCloudMachine);
|
---|
175 | void updateMachineState();
|
---|
176 | virtual bool isRunning() const RT_OVERRIDE RT_FINAL;
|
---|
177 | virtual bool isCloudVM() const RT_OVERRIDE RT_FINAL;
|
---|
178 | virtual QString machineStateString() const RT_OVERRIDE RT_FINAL;
|
---|
179 | virtual void setMachineState(int iState) RT_OVERRIDE RT_FINAL;
|
---|
180 |
|
---|
181 | private slots:
|
---|
182 |
|
---|
183 | void sltTimeout();
|
---|
184 | void sltMetricNameListingComplete(QVector<QString> metricNameList);
|
---|
185 | void sltMetricDataReceived(KMetricType enmMetricType,
|
---|
186 | const QVector<QString> &data, const QVector<QString> &timeStamps);
|
---|
187 | private:
|
---|
188 |
|
---|
189 | void getMetricList();
|
---|
190 | void resetColumData();
|
---|
191 |
|
---|
192 | QTimer *m_pTimer;
|
---|
193 | CCloudMachine m_comCloudMachine;
|
---|
194 | KCloudMachineState m_enmMachineState;
|
---|
195 | QVector<KMetricType> m_availableMetricTypes;
|
---|
196 | };
|
---|
197 |
|
---|
198 |
|
---|
199 | /*********************************************************************************************************************************
|
---|
200 | * UIVMActivityOverviewCell implementation. *
|
---|
201 | *********************************************************************************************************************************/
|
---|
202 |
|
---|
203 | UIVMActivityOverviewCell::UIVMActivityOverviewCell(QITableViewRow *pRow)
|
---|
204 | :QITableViewCell(pRow)
|
---|
205 | {
|
---|
206 | }
|
---|
207 |
|
---|
208 | QString UIVMActivityOverviewCell::text() const
|
---|
209 | {
|
---|
210 | return m_strText;
|
---|
211 | }
|
---|
212 |
|
---|
213 | int UIVMActivityOverviewCell::columnLength(int /*iColumnIndex*/) const
|
---|
214 | {
|
---|
215 | return 0;
|
---|
216 | }
|
---|
217 |
|
---|
218 | void UIVMActivityOverviewCell::setText(const QString &strText)
|
---|
219 | {
|
---|
220 | m_strText = strText;
|
---|
221 | }
|
---|
222 |
|
---|
223 | /*********************************************************************************************************************************
|
---|
224 | * UIVMActivityOverviewRow implementation. *
|
---|
225 | *********************************************************************************************************************************/
|
---|
226 |
|
---|
227 | UIVMActivityOverviewRow::UIVMActivityOverviewRow(QITableView *pTableView, const QUuid &uMachineId,
|
---|
228 | const QString &strMachineName)
|
---|
229 | : QITableViewRow(pTableView)
|
---|
230 | , m_uMachineId(uMachineId)
|
---|
231 | , m_strMachineName(strMachineName)
|
---|
232 | , m_uTotalRAM(0)
|
---|
233 | {
|
---|
234 | initCells();
|
---|
235 | }
|
---|
236 |
|
---|
237 | int UIVMActivityOverviewRow::childCount() const
|
---|
238 | {
|
---|
239 | return m_cells.size();
|
---|
240 | }
|
---|
241 |
|
---|
242 | QITableViewCell *UIVMActivityOverviewRow::childItem(int iIndex) const
|
---|
243 | {
|
---|
244 | return m_cells.value(iIndex, 0);
|
---|
245 | }
|
---|
246 |
|
---|
247 | QString UIVMActivityOverviewRow::cellText(int iColumn) const
|
---|
248 | {
|
---|
249 | if (!m_cells.contains(iColumn))
|
---|
250 | return QString();
|
---|
251 | if (!m_cells[iColumn])
|
---|
252 | return QString();
|
---|
253 | return m_cells[iColumn]->text();
|
---|
254 | }
|
---|
255 |
|
---|
256 | int UIVMActivityOverviewRow::columnLength(int iColumnIndex) const
|
---|
257 | {
|
---|
258 | UIVMActivityOverviewCell *pCell = m_cells.value(iColumnIndex, 0);
|
---|
259 | if (!pCell)
|
---|
260 | return 0;
|
---|
261 | return pCell->text().length();
|
---|
262 | }
|
---|
263 |
|
---|
264 | UIVMActivityOverviewRow::~UIVMActivityOverviewRow()
|
---|
265 | {
|
---|
266 | qDeleteAll(m_cells);
|
---|
267 | }
|
---|
268 |
|
---|
269 | void UIVMActivityOverviewRow::initCells()
|
---|
270 | {
|
---|
271 | for (int i = (int) VMActivityOverviewColumn_Name; i < (int) VMActivityOverviewColumn_Max; ++i)
|
---|
272 | m_cells[i] = new UIVMActivityOverviewCell(this);
|
---|
273 | m_cells[VMActivityOverviewColumn_Name]->setText(m_strMachineName);
|
---|
274 | }
|
---|
275 |
|
---|
276 | const QUuid &UIVMActivityOverviewRow::machineId() const
|
---|
277 | {
|
---|
278 | return m_uMachineId;
|
---|
279 | }
|
---|
280 |
|
---|
281 | void UIVMActivityOverviewRow::updateCellText(int /*VMActivityOverviewColumn*/ enmColumnIndex, const QString &strText)
|
---|
282 | {
|
---|
283 | if (m_cells.value(enmColumnIndex, 0))
|
---|
284 | m_cells[enmColumnIndex]->setText(strText);
|
---|
285 | }
|
---|
286 |
|
---|
287 | /*********************************************************************************************************************************
|
---|
288 | * UIVMActivityOverviewRowLocal implementation. *
|
---|
289 | *********************************************************************************************************************************/
|
---|
290 |
|
---|
291 | UIVMActivityOverviewRowLocal::UIVMActivityOverviewRowLocal(QITableView *pTableView, const QUuid &uMachineId,
|
---|
292 | const QString &strMachineName, KMachineState enmMachineState)
|
---|
293 | : UIVMActivityOverviewRow(pTableView, uMachineId, strMachineName)
|
---|
294 | , m_enmMachineState(enmMachineState)
|
---|
295 | , m_uFreeRAM(0)
|
---|
296 | , m_uNetworkDownTotal(0)
|
---|
297 | , m_uNetworkUpTotal(0)
|
---|
298 | , m_uVMExitTotal(0)
|
---|
299 | , m_uDiskWriteTotal(0)
|
---|
300 | , m_uDiskReadTotal(0)
|
---|
301 | {
|
---|
302 | if (m_enmMachineState == KMachineState_Running)
|
---|
303 | resetDebugger();
|
---|
304 | }
|
---|
305 |
|
---|
306 | void UIVMActivityOverviewRowLocal::updateCells()
|
---|
307 | {
|
---|
308 | /* CPU Load: */
|
---|
309 | ULONG aPctHalted;
|
---|
310 | ULONG uCPUGuestLoad;
|
---|
311 | ULONG uCPUVMMLoad;
|
---|
312 | m_comDebugger.GetCPULoad(0x7fffffff, uCPUGuestLoad, aPctHalted, uCPUVMMLoad);
|
---|
313 | updateCellText(VMActivityOverviewColumn_CPUVMMLoad, QString("%1%").arg(QString::number(uCPUVMMLoad)));
|
---|
314 | updateCellText(VMActivityOverviewColumn_CPUGuestLoad, QString("%1%").arg(QString::number(uCPUGuestLoad)));
|
---|
315 |
|
---|
316 | /* RAM Utilization: */
|
---|
317 | QString strRAMUsage;
|
---|
318 | QString strRAMPercentage;
|
---|
319 | int iDecimalCount = 2;
|
---|
320 | quint64 uUsedRAM = m_uTotalRAM - m_uFreeRAM;
|
---|
321 | float m_fRAMUsagePercentage = 0;
|
---|
322 |
|
---|
323 | if (m_uTotalRAM != 0)
|
---|
324 | m_fRAMUsagePercentage = 100.f * (uUsedRAM / (float)m_uTotalRAM);
|
---|
325 |
|
---|
326 | if (isWithGuestAdditions())
|
---|
327 | {
|
---|
328 | strRAMUsage =
|
---|
329 | QString("%1/%2").arg(UITranslator::formatSize(_1K * uUsedRAM, iDecimalCount)).
|
---|
330 | arg(UITranslator::formatSize(_1K * m_uTotalRAM, iDecimalCount));
|
---|
331 | strRAMPercentage =
|
---|
332 | QString("%1%").arg(QString::number(m_fRAMUsagePercentage, 'f', 2));
|
---|
333 | }
|
---|
334 | else
|
---|
335 | {
|
---|
336 | strRAMPercentage = QApplication::translate("UIVMActivityOverviewWidget", "N/A");
|
---|
337 | strRAMUsage = QApplication::translate("UIVMActivityOverviewWidget", "N/A");
|
---|
338 | }
|
---|
339 |
|
---|
340 | updateCellText(VMActivityOverviewColumn_RAMUsedAndTotal, strRAMUsage);
|
---|
341 | updateCellText(VMActivityOverviewColumn_RAMUsedPercentage, strRAMPercentage);
|
---|
342 |
|
---|
343 | /* Network rate: */
|
---|
344 | quint64 uPrevDownTotal = m_uNetworkDownTotal;
|
---|
345 | quint64 uPrevUpTotal = m_uNetworkUpTotal;
|
---|
346 | UIMonitorCommon::getNetworkLoad(m_comDebugger, m_uNetworkDownTotal, m_uNetworkUpTotal);
|
---|
347 | quint64 uNetworkDownRate = m_uNetworkDownTotal - uPrevDownTotal;
|
---|
348 | quint64 uNetworkUpRate = m_uNetworkUpTotal - uPrevUpTotal;
|
---|
349 |
|
---|
350 | updateCellText(VMActivityOverviewColumn_NetworkUpRate, QString("%1").arg(UITranslator::formatSize(uNetworkUpRate, iDecimalCount)));
|
---|
351 | updateCellText(VMActivityOverviewColumn_NetworkDownRate,QString("%1").arg(UITranslator::formatSize(uNetworkDownRate, iDecimalCount)));
|
---|
352 | updateCellText(VMActivityOverviewColumn_NetworkUpTotal, QString("%1").arg(UITranslator::formatSize(m_uNetworkUpTotal, iDecimalCount)));
|
---|
353 | updateCellText(VMActivityOverviewColumn_NetworkDownTotal, QString("%1").arg(UITranslator::formatSize(m_uNetworkDownTotal, iDecimalCount)));
|
---|
354 |
|
---|
355 | /* IO rate: */
|
---|
356 | quint64 uPrevWriteTotal = m_uDiskWriteTotal;
|
---|
357 | quint64 uPrevReadTotal = m_uDiskReadTotal;
|
---|
358 | UIMonitorCommon::getDiskLoad(m_comDebugger, m_uDiskWriteTotal, m_uDiskReadTotal);
|
---|
359 | quint64 uDiskWriteRate = m_uDiskWriteTotal - uPrevWriteTotal;
|
---|
360 | quint64 uDiskReadRate = m_uDiskReadTotal - uPrevReadTotal;
|
---|
361 | updateCellText(VMActivityOverviewColumn_DiskIOReadRate,QString("%1").arg(UITranslator::formatSize(uDiskReadRate, iDecimalCount)));
|
---|
362 | updateCellText(VMActivityOverviewColumn_DiskIOWriteRate,QString("%1").arg(UITranslator::formatSize(uDiskWriteRate, iDecimalCount)));
|
---|
363 | updateCellText(VMActivityOverviewColumn_DiskIOReadTotal, QString("%1").arg(UITranslator::formatSize(m_uDiskReadTotal, iDecimalCount)));
|
---|
364 | updateCellText(VMActivityOverviewColumn_DiskIOWriteTotal, QString("%1").arg(UITranslator::formatSize(m_uDiskWriteTotal, iDecimalCount)));
|
---|
365 |
|
---|
366 | /* VM Exits: */
|
---|
367 | quint64 uPrevVMExitsTotal = m_uVMExitTotal;
|
---|
368 | UIMonitorCommon::getVMMExitCount(m_comDebugger, m_uVMExitTotal);
|
---|
369 | quint64 uVMExitRate = m_uVMExitTotal - uPrevVMExitsTotal;
|
---|
370 | updateCellText(VMActivityOverviewColumn_VMExits, QString("%1/%2").arg(UITranslator::addMetricSuffixToNumber(uVMExitRate)).
|
---|
371 | arg(UITranslator::addMetricSuffixToNumber(m_uVMExitTotal)));
|
---|
372 | }
|
---|
373 |
|
---|
374 | UIVMActivityOverviewRowLocal::~UIVMActivityOverviewRowLocal()
|
---|
375 | {
|
---|
376 | if (!m_comSession.isNull())
|
---|
377 | m_comSession.UnlockMachine();
|
---|
378 | }
|
---|
379 |
|
---|
380 | void UIVMActivityOverviewRowLocal::resetDebugger()
|
---|
381 | {
|
---|
382 | m_comSession = openSession(m_uMachineId, KLockType_Shared);
|
---|
383 | if (!m_comSession.isNull())
|
---|
384 | {
|
---|
385 | CConsole comConsole = m_comSession.GetConsole();
|
---|
386 | if (!comConsole.isNull())
|
---|
387 | {
|
---|
388 | m_comGuest = comConsole.GetGuest();
|
---|
389 | m_comDebugger = comConsole.GetDebugger();
|
---|
390 | }
|
---|
391 | }
|
---|
392 | }
|
---|
393 |
|
---|
394 | void UIVMActivityOverviewRowLocal::setMachineState(int iState)
|
---|
395 | {
|
---|
396 | if (iState <= KMachineState_Null || iState >= KMachineState_Max)
|
---|
397 | return;
|
---|
398 | KMachineState enmState = static_cast<KMachineState>(iState);
|
---|
399 | if (m_enmMachineState == enmState)
|
---|
400 | return;
|
---|
401 | m_enmMachineState = enmState;
|
---|
402 | if (m_enmMachineState == KMachineState_Running)
|
---|
403 | resetDebugger();
|
---|
404 | }
|
---|
405 |
|
---|
406 | bool UIVMActivityOverviewRowLocal::isRunning() const
|
---|
407 | {
|
---|
408 | return m_enmMachineState == KMachineState_Running;
|
---|
409 | }
|
---|
410 |
|
---|
411 | bool UIVMActivityOverviewRowLocal::isCloudVM() const
|
---|
412 | {
|
---|
413 | return false;
|
---|
414 | }
|
---|
415 |
|
---|
416 | bool UIVMActivityOverviewRowLocal::isWithGuestAdditions()
|
---|
417 | {
|
---|
418 | if (m_comGuest.isNull())
|
---|
419 | return false;
|
---|
420 | return m_comGuest.GetAdditionsStatus(m_comGuest.GetAdditionsRunLevel());
|
---|
421 | }
|
---|
422 |
|
---|
423 | void UIVMActivityOverviewRowLocal::setTotalRAM(quint64 uTotalRAM)
|
---|
424 | {
|
---|
425 | m_uTotalRAM = uTotalRAM;
|
---|
426 | }
|
---|
427 |
|
---|
428 | void UIVMActivityOverviewRowLocal::setFreeRAM(quint64 uFreeRAM)
|
---|
429 | {
|
---|
430 | m_uFreeRAM = uFreeRAM;
|
---|
431 | }
|
---|
432 |
|
---|
433 | QString UIVMActivityOverviewRowLocal::machineStateString() const
|
---|
434 | {
|
---|
435 | return gpConverter->toString(m_enmMachineState);
|
---|
436 | }
|
---|
437 |
|
---|
438 | /*********************************************************************************************************************************
|
---|
439 | * UIVMActivityOverviewRowCloud implementation. *
|
---|
440 | *********************************************************************************************************************************/
|
---|
441 |
|
---|
442 | UIVMActivityOverviewRowCloud::UIVMActivityOverviewRowCloud(QITableView *pTableView, const QUuid &uMachineId,
|
---|
443 | const QString &strMachineName, CCloudMachine &comCloudMachine)
|
---|
444 | : UIVMActivityOverviewRow(pTableView, uMachineId, strMachineName)
|
---|
445 | , m_comCloudMachine(comCloudMachine)
|
---|
446 | {
|
---|
447 | updateMachineState();
|
---|
448 | m_pTimer = new QTimer(this);
|
---|
449 | if (m_pTimer)
|
---|
450 | {
|
---|
451 | connect(m_pTimer, &QTimer::timeout, this, &UIVMActivityOverviewRowCloud::sltTimeout);
|
---|
452 | m_pTimer->setInterval(60 * 1000);
|
---|
453 | }
|
---|
454 | resetColumData();
|
---|
455 | }
|
---|
456 |
|
---|
457 | void UIVMActivityOverviewRowCloud::updateMachineState()
|
---|
458 | {
|
---|
459 | if (m_comCloudMachine.isOk())
|
---|
460 | setMachineState(m_comCloudMachine.GetState());
|
---|
461 | }
|
---|
462 |
|
---|
463 | bool UIVMActivityOverviewRowCloud::isRunning() const
|
---|
464 | {
|
---|
465 | return m_enmMachineState == KCloudMachineState_Running;
|
---|
466 | }
|
---|
467 |
|
---|
468 | bool UIVMActivityOverviewRowCloud::isCloudVM() const
|
---|
469 | {
|
---|
470 | return true;
|
---|
471 | }
|
---|
472 |
|
---|
473 | QString UIVMActivityOverviewRowCloud::machineStateString() const
|
---|
474 | {
|
---|
475 | if (!m_comCloudMachine.isOk())
|
---|
476 | return QString();
|
---|
477 | return gpConverter->toString(m_comCloudMachine.GetState());
|
---|
478 | }
|
---|
479 |
|
---|
480 | void UIVMActivityOverviewRowCloud::sltTimeout()
|
---|
481 | {
|
---|
482 | int iDataSize = 1;
|
---|
483 | foreach (const KMetricType &enmMetricType, m_availableMetricTypes)
|
---|
484 | {
|
---|
485 | UIProgressTaskReadCloudMachineMetricData *pTask = new UIProgressTaskReadCloudMachineMetricData(this, m_comCloudMachine,
|
---|
486 | enmMetricType, iDataSize);
|
---|
487 | connect(pTask, &UIProgressTaskReadCloudMachineMetricData::sigMetricDataReceived,
|
---|
488 | this, &UIVMActivityOverviewRowCloud::sltMetricDataReceived);
|
---|
489 | pTask->start();
|
---|
490 | }
|
---|
491 | }
|
---|
492 |
|
---|
493 | void UIVMActivityOverviewRowCloud::sltMetricDataReceived(KMetricType enmMetricType,
|
---|
494 | const QVector<QString> &data, const QVector<QString> &timeStamps)
|
---|
495 | {
|
---|
496 | Q_UNUSED(timeStamps);
|
---|
497 | if (data.isEmpty())
|
---|
498 | return;
|
---|
499 |
|
---|
500 | if (data[0].toFloat() < 0)
|
---|
501 | return;
|
---|
502 |
|
---|
503 | int iDecimalCount = 2;
|
---|
504 | QLocale locale;
|
---|
505 | if (enmMetricType == KMetricType_CpuUtilization)
|
---|
506 | {
|
---|
507 | updateCellText(VMActivityOverviewColumn_CPUGuestLoad, QString("%1%").arg(locale.toString(data[0].toFloat(), 'f', iDecimalCount)));
|
---|
508 | }
|
---|
509 | else if (enmMetricType == KMetricType_MemoryUtilization)
|
---|
510 | {
|
---|
511 | if (m_uTotalRAM != 0)
|
---|
512 | {
|
---|
513 | quint64 uUsedRAM = (quint64)data[0].toFloat() * (m_uTotalRAM / 100.f);
|
---|
514 | updateCellText(VMActivityOverviewColumn_RAMUsedAndTotal,
|
---|
515 | QString("%1/%2").arg(UITranslator::formatSize(_1K * uUsedRAM, iDecimalCount)).
|
---|
516 | arg(UITranslator::formatSize(_1K * m_uTotalRAM, iDecimalCount)));
|
---|
517 | }
|
---|
518 | updateCellText(VMActivityOverviewColumn_RAMUsedPercentage,
|
---|
519 | QString("%1%").arg(QString::number(data[0].toFloat(), 'f', iDecimalCount)));
|
---|
520 | }
|
---|
521 | else if (enmMetricType == KMetricType_NetworksBytesOut)
|
---|
522 | updateCellText(VMActivityOverviewColumn_NetworkUpRate,
|
---|
523 | UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount));
|
---|
524 | else if (enmMetricType == KMetricType_NetworksBytesIn)
|
---|
525 | updateCellText(VMActivityOverviewColumn_NetworkDownRate,
|
---|
526 | UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount));
|
---|
527 | else if (enmMetricType == KMetricType_DiskBytesRead)
|
---|
528 | updateCellText(VMActivityOverviewColumn_DiskIOReadRate,
|
---|
529 | UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount));
|
---|
530 | else if (enmMetricType == KMetricType_DiskBytesWritten)
|
---|
531 | updateCellText(VMActivityOverviewColumn_DiskIOWriteRate,
|
---|
532 | UITranslator::formatSize((quint64)data[0].toFloat(), iDecimalCount));
|
---|
533 |
|
---|
534 | sender()->deleteLater();
|
---|
535 | }
|
---|
536 |
|
---|
537 | void UIVMActivityOverviewRowCloud::setMachineState(int iState)
|
---|
538 | {
|
---|
539 | if (iState <= KCloudMachineState_Invalid || iState >= KCloudMachineState_Max)
|
---|
540 | return;
|
---|
541 | KCloudMachineState enmState = static_cast<KCloudMachineState>(iState);
|
---|
542 | if (m_enmMachineState == enmState)
|
---|
543 | return;
|
---|
544 | m_enmMachineState = enmState;
|
---|
545 | if (isRunning())
|
---|
546 | {
|
---|
547 | getMetricList();
|
---|
548 | if (m_uTotalRAM == 0)
|
---|
549 | m_uTotalRAM = UIMonitorCommon::determineTotalRAMAmount(m_comCloudMachine);
|
---|
550 | }
|
---|
551 | else
|
---|
552 | {
|
---|
553 | if (m_pTimer)
|
---|
554 | m_pTimer->stop();
|
---|
555 | }
|
---|
556 | }
|
---|
557 |
|
---|
558 | void UIVMActivityOverviewRowCloud::resetColumData()
|
---|
559 | {
|
---|
560 | for (int i = (int) VMActivityOverviewColumn_CPUGuestLoad;
|
---|
561 | i < (int)VMActivityOverviewColumn_Max; ++i)
|
---|
562 | updateCellText(i, QApplication::translate("UIVMActivityOverviewWidget", "N/A"));
|
---|
563 | }
|
---|
564 |
|
---|
565 | void UIVMActivityOverviewRowCloud::getMetricList()
|
---|
566 | {
|
---|
567 | if (!isRunning())
|
---|
568 | return;
|
---|
569 | UIProgressTaskReadCloudMachineMetricList *pReadListProgressTask =
|
---|
570 | new UIProgressTaskReadCloudMachineMetricList(this, m_comCloudMachine);
|
---|
571 | AssertPtrReturnVoid(pReadListProgressTask);
|
---|
572 | connect(pReadListProgressTask, &UIProgressTaskReadCloudMachineMetricList::sigMetricListReceived,
|
---|
573 | this, &UIVMActivityOverviewRowCloud::sltMetricNameListingComplete);
|
---|
574 | pReadListProgressTask->start();
|
---|
575 | }
|
---|
576 |
|
---|
577 | void UIVMActivityOverviewRowCloud::sltMetricNameListingComplete(QVector<QString> metricNameList)
|
---|
578 | {
|
---|
579 | AssertReturnVoid(m_pTimer);
|
---|
580 | m_availableMetricTypes.clear();
|
---|
581 | foreach (const QString &strName, metricNameList)
|
---|
582 | m_availableMetricTypes << gpConverter->fromInternalString<KMetricType>(strName);
|
---|
583 |
|
---|
584 | if (!m_availableMetricTypes.isEmpty())
|
---|
585 | {
|
---|
586 | /* Dont wait 60 secs: */
|
---|
587 | sltTimeout();
|
---|
588 | m_pTimer->start();
|
---|
589 | }
|
---|
590 | else
|
---|
591 | {
|
---|
592 | m_pTimer->stop();
|
---|
593 | resetColumData();
|
---|
594 | }
|
---|
595 |
|
---|
596 | if (sender())
|
---|
597 | sender()->deleteLater();
|
---|
598 |
|
---|
599 | }
|
---|
600 |
|
---|
601 |
|
---|
602 | /*********************************************************************************************************************************
|
---|
603 | * UIVMActivityOverviewTableView implementation. *
|
---|
604 | *********************************************************************************************************************************/
|
---|
605 |
|
---|
606 | UIVMActivityOverviewTableView::UIVMActivityOverviewTableView(QWidget *pParent)
|
---|
607 | : QITableView(pParent)
|
---|
608 | {
|
---|
609 | }
|
---|
610 |
|
---|
611 | void UIVMActivityOverviewTableView::updateColumVisibility()
|
---|
612 | {
|
---|
613 | UIVMActivityOverviewProxyModel *pProxyModel = qobject_cast<UIVMActivityOverviewProxyModel*>(model());
|
---|
614 | if (!pProxyModel)
|
---|
615 | return;
|
---|
616 | UIVMActivityOverviewModel *pModel = qobject_cast<UIVMActivityOverviewModel*>(pProxyModel->sourceModel());
|
---|
617 | QHeaderView *pHeader = horizontalHeader();
|
---|
618 |
|
---|
619 | if (!pModel || !pHeader)
|
---|
620 | return;
|
---|
621 | for (int i = (int)VMActivityOverviewColumn_Name; i < (int)VMActivityOverviewColumn_Max; ++i)
|
---|
622 | {
|
---|
623 | if (!pModel->columnVisible(i))
|
---|
624 | pHeader->hideSection(i);
|
---|
625 | else
|
---|
626 | pHeader->showSection(i);
|
---|
627 | }
|
---|
628 | resizeHeaders();
|
---|
629 | }
|
---|
630 |
|
---|
631 | int UIVMActivityOverviewTableView::selectedItemIndex() const
|
---|
632 | {
|
---|
633 | UIVMActivityOverviewProxyModel *pModel = qobject_cast<UIVMActivityOverviewProxyModel*>(model());
|
---|
634 | if (!pModel)
|
---|
635 | return -1;
|
---|
636 |
|
---|
637 | QItemSelectionModel *pSelectionModel = selectionModel();
|
---|
638 | if (!pSelectionModel)
|
---|
639 | return -1;
|
---|
640 | QModelIndexList selectedItemIndices = pSelectionModel->selectedRows();
|
---|
641 | if (selectedItemIndices.isEmpty())
|
---|
642 | return -1;
|
---|
643 |
|
---|
644 | /* just use the the 1st index: */
|
---|
645 | QModelIndex modelIndex = pModel->mapToSource(selectedItemIndices[0]);
|
---|
646 |
|
---|
647 | if (!modelIndex.isValid())
|
---|
648 | return -1;
|
---|
649 | return modelIndex.row();
|
---|
650 | }
|
---|
651 |
|
---|
652 | bool UIVMActivityOverviewTableView::hasSelection() const
|
---|
653 | {
|
---|
654 | if (!selectionModel())
|
---|
655 | return false;
|
---|
656 | return selectionModel()->hasSelection();
|
---|
657 | }
|
---|
658 |
|
---|
659 | void UIVMActivityOverviewTableView::setMinimumColumnWidths(const QMap<int, int>& widths)
|
---|
660 | {
|
---|
661 | m_minimumColumnWidths = widths;
|
---|
662 | resizeHeaders();
|
---|
663 | }
|
---|
664 |
|
---|
665 | void UIVMActivityOverviewTableView::resizeEvent(QResizeEvent *pEvent)
|
---|
666 | {
|
---|
667 | resizeHeaders();
|
---|
668 | QTableView::resizeEvent(pEvent);
|
---|
669 | }
|
---|
670 |
|
---|
671 | void UIVMActivityOverviewTableView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
---|
672 | {
|
---|
673 | emit sigSelectionChanged(selected, deselected);
|
---|
674 | QTableView::selectionChanged(selected, deselected);
|
---|
675 | }
|
---|
676 |
|
---|
677 | void UIVMActivityOverviewTableView::mousePressEvent(QMouseEvent *pEvent)
|
---|
678 | {
|
---|
679 | if (!indexAt(pEvent->position().toPoint()).isValid())
|
---|
680 | clearSelection();
|
---|
681 | QTableView::mousePressEvent(pEvent);
|
---|
682 | }
|
---|
683 |
|
---|
684 | void UIVMActivityOverviewTableView::resizeHeaders()
|
---|
685 | {
|
---|
686 | QHeaderView* pHeader = horizontalHeader();
|
---|
687 | if (!pHeader || pHeader->count() <= 0)
|
---|
688 | return;
|
---|
689 | int iSectionCount = pHeader->count();
|
---|
690 | int iHiddenSectionCount = pHeader->hiddenSectionCount();
|
---|
691 | if (iSectionCount == iHiddenSectionCount)
|
---|
692 | return;
|
---|
693 | int iWidth = width() / (iSectionCount - iHiddenSectionCount);
|
---|
694 | for (int i = 0; i < iSectionCount; ++i)
|
---|
695 | {
|
---|
696 | if (pHeader->isSectionHidden(i))
|
---|
697 | continue;
|
---|
698 | int iMinWidth = m_minimumColumnWidths.value((VMActivityOverviewColumn)i, 0);
|
---|
699 | pHeader->resizeSection(i, iWidth < iMinWidth ? iMinWidth : iWidth);
|
---|
700 | }
|
---|
701 | }
|
---|
702 |
|
---|
703 | /*********************************************************************************************************************************
|
---|
704 | * UIVMActivityOverviewModel implementation. *
|
---|
705 | *********************************************************************************************************************************/
|
---|
706 |
|
---|
707 | UIVMActivityOverviewModel::UIVMActivityOverviewModel(QObject *pParent, QITableView *pView)
|
---|
708 | :QAbstractTableModel(pParent)
|
---|
709 | , m_pTableView(pView)
|
---|
710 | , m_pLocalVMUpdateTimer(new QTimer(this))
|
---|
711 | {
|
---|
712 | initialize();
|
---|
713 | }
|
---|
714 |
|
---|
715 | void UIVMActivityOverviewModel::setCloudMachineItems(const QList<UIVirtualMachineItemCloud*> &cloudItems)
|
---|
716 | {
|
---|
717 | QVector<QUuid> newIds;
|
---|
718 | foreach (const UIVirtualMachineItemCloud* pItem, cloudItems)
|
---|
719 | {
|
---|
720 | if (!pItem)
|
---|
721 | continue;
|
---|
722 | QUuid id = pItem->machineId();
|
---|
723 | if (id.isNull())
|
---|
724 | continue;
|
---|
725 | newIds << id;
|
---|
726 | }
|
---|
727 | QVector<UIVMActivityOverviewRow*> originalItemList = m_rows;
|
---|
728 |
|
---|
729 | /* Remove m_rows items that are not in @cloudItems: */
|
---|
730 | QMutableVectorIterator<UIVMActivityOverviewRow*> iterator(m_rows);
|
---|
731 | while (iterator.hasNext())
|
---|
732 | {
|
---|
733 | UIVMActivityOverviewRow *pItem = iterator.next();
|
---|
734 | if (!pItem->isCloudVM())
|
---|
735 | continue;
|
---|
736 | if (pItem && !newIds.contains(pItem->machineId()))
|
---|
737 | iterator.remove();
|
---|
738 | }
|
---|
739 |
|
---|
740 | /* Add items that are not in m_rows: */
|
---|
741 | foreach (const UIVirtualMachineItemCloud* pItem, cloudItems)
|
---|
742 | {
|
---|
743 | if (!pItem)
|
---|
744 | continue;
|
---|
745 | CCloudMachine comMachine = pItem->machine();
|
---|
746 | if (!comMachine.isOk())
|
---|
747 | continue;
|
---|
748 | QUuid id = comMachine.GetId();
|
---|
749 | /* Linearly search for the vm with th same id. I cannot make QVector::contain work since we store pointers: */
|
---|
750 | bool fFound = false;
|
---|
751 | for (int i = 0; i < m_rows.size() && !fFound; ++i)
|
---|
752 | {
|
---|
753 | if (m_rows[i] && m_rows[i]->machineId() == id)
|
---|
754 | fFound = true;
|
---|
755 | }
|
---|
756 | if (!fFound)
|
---|
757 | m_rows.append(new UIVMActivityOverviewRowCloud(m_pTableView, id, comMachine.GetName(), comMachine));
|
---|
758 | }
|
---|
759 |
|
---|
760 | /* Update cloud machine states: */
|
---|
761 | for (int i = 0; i < m_rows.size(); ++i)
|
---|
762 | {
|
---|
763 | if (!m_rows[i] || !m_rows[i]->isCloudVM())
|
---|
764 | continue;
|
---|
765 | UIVMActivityOverviewRowCloud *pItem = qobject_cast<UIVMActivityOverviewRowCloud*>(m_rows[i]);
|
---|
766 | if (!pItem)
|
---|
767 | continue;
|
---|
768 | pItem->updateMachineState();
|
---|
769 | }
|
---|
770 | }
|
---|
771 |
|
---|
772 | void UIVMActivityOverviewModel::setColumnVisible(const QMap<int, bool>& columnVisible)
|
---|
773 | {
|
---|
774 | m_columnVisible = columnVisible;
|
---|
775 | }
|
---|
776 |
|
---|
777 | bool UIVMActivityOverviewModel::columnVisible(int iColumnId) const
|
---|
778 | {
|
---|
779 | return m_columnVisible.value(iColumnId, true);
|
---|
780 | }
|
---|
781 |
|
---|
782 |
|
---|
783 | bool UIVMActivityOverviewModel::isVMRunning(int rowIndex) const
|
---|
784 | {
|
---|
785 | if (rowIndex >= m_rows.size() || rowIndex < 0 || !m_rows[rowIndex])
|
---|
786 | return false;
|
---|
787 | return m_rows[rowIndex]->isRunning();
|
---|
788 | }
|
---|
789 |
|
---|
790 | bool UIVMActivityOverviewModel::isCloudVM(int rowIndex) const
|
---|
791 | {
|
---|
792 | if (rowIndex >= m_rows.size() || rowIndex < 0 || !m_rows[rowIndex])
|
---|
793 | return false;
|
---|
794 | return m_rows[rowIndex]->isCloudVM();
|
---|
795 | }
|
---|
796 |
|
---|
797 | void UIVMActivityOverviewModel::setupPerformanceCollector()
|
---|
798 | {
|
---|
799 | m_nameList.clear();
|
---|
800 | m_objectList.clear();
|
---|
801 | /* Initialize and configure CPerformanceCollector: */
|
---|
802 | const ULONG iPeriod = 1;
|
---|
803 | const int iMetricSetupCount = 1;
|
---|
804 | if (m_performanceCollector.isNull())
|
---|
805 | m_performanceCollector = gpGlobalSession->virtualBox().GetPerformanceCollector();
|
---|
806 | for (int i = 0; i < m_rows.size(); ++i)
|
---|
807 | m_nameList << "Guest/RAM/Usage*";
|
---|
808 | /* This is for the host: */
|
---|
809 | m_nameList << "CPU*";
|
---|
810 | m_nameList << "FS*";
|
---|
811 | m_objectList = QVector<CUnknown>(m_nameList.size(), CUnknown());
|
---|
812 | m_performanceCollector.SetupMetrics(m_nameList, m_objectList, iPeriod, iMetricSetupCount);
|
---|
813 | }
|
---|
814 |
|
---|
815 | void UIVMActivityOverviewModel::clearData()
|
---|
816 | {
|
---|
817 | /* We have a request to detach COM stuff,
|
---|
818 | * first of all we are removing all the items,
|
---|
819 | * this will detach COM wrappers implicitly: */
|
---|
820 | qDeleteAll(m_rows);
|
---|
821 | m_rows.clear();
|
---|
822 | /* Detaching perf. collector finally,
|
---|
823 | * please do not use it after all: */
|
---|
824 | m_performanceCollector.detach();
|
---|
825 | }
|
---|
826 |
|
---|
827 | UIVMActivityOverviewModel::~UIVMActivityOverviewModel()
|
---|
828 | {
|
---|
829 | clearData();
|
---|
830 | }
|
---|
831 |
|
---|
832 | void UIVMActivityOverviewModel::setShouldUpdate(bool fShouldUpdate)
|
---|
833 | {
|
---|
834 | if (m_pLocalVMUpdateTimer)
|
---|
835 | {
|
---|
836 | if (fShouldUpdate)
|
---|
837 | m_pLocalVMUpdateTimer->start();
|
---|
838 | else
|
---|
839 | m_pLocalVMUpdateTimer->stop();
|
---|
840 | }
|
---|
841 | }
|
---|
842 |
|
---|
843 | QModelIndex UIVMActivityOverviewModel::index(int iRow, int iColumn, const QModelIndex &parentIdx /* = QModelIndex() */) const
|
---|
844 | {
|
---|
845 | /* No index for unknown items: */
|
---|
846 | if (!hasIndex(iRow, iColumn, parentIdx))
|
---|
847 | return QModelIndex();
|
---|
848 |
|
---|
849 | /* Provide index users with packed item pointer: */
|
---|
850 | UIVMActivityOverviewRow *pItem = iRow >= 0 && iRow < m_rows.size() ? m_rows.at(iRow) : 0;
|
---|
851 | return pItem ? createIndex(iRow, iColumn, pItem) : QModelIndex();
|
---|
852 | }
|
---|
853 |
|
---|
854 | int UIVMActivityOverviewModel::rowCount(const QModelIndex &parent) const
|
---|
855 | {
|
---|
856 | Q_UNUSED(parent);
|
---|
857 | return m_rows.size();
|
---|
858 | }
|
---|
859 |
|
---|
860 | int UIVMActivityOverviewModel::columnCount(const QModelIndex &parent) const
|
---|
861 | {
|
---|
862 | Q_UNUSED(parent);
|
---|
863 | if (m_rows.isEmpty())
|
---|
864 | return 0;
|
---|
865 | if (m_rows[0])
|
---|
866 | return m_rows[0]->childCount();
|
---|
867 | return 0;
|
---|
868 | }
|
---|
869 |
|
---|
870 | QVariant UIVMActivityOverviewModel::data(const QModelIndex &index, int role) const
|
---|
871 | {
|
---|
872 | int iRow = index.row();
|
---|
873 | if (iRow < 0 || iRow >= m_rows.size())
|
---|
874 | return QVariant();
|
---|
875 | if (!m_rows[iRow])
|
---|
876 | return QVariant();
|
---|
877 |
|
---|
878 | if (role == Qt::DisplayRole)
|
---|
879 | {
|
---|
880 | return m_rows[iRow]->cellText(index.column());
|
---|
881 |
|
---|
882 | }
|
---|
883 | return QVariant();
|
---|
884 | }
|
---|
885 |
|
---|
886 | const QMap<int, int> UIVMActivityOverviewModel::dataLengths() const
|
---|
887 | {
|
---|
888 | return m_columnDataMaxLength;
|
---|
889 | }
|
---|
890 |
|
---|
891 | void UIVMActivityOverviewModel::initialize()
|
---|
892 | {
|
---|
893 | for (int i = 0; i < (int)VMActivityOverviewColumn_Max; ++i)
|
---|
894 | m_columnDataMaxLength[i] = 0;
|
---|
895 |
|
---|
896 | if (m_pLocalVMUpdateTimer)
|
---|
897 | {
|
---|
898 | connect(m_pLocalVMUpdateTimer, &QTimer::timeout, this, &UIVMActivityOverviewModel::sltLocalVMUpdateTimeout);
|
---|
899 | m_pLocalVMUpdateTimer->start(1000);
|
---|
900 | }
|
---|
901 |
|
---|
902 | connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange,
|
---|
903 | this, &UIVMActivityOverviewModel::sltMachineStateChanged);
|
---|
904 | connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineRegistered,
|
---|
905 | this, &UIVMActivityOverviewModel::sltMachineRegistered);
|
---|
906 | foreach (const CMachine &comMachine, gpGlobalSession->virtualBox().GetMachines())
|
---|
907 | {
|
---|
908 | if (!comMachine.isNull())
|
---|
909 | addRow(comMachine.GetId(), comMachine.GetName(), comMachine.GetState());
|
---|
910 | }
|
---|
911 | setupPerformanceCollector();
|
---|
912 | }
|
---|
913 |
|
---|
914 | void UIVMActivityOverviewModel::addRow(const QUuid& uMachineId, const QString& strMachineName, KMachineState enmState)
|
---|
915 | {
|
---|
916 | //QVector<UIVMActivityOverviewRow*> m_rows;
|
---|
917 | m_rows << new UIVMActivityOverviewRowLocal(m_pTableView, uMachineId, strMachineName, enmState);
|
---|
918 | }
|
---|
919 |
|
---|
920 | QVariant UIVMActivityOverviewModel::headerData(int section, Qt::Orientation orientation, int role) const
|
---|
921 | {
|
---|
922 | if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
---|
923 | return m_columnTitles.value((VMActivityOverviewColumn)section, QString());;
|
---|
924 | return QVariant();
|
---|
925 | }
|
---|
926 |
|
---|
927 | void UIVMActivityOverviewModel::setColumnCaptions(const QMap<int, QString>& captions)
|
---|
928 | {
|
---|
929 | m_columnTitles = captions;
|
---|
930 | }
|
---|
931 |
|
---|
932 |
|
---|
933 | void UIVMActivityOverviewModel::sltMachineStateChanged(const QUuid &uId, const KMachineState state)
|
---|
934 | {
|
---|
935 | int iIndex = itemIndex(uId);
|
---|
936 | if (iIndex != -1 && iIndex < m_rows.size())
|
---|
937 | {
|
---|
938 | UIVMActivityOverviewRowLocal *pItem = qobject_cast<UIVMActivityOverviewRowLocal*>(m_rows[iIndex]);
|
---|
939 | if (pItem)
|
---|
940 | {
|
---|
941 | pItem->setMachineState(state);
|
---|
942 | if (state == KMachineState_Running)
|
---|
943 | pItem->resetDebugger();
|
---|
944 | }
|
---|
945 | }
|
---|
946 | }
|
---|
947 |
|
---|
948 | void UIVMActivityOverviewModel::sltMachineRegistered(const QUuid &uId, bool fRegistered)
|
---|
949 | {
|
---|
950 | if (fRegistered)
|
---|
951 | {
|
---|
952 | CMachine comMachine = gpGlobalSession->virtualBox().FindMachine(uId.toString());
|
---|
953 | if (!comMachine.isNull())
|
---|
954 | addRow(uId, comMachine.GetName(), comMachine.GetState());
|
---|
955 | }
|
---|
956 | else
|
---|
957 | removeRow(uId);
|
---|
958 | emit sigDataUpdate();
|
---|
959 | }
|
---|
960 |
|
---|
961 | void UIVMActivityOverviewModel::getHostRAMStats()
|
---|
962 | {
|
---|
963 | CHost comHost = gpGlobalSession->host();
|
---|
964 | m_hostStats.m_iRAMTotal = _1M * (quint64)comHost.GetMemorySize();
|
---|
965 | m_hostStats.m_iRAMFree = _1M * (quint64)comHost.GetMemoryAvailable();
|
---|
966 | }
|
---|
967 |
|
---|
968 | void UIVMActivityOverviewModel::sltLocalVMUpdateTimeout()
|
---|
969 | {
|
---|
970 | /* Host's RAM usage is obtained from IHost not from IPerformanceCollector: */
|
---|
971 | getHostRAMStats();
|
---|
972 |
|
---|
973 | /* Use IPerformanceCollector to update VM RAM usage and Host CPU and file IO stats: */
|
---|
974 | queryPerformanceCollector();
|
---|
975 |
|
---|
976 | for (int i = 0; i < m_rows.size(); ++i)
|
---|
977 | {
|
---|
978 | UIVMActivityOverviewRowLocal *pItem = qobject_cast<UIVMActivityOverviewRowLocal*>(m_rows[i]);
|
---|
979 | if (!pItem || !pItem->isRunning())
|
---|
980 | continue;
|
---|
981 | pItem->updateCells();
|
---|
982 | }
|
---|
983 |
|
---|
984 | for (int i = 0; i < (int)VMActivityOverviewColumn_Max; ++i)
|
---|
985 | {
|
---|
986 | for (int j = 0; j < m_rows.size(); ++j)
|
---|
987 | if (m_columnDataMaxLength.value(i, 0) < m_rows[j]->columnLength(i))
|
---|
988 | m_columnDataMaxLength[i] = m_rows[j]->columnLength(i);
|
---|
989 | }
|
---|
990 |
|
---|
991 | emit sigDataUpdate();
|
---|
992 | emit sigHostStatsUpdate(m_hostStats);
|
---|
993 | }
|
---|
994 |
|
---|
995 | int UIVMActivityOverviewModel::itemIndex(const QUuid &uid)
|
---|
996 | {
|
---|
997 | for (int i = 0; i < m_rows.size(); ++i)
|
---|
998 | {
|
---|
999 | if (!m_rows[i])
|
---|
1000 | continue;
|
---|
1001 | if (m_rows[i]->machineId() == uid)
|
---|
1002 | return i;
|
---|
1003 | }
|
---|
1004 | return -1;
|
---|
1005 | }
|
---|
1006 |
|
---|
1007 | QUuid UIVMActivityOverviewModel::itemUid(int iIndex)
|
---|
1008 | {
|
---|
1009 | if (iIndex >= m_rows.size() || !m_rows[iIndex])
|
---|
1010 | return QUuid();
|
---|
1011 | return m_rows[iIndex]->machineId();
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | void UIVMActivityOverviewModel::removeRow(const QUuid& uMachineId)
|
---|
1015 | {
|
---|
1016 | int iIndex = itemIndex(uMachineId);
|
---|
1017 | if (iIndex == -1)
|
---|
1018 | return;
|
---|
1019 | delete m_rows[iIndex];
|
---|
1020 | m_rows.remove(iIndex);
|
---|
1021 | }
|
---|
1022 |
|
---|
1023 | void UIVMActivityOverviewModel::queryPerformanceCollector()
|
---|
1024 | {
|
---|
1025 | QVector<QString> aReturnNames;
|
---|
1026 | QVector<CUnknown> aReturnObjects;
|
---|
1027 | QVector<QString> aReturnUnits;
|
---|
1028 | QVector<ULONG> aReturnScales;
|
---|
1029 | QVector<ULONG> aReturnSequenceNumbers;
|
---|
1030 | QVector<ULONG> aReturnDataIndices;
|
---|
1031 | QVector<ULONG> aReturnDataLengths;
|
---|
1032 |
|
---|
1033 | QVector<LONG> returnData = m_performanceCollector.QueryMetricsData(m_nameList,
|
---|
1034 | m_objectList,
|
---|
1035 | aReturnNames,
|
---|
1036 | aReturnObjects,
|
---|
1037 | aReturnUnits,
|
---|
1038 | aReturnScales,
|
---|
1039 | aReturnSequenceNumbers,
|
---|
1040 | aReturnDataIndices,
|
---|
1041 | aReturnDataLengths);
|
---|
1042 | /* Parse the result we get from CPerformanceCollector to get respective values: */
|
---|
1043 | for (int i = 0; i < aReturnNames.size(); ++i)
|
---|
1044 | {
|
---|
1045 | if (aReturnDataLengths[i] == 0)
|
---|
1046 | continue;
|
---|
1047 | /* Read the last of the return data disregarding the rest since we are caching the data in GUI side: */
|
---|
1048 | float fData = returnData[aReturnDataIndices[i] + aReturnDataLengths[i] - 1] / (float)aReturnScales[i];
|
---|
1049 | if (aReturnNames[i].contains("RAM", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
|
---|
1050 | {
|
---|
1051 | if (aReturnNames[i].contains("Total", Qt::CaseInsensitive) || aReturnNames[i].contains("Free", Qt::CaseInsensitive))
|
---|
1052 | {
|
---|
1053 | {
|
---|
1054 | CMachine comMachine = (CMachine)aReturnObjects[i];
|
---|
1055 | if (comMachine.isNull())
|
---|
1056 | continue;
|
---|
1057 | int iIndex = itemIndex(comMachine.GetId());
|
---|
1058 | if (iIndex == -1 || iIndex >= m_rows.size() || !m_rows[iIndex])
|
---|
1059 | continue;
|
---|
1060 |
|
---|
1061 | UIVMActivityOverviewRowLocal *pItem = qobject_cast<UIVMActivityOverviewRowLocal*>(m_rows[iIndex]);
|
---|
1062 | if (!pItem)
|
---|
1063 | continue;
|
---|
1064 | if (aReturnNames[i].contains("Total", Qt::CaseInsensitive))
|
---|
1065 | pItem->setTotalRAM((quint64)fData);
|
---|
1066 | else
|
---|
1067 | pItem->setFreeRAM((quint64)fData);
|
---|
1068 | }
|
---|
1069 | }
|
---|
1070 | }
|
---|
1071 | else if (aReturnNames[i].contains("CPU/Load/User", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
|
---|
1072 | {
|
---|
1073 | CHost comHost = (CHost)aReturnObjects[i];
|
---|
1074 | if (!comHost.isNull())
|
---|
1075 | m_hostStats.m_iCPUUserLoad = fData;
|
---|
1076 | }
|
---|
1077 | else if (aReturnNames[i].contains("CPU/Load/Kernel", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
|
---|
1078 | {
|
---|
1079 | CHost comHost = (CHost)aReturnObjects[i];
|
---|
1080 | if (!comHost.isNull())
|
---|
1081 | m_hostStats.m_iCPUKernelLoad = fData;
|
---|
1082 | }
|
---|
1083 | else if (aReturnNames[i].contains("CPU/MHz", Qt::CaseInsensitive) && !aReturnNames[i].contains(":"))
|
---|
1084 | {
|
---|
1085 | CHost comHost = (CHost)aReturnObjects[i];
|
---|
1086 | if (!comHost.isNull())
|
---|
1087 | m_hostStats.m_iCPUFreq = fData;
|
---|
1088 | }
|
---|
1089 | else if (aReturnNames[i].contains("FS", Qt::CaseInsensitive) &&
|
---|
1090 | aReturnNames[i].contains("Total", Qt::CaseInsensitive) &&
|
---|
1091 | !aReturnNames[i].contains(":"))
|
---|
1092 | {
|
---|
1093 | CHost comHost = (CHost)aReturnObjects[i];
|
---|
1094 | if (!comHost.isNull())
|
---|
1095 | m_hostStats.m_iFSTotal = _1M * fData;
|
---|
1096 | }
|
---|
1097 | else if (aReturnNames[i].contains("FS", Qt::CaseInsensitive) &&
|
---|
1098 | aReturnNames[i].contains("Free", Qt::CaseInsensitive) &&
|
---|
1099 | !aReturnNames[i].contains(":"))
|
---|
1100 | {
|
---|
1101 | CHost comHost = (CHost)aReturnObjects[i];
|
---|
1102 | if (!comHost.isNull())
|
---|
1103 | m_hostStats.m_iFSFree = _1M * fData;
|
---|
1104 | }
|
---|
1105 | }
|
---|
1106 | }
|
---|
1107 |
|
---|
1108 | /*********************************************************************************************************************************
|
---|
1109 | * UIVMActivityOverviewProxyModel implementation. *
|
---|
1110 | *********************************************************************************************************************************/
|
---|
1111 |
|
---|
1112 | UIVMActivityOverviewProxyModel::UIVMActivityOverviewProxyModel(QObject *pParent /* = 0 */)
|
---|
1113 | : QSortFilterProxyModel(pParent)
|
---|
1114 | {
|
---|
1115 | }
|
---|
1116 |
|
---|
1117 | void UIVMActivityOverviewProxyModel::dataUpdate()
|
---|
1118 | {
|
---|
1119 | if (sourceModel())
|
---|
1120 | emit dataChanged(index(0,0), index(sourceModel()->rowCount(), sourceModel()->columnCount()));
|
---|
1121 | invalidate();
|
---|
1122 | }
|
---|
1123 |
|
---|
1124 | void UIVMActivityOverviewProxyModel::setNotRunningVMVisibility(bool fShow)
|
---|
1125 | {
|
---|
1126 | if (m_fShowNotRunningVMs == fShow)
|
---|
1127 | return;
|
---|
1128 | m_fShowNotRunningVMs = fShow;
|
---|
1129 | invalidateFilter();
|
---|
1130 | }
|
---|
1131 |
|
---|
1132 |
|
---|
1133 | void UIVMActivityOverviewProxyModel::setCloudVMVisibility(bool fShow)
|
---|
1134 | {
|
---|
1135 | if (m_fShowCloudVMs == fShow)
|
---|
1136 | return;
|
---|
1137 | m_fShowCloudVMs = fShow;
|
---|
1138 | invalidateFilter();
|
---|
1139 | }
|
---|
1140 |
|
---|
1141 | bool UIVMActivityOverviewProxyModel::filterAcceptsRow(int iSourceRow, const QModelIndex &sourceParent) const
|
---|
1142 | {
|
---|
1143 | Q_UNUSED(sourceParent);
|
---|
1144 | if (m_fShowNotRunningVMs && m_fShowCloudVMs)
|
---|
1145 | return true;
|
---|
1146 | UIVMActivityOverviewModel *pModel = qobject_cast<UIVMActivityOverviewModel*>(sourceModel());
|
---|
1147 | if (!pModel)
|
---|
1148 | return true;
|
---|
1149 |
|
---|
1150 | if (!m_fShowNotRunningVMs && !pModel->isVMRunning(iSourceRow))
|
---|
1151 | return false;
|
---|
1152 | if (!m_fShowCloudVMs && pModel->isCloudVM(iSourceRow))
|
---|
1153 | return false;
|
---|
1154 | return true;
|
---|
1155 | }
|
---|
1156 |
|
---|
1157 | bool UIVMActivityOverviewProxyModel::lessThan(const QModelIndex &sourceLeftIndex, const QModelIndex &sourceRightIndex) const
|
---|
1158 | {
|
---|
1159 | UIVMActivityOverviewModel *pModel = qobject_cast<UIVMActivityOverviewModel*>(sourceModel());
|
---|
1160 | if (pModel)
|
---|
1161 | {
|
---|
1162 | /* Keep running vm always on top of the list: */
|
---|
1163 | bool fLeftRunning = pModel->isVMRunning(sourceLeftIndex.row());
|
---|
1164 | bool fRightRunning = pModel->isVMRunning(sourceRightIndex.row());
|
---|
1165 | if (fLeftRunning && !fRightRunning)
|
---|
1166 | {
|
---|
1167 | if (sortOrder() == Qt::AscendingOrder)
|
---|
1168 | return true;
|
---|
1169 | else
|
---|
1170 | return false;
|
---|
1171 | }
|
---|
1172 | if (!fLeftRunning && fRightRunning)
|
---|
1173 | {
|
---|
1174 | if (sortOrder() == Qt::AscendingOrder)
|
---|
1175 | return false;
|
---|
1176 | else
|
---|
1177 | return true;
|
---|
1178 | }
|
---|
1179 | }
|
---|
1180 | return QSortFilterProxyModel::lessThan(sourceLeftIndex, sourceRightIndex);
|
---|
1181 | }
|
---|
1182 |
|
---|
1183 |
|
---|
1184 | #include "UIVMActivityOverviewModelView.moc"
|
---|