1 | /* $Id: UIVirtualMachineItemLocal.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBox Qt GUI - UIVirtualMachineItem class implementation.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2006-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 <QFileInfo>
|
---|
30 | #include <QIcon>
|
---|
31 |
|
---|
32 | /* GUI includes: */
|
---|
33 | #include "UICommon.h"
|
---|
34 | #include "UIConverter.h"
|
---|
35 | #include "UIErrorString.h"
|
---|
36 | #include "UIExtraDataManager.h"
|
---|
37 | #include "UIIconPool.h"
|
---|
38 | #include "UIVirtualMachineItemLocal.h"
|
---|
39 | #ifdef VBOX_WS_MAC
|
---|
40 | # include <ApplicationServices/ApplicationServices.h>
|
---|
41 | #endif /* VBOX_WS_MAC */
|
---|
42 |
|
---|
43 | /* COM includes: */
|
---|
44 | #include "CSnapshot.h"
|
---|
45 | #include "CVirtualBoxErrorInfo.h"
|
---|
46 |
|
---|
47 |
|
---|
48 | /*********************************************************************************************************************************
|
---|
49 | * Class UIVirtualMachineItemLocal implementation. *
|
---|
50 | *********************************************************************************************************************************/
|
---|
51 |
|
---|
52 | UIVirtualMachineItemLocal::UIVirtualMachineItemLocal(const CMachine &comMachine)
|
---|
53 | : UIVirtualMachineItem(UIVirtualMachineItemType_Local)
|
---|
54 | , m_comMachine(comMachine)
|
---|
55 | , m_cSnaphot(0)
|
---|
56 | , m_enmMachineState(KMachineState_Null)
|
---|
57 | , m_enmSessionState(KSessionState_Null)
|
---|
58 | {
|
---|
59 | recache();
|
---|
60 | }
|
---|
61 |
|
---|
62 | UIVirtualMachineItemLocal::~UIVirtualMachineItemLocal()
|
---|
63 | {
|
---|
64 | }
|
---|
65 |
|
---|
66 | void UIVirtualMachineItemLocal::recache()
|
---|
67 | {
|
---|
68 | /* Determine attributes which are always available: */
|
---|
69 | m_uId = m_comMachine.GetId();
|
---|
70 | m_strSettingsFile = m_comMachine.GetSettingsFilePath();
|
---|
71 |
|
---|
72 | /* Now determine whether VM is accessible: */
|
---|
73 | m_fAccessible = m_comMachine.GetAccessible();
|
---|
74 | if (m_fAccessible)
|
---|
75 | {
|
---|
76 | /* Reset last access error information: */
|
---|
77 | m_strAccessError.clear();
|
---|
78 |
|
---|
79 | /* Determine own VM attributes: */
|
---|
80 | m_strName = m_comMachine.GetName();
|
---|
81 | m_strOSTypeId = m_comMachine.GetOSTypeId();
|
---|
82 | m_groups = m_comMachine.GetGroups().toList();
|
---|
83 |
|
---|
84 | /* Determine snapshot attributes: */
|
---|
85 | CSnapshot comSnapshot = m_comMachine.GetCurrentSnapshot();
|
---|
86 | m_strSnapshotName = comSnapshot.isNull() ? QString() : comSnapshot.GetName();
|
---|
87 | #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
|
---|
88 | m_lastStateChange.setSecsSinceEpoch(m_comMachine.GetLastStateChange() / 1000);
|
---|
89 | #else
|
---|
90 | m_lastStateChange.setTime_t(m_comMachine.GetLastStateChange() / 1000);
|
---|
91 | #endif
|
---|
92 | m_cSnaphot = m_comMachine.GetSnapshotCount();
|
---|
93 |
|
---|
94 | /* Determine VM states: */
|
---|
95 | m_enmMachineState = m_comMachine.GetState();
|
---|
96 | m_machineStateIcon = gpConverter->toIcon(m_enmMachineState);
|
---|
97 | m_enmSessionState = m_comMachine.GetSessionState();
|
---|
98 |
|
---|
99 | /* Determine configuration access level: */
|
---|
100 | m_enmConfigurationAccessLevel = ::configurationAccessLevel(m_enmSessionState, m_enmMachineState);
|
---|
101 | /* Also take restrictions into account: */
|
---|
102 | if ( m_enmConfigurationAccessLevel != ConfigurationAccessLevel_Null
|
---|
103 | && !gEDataManager->machineReconfigurationEnabled(m_uId))
|
---|
104 | m_enmConfigurationAccessLevel = ConfigurationAccessLevel_Null;
|
---|
105 |
|
---|
106 | /* Determine PID finally: */
|
---|
107 | if ( m_enmMachineState == KMachineState_PoweredOff
|
---|
108 | || m_enmMachineState == KMachineState_Saved
|
---|
109 | || m_enmMachineState == KMachineState_Teleported
|
---|
110 | || m_enmMachineState == KMachineState_Aborted
|
---|
111 | || m_enmMachineState == KMachineState_AbortedSaved
|
---|
112 | )
|
---|
113 | {
|
---|
114 | m_pid = (ULONG) ~0;
|
---|
115 | }
|
---|
116 | else
|
---|
117 | {
|
---|
118 | m_pid = m_comMachine.GetSessionPID();
|
---|
119 | }
|
---|
120 |
|
---|
121 | /* Determine whether we should show this VM details: */
|
---|
122 | m_fHasDetails = gEDataManager->showMachineInVirtualBoxManagerDetails(m_uId);
|
---|
123 | }
|
---|
124 | else
|
---|
125 | {
|
---|
126 | /* Update last access error information: */
|
---|
127 | m_strAccessError = UIErrorString::formatErrorInfo(m_comMachine.GetAccessError());
|
---|
128 |
|
---|
129 | /* Determine machine name on the basis of settings file only: */
|
---|
130 | QFileInfo fi(m_strSettingsFile);
|
---|
131 | m_strName = UICommon::hasAllowedExtension(fi.completeSuffix(), VBoxFileExts)
|
---|
132 | ? fi.completeBaseName()
|
---|
133 | : fi.fileName();
|
---|
134 | /* Reset other VM attributes: */
|
---|
135 | m_strOSTypeId = QString();
|
---|
136 | m_groups.clear();
|
---|
137 |
|
---|
138 | /* Reset snapshot attributes: */
|
---|
139 | m_strSnapshotName = QString();
|
---|
140 | m_lastStateChange = QDateTime::currentDateTime();
|
---|
141 | m_cSnaphot = 0;
|
---|
142 |
|
---|
143 | /* Reset VM states: */
|
---|
144 | m_enmMachineState = KMachineState_Null;
|
---|
145 | m_machineStateIcon = gpConverter->toIcon(KMachineState_Aborted);
|
---|
146 | m_enmSessionState = KSessionState_Null;
|
---|
147 |
|
---|
148 | /* Reset configuration access level: */
|
---|
149 | m_enmConfigurationAccessLevel = ConfigurationAccessLevel_Null;
|
---|
150 |
|
---|
151 | /* Reset PID finally: */
|
---|
152 | m_pid = (ULONG) ~0;
|
---|
153 |
|
---|
154 | /* Reset whether we should show this VM details: */
|
---|
155 | m_fHasDetails = true;
|
---|
156 | }
|
---|
157 |
|
---|
158 | /* Recache item pixmap: */
|
---|
159 | recachePixmap();
|
---|
160 |
|
---|
161 | /* Retranslate finally: */
|
---|
162 | retranslateUi();
|
---|
163 | }
|
---|
164 |
|
---|
165 | void UIVirtualMachineItemLocal::recachePixmap()
|
---|
166 | {
|
---|
167 | /* If machine is accessible: */
|
---|
168 | if (m_fAccessible)
|
---|
169 | {
|
---|
170 | /* First, we are trying to acquire personal machine guest OS type icon: */
|
---|
171 | m_pixmap = generalIconPool().userMachinePixmapDefault(m_comMachine, &m_logicalPixmapSize);
|
---|
172 | /* If there is nothing, we are using icon corresponding to cached guest OS type: */
|
---|
173 | if (m_pixmap.isNull())
|
---|
174 | m_pixmap = generalIconPool().guestOSTypePixmapDefault(m_strOSTypeId, &m_logicalPixmapSize);
|
---|
175 | }
|
---|
176 | /* Otherwise: */
|
---|
177 | else
|
---|
178 | {
|
---|
179 | /* We are using "Other" guest OS type icon: */
|
---|
180 | m_pixmap = generalIconPool().guestOSTypePixmapDefault("Other", &m_logicalPixmapSize);
|
---|
181 | }
|
---|
182 | }
|
---|
183 |
|
---|
184 | bool UIVirtualMachineItemLocal::isItemEditable() const
|
---|
185 | {
|
---|
186 | return accessible()
|
---|
187 | && sessionState() == KSessionState_Unlocked;
|
---|
188 | }
|
---|
189 |
|
---|
190 | bool UIVirtualMachineItemLocal::isItemRemovable() const
|
---|
191 | {
|
---|
192 | return !accessible()
|
---|
193 | || sessionState() == KSessionState_Unlocked;
|
---|
194 | }
|
---|
195 |
|
---|
196 | bool UIVirtualMachineItemLocal::isItemSaved() const
|
---|
197 | {
|
---|
198 | return accessible()
|
---|
199 | && ( machineState() == KMachineState_Saved
|
---|
200 | || machineState() == KMachineState_AbortedSaved);
|
---|
201 | }
|
---|
202 |
|
---|
203 | bool UIVirtualMachineItemLocal::isItemPoweredOff() const
|
---|
204 | {
|
---|
205 | return accessible()
|
---|
206 | && ( machineState() == KMachineState_PoweredOff
|
---|
207 | || machineState() == KMachineState_Saved
|
---|
208 | || machineState() == KMachineState_Teleported
|
---|
209 | || machineState() == KMachineState_Aborted
|
---|
210 | || machineState() == KMachineState_AbortedSaved);
|
---|
211 | }
|
---|
212 |
|
---|
213 | bool UIVirtualMachineItemLocal::isItemStarted() const
|
---|
214 | {
|
---|
215 | return isItemRunning()
|
---|
216 | || isItemPaused();
|
---|
217 | }
|
---|
218 |
|
---|
219 | bool UIVirtualMachineItemLocal::isItemRunning() const
|
---|
220 | {
|
---|
221 | return accessible()
|
---|
222 | && ( machineState() == KMachineState_Running
|
---|
223 | || machineState() == KMachineState_Teleporting
|
---|
224 | || machineState() == KMachineState_LiveSnapshotting);
|
---|
225 | }
|
---|
226 |
|
---|
227 | bool UIVirtualMachineItemLocal::isItemRunningHeadless() const
|
---|
228 | {
|
---|
229 | if (isItemRunning())
|
---|
230 | {
|
---|
231 | /* Open session to determine which frontend VM is started with: */
|
---|
232 | CSession comSession = uiCommon().openExistingSession(id());
|
---|
233 | if (!comSession.isNull())
|
---|
234 | {
|
---|
235 | /* Acquire the session name: */
|
---|
236 | const QString strSessionName = comSession.GetMachine().GetSessionName();
|
---|
237 | /* Close the session early: */
|
---|
238 | comSession.UnlockMachine();
|
---|
239 | /* Check whether we are in 'headless' session: */
|
---|
240 | return strSessionName == "headless";
|
---|
241 | }
|
---|
242 | }
|
---|
243 | return false;
|
---|
244 | }
|
---|
245 |
|
---|
246 | bool UIVirtualMachineItemLocal::isItemPaused() const
|
---|
247 | {
|
---|
248 | return accessible()
|
---|
249 | && ( machineState() == KMachineState_Paused
|
---|
250 | || machineState() == KMachineState_TeleportingPausedVM);
|
---|
251 | }
|
---|
252 |
|
---|
253 | bool UIVirtualMachineItemLocal::isItemStuck() const
|
---|
254 | {
|
---|
255 | return accessible()
|
---|
256 | && machineState() == KMachineState_Stuck;
|
---|
257 | }
|
---|
258 |
|
---|
259 | bool UIVirtualMachineItemLocal::isItemCanBeSwitchedTo() const
|
---|
260 | {
|
---|
261 | return const_cast<CMachine&>(m_comMachine).CanShowConsoleWindow()
|
---|
262 | || isItemRunningHeadless();
|
---|
263 | }
|
---|
264 |
|
---|
265 | void UIVirtualMachineItemLocal::retranslateUi()
|
---|
266 | {
|
---|
267 | /* This is used in tool-tip generation: */
|
---|
268 | #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
|
---|
269 | const QString strDateTime = m_lastStateChange.date() == QDate::currentDate()
|
---|
270 | ? QLocale::system().toString(m_lastStateChange.time(), QLocale::ShortFormat)
|
---|
271 | : QLocale::system().toString(m_lastStateChange, QLocale::ShortFormat);
|
---|
272 | #else
|
---|
273 | const QString strDateTime = (m_lastStateChange.date() == QDate::currentDate())
|
---|
274 | ? m_lastStateChange.time().toString(Qt::LocalDate)
|
---|
275 | : m_lastStateChange.toString(Qt::LocalDate);
|
---|
276 | #endif
|
---|
277 |
|
---|
278 | /* If machine is accessible: */
|
---|
279 | if (m_fAccessible)
|
---|
280 | {
|
---|
281 | /* Just use the usual translation for valid states: */
|
---|
282 | m_strMachineStateName = gpConverter->toString(m_enmMachineState);
|
---|
283 | m_strSessionStateName = gpConverter->toString(m_enmSessionState);
|
---|
284 |
|
---|
285 | /* Update tool-tip: */
|
---|
286 | m_strToolTipText = QString("<b>%1</b>").arg(m_strName);
|
---|
287 | if (!m_strSnapshotName.isNull())
|
---|
288 | m_strToolTipText += QString(" (%1)").arg(m_strSnapshotName);
|
---|
289 | m_strToolTipText = tr("<nobr>%1<br></nobr>"
|
---|
290 | "<nobr>%2 since %3</nobr><br>"
|
---|
291 | "<nobr>Session %4</nobr>",
|
---|
292 | "VM tooltip (name, last state change, session state)")
|
---|
293 | .arg(m_strToolTipText)
|
---|
294 | .arg(gpConverter->toString(m_enmMachineState))
|
---|
295 | .arg(strDateTime)
|
---|
296 | .arg(gpConverter->toString(m_enmSessionState).toLower());
|
---|
297 | }
|
---|
298 | /* Otherwise: */
|
---|
299 | else
|
---|
300 | {
|
---|
301 | /* We have our own translation for Null states: */
|
---|
302 | m_strMachineStateName = tr("Inaccessible");
|
---|
303 | m_strSessionStateName = tr("Inaccessible");
|
---|
304 |
|
---|
305 | /* Update tool-tip: */
|
---|
306 | m_strToolTipText = tr("<nobr><b>%1</b><br></nobr>"
|
---|
307 | "<nobr>Inaccessible since %2</nobr>",
|
---|
308 | "Inaccessible VM tooltip (name, last state change)")
|
---|
309 | .arg(m_strSettingsFile)
|
---|
310 | .arg(strDateTime);
|
---|
311 | }
|
---|
312 | }
|
---|