1 | /* $Id: UIVMActivityMonitorContainer.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBox Qt GUI - UIVMLogViewer class implementation.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2010-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 <QColor>
|
---|
31 | #include <QColorDialog>
|
---|
32 | #include <QHBoxLayout>
|
---|
33 | #include <QLabel>
|
---|
34 | #include <QPainter>
|
---|
35 | #include <QPixmap>
|
---|
36 | #include <QPlainTextEdit>
|
---|
37 | #include <QPushButton>
|
---|
38 | #include <QStyle>
|
---|
39 | #include <QTabWidget>
|
---|
40 |
|
---|
41 | /* GUI includes: */
|
---|
42 | #include "UIActionPool.h"
|
---|
43 | #include "UIExtraDataManager.h"
|
---|
44 | #include "UIGlobalSession.h"
|
---|
45 | #include "UITranslationEventListener.h"
|
---|
46 | #include "UIVMActivityMonitor.h"
|
---|
47 | #include "UIVMActivityMonitorContainer.h"
|
---|
48 |
|
---|
49 | /* Other includes: */
|
---|
50 | #include "iprt/assert.h"
|
---|
51 |
|
---|
52 |
|
---|
53 | /*********************************************************************************************************************************
|
---|
54 | * UIVMActivityMonitorPaneContainer implementation. *
|
---|
55 | *********************************************************************************************************************************/
|
---|
56 |
|
---|
57 |
|
---|
58 | UIVMActivityMonitorPaneContainer::UIVMActivityMonitorPaneContainer(QWidget *pParent)
|
---|
59 | : UIPaneContainer(pParent)
|
---|
60 | , m_pColorLabel{0, 0}
|
---|
61 | , m_pColorChangeButton{0, 0}
|
---|
62 | , m_pResetButton(0)
|
---|
63 | {
|
---|
64 | setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
---|
65 | prepare();
|
---|
66 | }
|
---|
67 |
|
---|
68 | void UIVMActivityMonitorPaneContainer::prepare()
|
---|
69 | {
|
---|
70 | QWidget *pContainerWidget = new QWidget(this);
|
---|
71 | QVBoxLayout *pContainerLayout = new QVBoxLayout(pContainerWidget);
|
---|
72 | AssertReturnVoid(pContainerWidget);
|
---|
73 | AssertReturnVoid(pContainerLayout);
|
---|
74 | insertTab(Tab_Preferences, pContainerWidget, "");
|
---|
75 | pContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
---|
76 |
|
---|
77 | for (int i = 0; i < 2; ++i)
|
---|
78 | {
|
---|
79 | QHBoxLayout *pColorLayout = new QHBoxLayout;
|
---|
80 | AssertReturnVoid(pColorLayout);
|
---|
81 | m_pColorLabel[i] = new QLabel(this);
|
---|
82 | m_pColorChangeButton[i] = new QPushButton(this);
|
---|
83 | AssertReturnVoid(m_pColorLabel[i]);
|
---|
84 | AssertReturnVoid(m_pColorChangeButton[i]);
|
---|
85 | pColorLayout->addWidget(m_pColorLabel[i]);
|
---|
86 | pColorLayout->addWidget(m_pColorChangeButton[i]);
|
---|
87 | pColorLayout->addStretch();
|
---|
88 | pContainerLayout->addLayout(pColorLayout);
|
---|
89 | connect(m_pColorChangeButton[i], &QPushButton::pressed,
|
---|
90 | this, &UIVMActivityMonitorPaneContainer::sltColorChangeButtonPressed);
|
---|
91 | }
|
---|
92 | m_pResetButton = new QPushButton(this);
|
---|
93 | AssertReturnVoid(m_pResetButton);
|
---|
94 | m_pResetButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
|
---|
95 | connect(m_pResetButton, &QPushButton::pressed,
|
---|
96 | this, &UIVMActivityMonitorPaneContainer::sltResetToDefaults);
|
---|
97 |
|
---|
98 | pContainerLayout->addWidget(m_pResetButton);
|
---|
99 |
|
---|
100 | pContainerLayout->addStretch();
|
---|
101 |
|
---|
102 | sltRetranslateUI();
|
---|
103 | connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
|
---|
104 | this, &UIVMActivityMonitorPaneContainer::sltRetranslateUI);
|
---|
105 |
|
---|
106 | }
|
---|
107 |
|
---|
108 | void UIVMActivityMonitorPaneContainer::sltRetranslateUI()
|
---|
109 | {
|
---|
110 | setTabText(Tab_Preferences, QApplication::translate("UIVMActivityMonitorPaneContainer", "Preferences"));
|
---|
111 |
|
---|
112 | if (m_pColorLabel[0])
|
---|
113 | m_pColorLabel[0]->setText(QApplication::translate("UIVMActivityMonitorPaneContainer", "Data Series 1 Color"));
|
---|
114 | if (m_pColorLabel[1])
|
---|
115 | m_pColorLabel[1]->setText(QApplication::translate("UIVMActivityMonitorPaneContainer", "Data Series 2 Color"));
|
---|
116 | if (m_pResetButton)
|
---|
117 | m_pResetButton->setText(QApplication::translate("UIVMActivityMonitorPaneContainer", "Reset to Defaults"));
|
---|
118 |
|
---|
119 | }
|
---|
120 |
|
---|
121 | void UIVMActivityMonitorPaneContainer::colorPushButtons(QPushButton *pButton, const QColor &color)
|
---|
122 | {
|
---|
123 | AssertReturnVoid(pButton);
|
---|
124 | int iSize = qApp->style()->pixelMetric(QStyle::PM_ButtonIconSize);
|
---|
125 | QPixmap iconPixmap(iSize, iSize);
|
---|
126 | QPainter painter(&iconPixmap);
|
---|
127 | painter.setBrush(color);
|
---|
128 | painter.drawRect(iconPixmap.rect());
|
---|
129 | pButton->setIcon(QIcon(iconPixmap));
|
---|
130 | }
|
---|
131 |
|
---|
132 | void UIVMActivityMonitorPaneContainer::setDataSeriesColor(int iIndex, const QColor &color)
|
---|
133 | {
|
---|
134 | if (iIndex == 0 || iIndex == 1)
|
---|
135 | {
|
---|
136 | if (m_color[iIndex] != color)
|
---|
137 | {
|
---|
138 | m_color[iIndex] = color;
|
---|
139 | colorPushButtons(m_pColorChangeButton[iIndex], color);
|
---|
140 | emit sigColorChanged(iIndex, color);
|
---|
141 | }
|
---|
142 | }
|
---|
143 | }
|
---|
144 |
|
---|
145 | QColor UIVMActivityMonitorPaneContainer::dataSeriesColor(int iIndex) const
|
---|
146 | {
|
---|
147 | if (iIndex >= 0 && iIndex < 2)
|
---|
148 | return m_color[iIndex];
|
---|
149 | return QColor();
|
---|
150 | }
|
---|
151 |
|
---|
152 | void UIVMActivityMonitorPaneContainer::sltColorChangeButtonPressed()
|
---|
153 | {
|
---|
154 | int iIndex = -1;
|
---|
155 | if (sender() == m_pColorChangeButton[0])
|
---|
156 | iIndex = 0;
|
---|
157 | else if (sender() == m_pColorChangeButton[1])
|
---|
158 | iIndex = 1;
|
---|
159 | else
|
---|
160 | return;
|
---|
161 |
|
---|
162 | QColorDialog colorDialog(m_color[iIndex], this);
|
---|
163 | if (colorDialog.exec() == QDialog::Rejected)
|
---|
164 | return;
|
---|
165 | QColor newColor = colorDialog.selectedColor();
|
---|
166 | if (m_color[iIndex] == newColor)
|
---|
167 | return;
|
---|
168 | m_color[iIndex] = newColor;
|
---|
169 | colorPushButtons(m_pColorChangeButton[iIndex], newColor);
|
---|
170 | emit sigColorChanged(iIndex, newColor);
|
---|
171 | }
|
---|
172 |
|
---|
173 | void UIVMActivityMonitorPaneContainer::sltResetToDefaults()
|
---|
174 | {
|
---|
175 | /* Reset data series colors: */
|
---|
176 | setDataSeriesColor(0, QApplication::palette().color(QPalette::LinkVisited));
|
---|
177 | setDataSeriesColor(1, QApplication::palette().color(QPalette::Link));
|
---|
178 | }
|
---|
179 |
|
---|
180 | /*********************************************************************************************************************************
|
---|
181 | * UIVMActivityMonitorContainer implementation. *
|
---|
182 | *********************************************************************************************************************************/
|
---|
183 |
|
---|
184 | UIVMActivityMonitorContainer::UIVMActivityMonitorContainer(QWidget *pParent, UIActionPool *pActionPool, EmbedTo enmEmbedding)
|
---|
185 | :QWidget(pParent)
|
---|
186 | , m_pPaneContainer(0)
|
---|
187 | , m_pTabWidget(0)
|
---|
188 | , m_pExportToFileAction(0)
|
---|
189 | , m_pActionPool(pActionPool)
|
---|
190 | , m_enmEmbedding(enmEmbedding)
|
---|
191 | {
|
---|
192 | prepare();
|
---|
193 | loadSettings();
|
---|
194 | sltCurrentTabChanged(0);
|
---|
195 | }
|
---|
196 |
|
---|
197 | void UIVMActivityMonitorContainer::removeTabs(const QVector<QUuid> &machineIdsToRemove)
|
---|
198 | {
|
---|
199 | AssertReturnVoid(m_pTabWidget);
|
---|
200 | QVector<UIVMActivityMonitor*> removeList;
|
---|
201 |
|
---|
202 | for (int i = m_pTabWidget->count() - 1; i >= 0; --i)
|
---|
203 | {
|
---|
204 | UIVMActivityMonitor *pMonitor = qobject_cast<UIVMActivityMonitor*>(m_pTabWidget->widget(i));
|
---|
205 | if (!pMonitor)
|
---|
206 | continue;
|
---|
207 | if (machineIdsToRemove.contains(pMonitor->machineId()))
|
---|
208 | {
|
---|
209 | removeList << pMonitor;
|
---|
210 | m_pTabWidget->removeTab(i);
|
---|
211 | }
|
---|
212 | }
|
---|
213 | qDeleteAll(removeList.begin(), removeList.end());
|
---|
214 | }
|
---|
215 |
|
---|
216 | void UIVMActivityMonitorContainer::prepare()
|
---|
217 | {
|
---|
218 | QVBoxLayout *pMainLayout = new QVBoxLayout(this);
|
---|
219 | pMainLayout->setContentsMargins(0, 0, 0, 0);
|
---|
220 |
|
---|
221 | m_pTabWidget = new QTabWidget(this);
|
---|
222 | m_pTabWidget->setTabPosition(QTabWidget::East);
|
---|
223 | m_pTabWidget->setTabBarAutoHide(true);
|
---|
224 |
|
---|
225 | m_pPaneContainer = new UIVMActivityMonitorPaneContainer(this);
|
---|
226 | m_pPaneContainer->hide();
|
---|
227 |
|
---|
228 | pMainLayout->addWidget(m_pTabWidget);
|
---|
229 | pMainLayout->addWidget(m_pPaneContainer);
|
---|
230 |
|
---|
231 | connect(m_pTabWidget, &QTabWidget::currentChanged,
|
---|
232 | this, &UIVMActivityMonitorContainer::sltCurrentTabChanged);
|
---|
233 | connect(m_pPaneContainer, &UIVMActivityMonitorPaneContainer::sigColorChanged,
|
---|
234 | this, &UIVMActivityMonitorContainer::sltDataSeriesColorChanged);
|
---|
235 | m_pExportToFileAction = m_pActionPool->action(UIActionIndex_M_Activity_S_Export);
|
---|
236 | if (m_pExportToFileAction)
|
---|
237 | connect(m_pExportToFileAction, &QAction::triggered, this, &UIVMActivityMonitorContainer::sltExportToFile);
|
---|
238 |
|
---|
239 | if (m_pActionPool->action(UIActionIndex_M_Activity_T_Preferences))
|
---|
240 | connect(m_pActionPool->action(UIActionIndex_M_Activity_T_Preferences), &QAction::toggled,
|
---|
241 | this, &UIVMActivityMonitorContainer::sltTogglePreferencesPane);
|
---|
242 | }
|
---|
243 |
|
---|
244 | void UIVMActivityMonitorContainer::loadSettings()
|
---|
245 | {
|
---|
246 | if (m_pPaneContainer)
|
---|
247 | {
|
---|
248 | QStringList colorList = gEDataManager->VMActivityMonitorDataSeriesColors();
|
---|
249 | if (colorList.size() == 2)
|
---|
250 | {
|
---|
251 | for (int i = 0; i < 2; ++i)
|
---|
252 | {
|
---|
253 | QColor color(colorList[i]);
|
---|
254 | if (color.isValid())
|
---|
255 | m_pPaneContainer->setDataSeriesColor(i, color);
|
---|
256 | }
|
---|
257 | }
|
---|
258 | if (!m_pPaneContainer->dataSeriesColor(0).isValid())
|
---|
259 | m_pPaneContainer->setDataSeriesColor(0, QApplication::palette().color(QPalette::LinkVisited));
|
---|
260 | if (!m_pPaneContainer->dataSeriesColor(1).isValid())
|
---|
261 | m_pPaneContainer->setDataSeriesColor(1, QApplication::palette().color(QPalette::Link));
|
---|
262 | }
|
---|
263 | }
|
---|
264 |
|
---|
265 | void UIVMActivityMonitorContainer::saveSettings()
|
---|
266 | {
|
---|
267 | if (m_pPaneContainer)
|
---|
268 | {
|
---|
269 | QStringList colorList;
|
---|
270 | colorList << m_pPaneContainer->dataSeriesColor(0).name(QColor::HexArgb);
|
---|
271 | colorList << m_pPaneContainer->dataSeriesColor(1).name(QColor::HexArgb);
|
---|
272 | gEDataManager->setVMActivityMonitorDataSeriesColors(colorList);
|
---|
273 | }
|
---|
274 | }
|
---|
275 |
|
---|
276 | void UIVMActivityMonitorContainer::sltCurrentTabChanged(int iIndex)
|
---|
277 | {
|
---|
278 | AssertReturnVoid(m_pTabWidget);
|
---|
279 | Q_UNUSED(iIndex);
|
---|
280 | UIVMActivityMonitor *pActivityMonitor = qobject_cast<UIVMActivityMonitor*>(m_pTabWidget->currentWidget());
|
---|
281 | if (pActivityMonitor)
|
---|
282 | {
|
---|
283 | CMachine comMachine = gpGlobalSession->virtualBox().FindMachine(pActivityMonitor->machineId().toString());
|
---|
284 | if (!comMachine.isNull())
|
---|
285 | {
|
---|
286 | setExportActionEnabled(comMachine.GetState() == KMachineState_Running);
|
---|
287 | }
|
---|
288 | }
|
---|
289 | }
|
---|
290 |
|
---|
291 | void UIVMActivityMonitorContainer::sltDataSeriesColorChanged(int iIndex, const QColor &color)
|
---|
292 | {
|
---|
293 | for (int i = m_pTabWidget->count() - 1; i >= 0; --i)
|
---|
294 | {
|
---|
295 | UIVMActivityMonitor *pMonitor = qobject_cast<UIVMActivityMonitor*>(m_pTabWidget->widget(i));
|
---|
296 | if (!pMonitor)
|
---|
297 | continue;
|
---|
298 | pMonitor->setDataSeriesColor(iIndex, color);
|
---|
299 | }
|
---|
300 | saveSettings();
|
---|
301 | }
|
---|
302 |
|
---|
303 | void UIVMActivityMonitorContainer::setExportActionEnabled(bool fEnabled)
|
---|
304 | {
|
---|
305 | if (m_pExportToFileAction)
|
---|
306 | m_pExportToFileAction->setEnabled(fEnabled);
|
---|
307 | }
|
---|
308 |
|
---|
309 | void UIVMActivityMonitorContainer::sltExportToFile()
|
---|
310 | {
|
---|
311 | AssertReturnVoid(m_pTabWidget);
|
---|
312 | UIVMActivityMonitor *pActivityMonitor = qobject_cast<UIVMActivityMonitor*>(m_pTabWidget->currentWidget());
|
---|
313 | if (pActivityMonitor)
|
---|
314 | pActivityMonitor->sltExportMetricsToFile();
|
---|
315 | }
|
---|
316 |
|
---|
317 | void UIVMActivityMonitorContainer::addLocalMachine(const CMachine &comMachine)
|
---|
318 | {
|
---|
319 | AssertReturnVoid(m_pTabWidget);
|
---|
320 | if (!comMachine.isOk())
|
---|
321 | return;
|
---|
322 | UIVMActivityMonitorLocal *pActivityMonitor = new UIVMActivityMonitorLocal(m_enmEmbedding, this, comMachine, m_pActionPool);
|
---|
323 | if (m_pPaneContainer)
|
---|
324 | {
|
---|
325 | pActivityMonitor->setDataSeriesColor(0, m_pPaneContainer->dataSeriesColor(0));
|
---|
326 | pActivityMonitor->setDataSeriesColor(1, m_pPaneContainer->dataSeriesColor(1));
|
---|
327 | }
|
---|
328 | m_pTabWidget->addTab(pActivityMonitor, comMachine.GetName());
|
---|
329 | }
|
---|
330 |
|
---|
331 | void UIVMActivityMonitorContainer::addCloudMachine(const CCloudMachine &comMachine)
|
---|
332 | {
|
---|
333 | AssertReturnVoid(m_pTabWidget);
|
---|
334 | if (!comMachine.isOk())
|
---|
335 | return;
|
---|
336 | UIVMActivityMonitorCloud *pActivityMonitor = new UIVMActivityMonitorCloud(m_enmEmbedding, this, comMachine, m_pActionPool);
|
---|
337 | if (m_pPaneContainer)
|
---|
338 | {
|
---|
339 | pActivityMonitor->setDataSeriesColor(0, m_pPaneContainer->dataSeriesColor(0));
|
---|
340 | pActivityMonitor->setDataSeriesColor(1, m_pPaneContainer->dataSeriesColor(1));
|
---|
341 | }
|
---|
342 | m_pTabWidget->addTab(pActivityMonitor, comMachine.GetName());
|
---|
343 | }
|
---|
344 |
|
---|
345 | void UIVMActivityMonitorContainer::sltTogglePreferencesPane(bool fChecked)
|
---|
346 | {
|
---|
347 | AssertReturnVoid(m_pPaneContainer);
|
---|
348 | m_pPaneContainer->setVisible(fChecked);
|
---|
349 | }
|
---|
350 |
|
---|
351 | void UIVMActivityMonitorContainer::guestAdditionsStateChange(const QUuid &machineId)
|
---|
352 | {
|
---|
353 | for (int i = m_pTabWidget->count() - 1; i >= 0; --i)
|
---|
354 | {
|
---|
355 | UIVMActivityMonitorLocal *pMonitor = qobject_cast<UIVMActivityMonitorLocal*>(m_pTabWidget->widget(i));
|
---|
356 | if (!pMonitor)
|
---|
357 | continue;
|
---|
358 | if (pMonitor->machineId() == machineId)
|
---|
359 | pMonitor->guestAdditionsStateChange();
|
---|
360 | }
|
---|
361 | }
|
---|