VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp@ 104158

Last change on this file since 104158 was 103710, checked in by vboxsync, 9 months ago

FE/Qt: Get rid of unwanted UICommon includes across whole the GUI.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1/* $Id: UIPopupCenter.cpp 103710 2024-03-06 16:53:27Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIPopupCenter class implementation.
4 */
5
6/*
7 * Copyright (C) 2013-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/* GUI includes: */
29#include "QIMessageBox.h"
30#include "UIErrorString.h"
31#include "UIExtraDataManager.h"
32#include "UIHostComboEditor.h"
33#include "UILoggingDefs.h"
34#include "UIPopupCenter.h"
35#include "UIPopupStack.h"
36
37/* COM includes: */
38#include "CAudioAdapter.h"
39#include "CConsole.h"
40#include "CEmulatedUSB.h"
41#include "CMachine.h"
42#include "CNetworkAdapter.h"
43#include "CVRDEServer.h"
44
45/* Other VBox includes: */
46#include <VBox/sup.h>
47
48
49/* static */
50UIPopupCenter* UIPopupCenter::s_pInstance = 0;
51UIPopupCenter* UIPopupCenter::instance() { return s_pInstance; }
52
53/* static */
54void UIPopupCenter::create()
55{
56 /* Make sure instance is NOT created yet: */
57 if (s_pInstance)
58 return;
59
60 /* Create instance: */
61 new UIPopupCenter;
62 /* Prepare instance: */
63 s_pInstance->prepare();
64}
65
66/* static */
67void UIPopupCenter::destroy()
68{
69 /* Make sure instance is NOT destroyed yet: */
70 if (!s_pInstance)
71 return;
72
73 /* Cleanup instance: */
74 s_pInstance->cleanup();
75 /* Destroy instance: */
76 delete s_pInstance;
77}
78
79UIPopupCenter::UIPopupCenter()
80{
81 /* Assign instance: */
82 s_pInstance = this;
83}
84
85UIPopupCenter::~UIPopupCenter()
86{
87 /* Unassign instance: */
88 s_pInstance = 0;
89}
90
91void UIPopupCenter::prepare()
92{
93}
94
95void UIPopupCenter::cleanup()
96{
97 /* Make sure all the popup-stack types destroyed: */
98 foreach (const QString &strTypeID, m_stackTypes.keys())
99 m_stackTypes.remove(strTypeID);
100 /* Make sure all the popup-stacks destroyed: */
101 foreach (const QString &strID, m_stacks.keys())
102 {
103 delete m_stacks[strID];
104 m_stacks.remove(strID);
105 }
106}
107
108void UIPopupCenter::showPopupStack(QWidget *pParent)
109{
110 /* Make sure parent is set! */
111 AssertPtrReturnVoid(pParent);
112
113 /* Make sure corresponding popup-stack *exists*: */
114 const QString strPopupStackID(popupStackID(pParent));
115 if (!m_stacks.contains(strPopupStackID))
116 return;
117
118 /* Assign stack with passed parent: */
119 UIPopupStack *pPopupStack = m_stacks[strPopupStackID];
120 assignPopupStackParent(pPopupStack, pParent, m_stackTypes[strPopupStackID]);
121 pPopupStack->show();
122}
123
124void UIPopupCenter::hidePopupStack(QWidget *pParent)
125{
126 /* Make sure parent is set! */
127 AssertPtrReturnVoid(pParent);
128
129 /* Make sure corresponding popup-stack *exists*: */
130 const QString strPopupStackID(popupStackID(pParent));
131 if (!m_stacks.contains(strPopupStackID))
132 return;
133
134 /* Unassign stack with passed parent: */
135 UIPopupStack *pPopupStack = m_stacks[strPopupStackID];
136 pPopupStack->hide();
137 unassignPopupStackParent(pPopupStack, pParent);
138}
139
140void UIPopupCenter::setPopupStackType(QWidget *pParent, UIPopupStackType enmType)
141{
142 /* Make sure parent is set! */
143 AssertPtrReturnVoid(pParent);
144
145 /* Composing corresponding popup-stack ID: */
146 const QString strPopupStackID(popupStackID(pParent));
147
148 /* Looking for current popup-stack type, create if it doesn't exists: */
149 UIPopupStackType &enmCurrentType = m_stackTypes[strPopupStackID];
150
151 /* Make sure stack-type has changed: */
152 if (enmCurrentType == enmType)
153 return;
154
155 /* Remember new stack type: */
156 LogRelFlow(("UIPopupCenter::setPopupStackType: Changing type of popup-stack with ID = '%s' from '%s' to '%s'.\n",
157 strPopupStackID.toLatin1().constData(),
158 enmCurrentType == UIPopupStackType_Separate ? "separate window" : "embedded widget",
159 enmType == UIPopupStackType_Separate ? "separate window" : "embedded widget"));
160 enmCurrentType = enmType;
161}
162
163void UIPopupCenter::setPopupStackOrientation(QWidget *pParent, UIPopupStackOrientation newStackOrientation)
164{
165 /* Make sure parent is set! */
166 AssertPtrReturnVoid(pParent);
167
168 /* Composing corresponding popup-stack ID: */
169 const QString strPopupStackID(popupStackID(pParent));
170
171 /* Looking for current popup-stack orientation, create if it doesn't exists: */
172 UIPopupStackOrientation &stackOrientation = m_stackOrientations[strPopupStackID];
173
174 /* Make sure stack-orientation has changed: */
175 if (stackOrientation == newStackOrientation)
176 return;
177
178 /* Remember new stack orientation: */
179 LogRelFlow(("UIPopupCenter::setPopupStackType: Changing orientation of popup-stack with ID = '%s' from '%s' to '%s'.\n",
180 strPopupStackID.toLatin1().constData(),
181 stackOrientation == UIPopupStackOrientation_Top ? "top oriented" : "bottom oriented",
182 newStackOrientation == UIPopupStackOrientation_Top ? "top oriented" : "bottom oriented"));
183 stackOrientation = newStackOrientation;
184
185 /* Update orientation for popup-stack if it currently exists: */
186 if (m_stacks.contains(strPopupStackID))
187 m_stacks[strPopupStackID]->setOrientation(stackOrientation);
188}
189
190void UIPopupCenter::message(QWidget *pParent, const QString &strID,
191 const QString &strMessage, const QString &strDetails,
192 const QString &strButtonText1 /* = QString() */,
193 const QString &strButtonText2 /* = QString() */,
194 bool fProposeAutoConfirmation /* = false */)
195{
196 showPopupPane(pParent, strID,
197 strMessage, strDetails,
198 strButtonText1, strButtonText2,
199 fProposeAutoConfirmation);
200}
201
202void UIPopupCenter::popup(QWidget *pParent, const QString &strID,
203 const QString &strMessage)
204{
205 message(pParent, strID, strMessage, QString());
206}
207
208void UIPopupCenter::alert(QWidget *pParent, const QString &strID,
209 const QString &strMessage,
210 bool fProposeAutoConfirmation /* = false */)
211{
212 message(pParent, strID, strMessage, QString(),
213 QApplication::translate("UIMessageCenter", "Close") /* 1st button text */,
214 QString() /* 2nd button text */,
215 fProposeAutoConfirmation);
216}
217
218void UIPopupCenter::alertWithDetails(QWidget *pParent, const QString &strID,
219 const QString &strMessage,
220 const QString &strDetails,
221 bool fProposeAutoConfirmation /* = false */)
222{
223 message(pParent, strID, strMessage, strDetails,
224 QApplication::translate("UIMessageCenter", "Close") /* 1st button text */,
225 QString() /* 2nd button text */,
226 fProposeAutoConfirmation);
227}
228
229void UIPopupCenter::question(QWidget *pParent, const QString &strID,
230 const QString &strMessage,
231 const QString &strButtonText1 /* = QString() */,
232 const QString &strButtonText2 /* = QString() */,
233 bool fProposeAutoConfirmation /* = false */)
234{
235 message(pParent, strID, strMessage, QString(),
236 strButtonText1, strButtonText2,
237 fProposeAutoConfirmation);
238}
239
240void UIPopupCenter::recall(QWidget *pParent, const QString &strID)
241{
242 hidePopupPane(pParent, strID);
243}
244
245void UIPopupCenter::showPopupPane(QWidget *pParent, const QString &strID,
246 const QString &strMessage, const QString &strDetails,
247 QString strButtonText1 /* = QString() */, QString strButtonText2 /* = QString() */,
248 bool fProposeAutoConfirmation /* = false */)
249{
250 /* Make sure parent is set! */
251 AssertPtrReturnVoid(pParent);
252
253 /* Prepare buttons: */
254 int iButton1 = 0;
255 int iButton2 = 0;
256 /* Make sure single button is properly configured: */
257 if (!strButtonText1.isEmpty() && strButtonText2.isEmpty())
258 iButton1 = AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape;
259 else if (strButtonText1.isEmpty() && !strButtonText2.isEmpty())
260 iButton2 = AlertButton_Cancel | AlertButtonOption_Default | AlertButtonOption_Escape;
261 /* Make sure buttons are unique if set both: */
262 else if (!strButtonText1.isEmpty() && !strButtonText2.isEmpty())
263 {
264 iButton1 = AlertButton_Ok | AlertButtonOption_Default;
265 iButton2 = AlertButton_Cancel | AlertButtonOption_Escape;
266 /* If user made a mistake in button names, we will fix that: */
267 if (strButtonText1 == strButtonText2)
268 {
269 strButtonText1 = QApplication::translate("UIMessageCenter", "Ok");
270 strButtonText1 = QApplication::translate("UIMessageCenter", "Cancel");
271 }
272 }
273
274 /* Check if popup-pane was auto-confirmed before: */
275 if ((iButton1 || iButton2) && fProposeAutoConfirmation)
276 {
277 const QStringList confirmedPopupList = gEDataManager->suppressedMessages();
278 if ( confirmedPopupList.contains(strID)
279 || confirmedPopupList.contains("allPopupPanes")
280 || confirmedPopupList.contains("all") )
281 {
282 int iResultCode = AlertOption_AutoConfirmed;
283 if (iButton1 & AlertButtonOption_Default)
284 iResultCode |= (iButton1 & AlertButtonMask);
285 else if (iButton2 & AlertButtonOption_Default)
286 iResultCode |= (iButton2 & AlertButtonMask);
287 emit sigPopupPaneDone(strID, iResultCode);
288 return;
289 }
290 }
291
292 /* Looking for corresponding popup-stack: */
293 const QString strPopupStackID(popupStackID(pParent));
294 UIPopupStack *pPopupStack = 0;
295 /* If there is already popup-stack with such ID: */
296 if (m_stacks.contains(strPopupStackID))
297 {
298 /* Just get existing one: */
299 pPopupStack = m_stacks[strPopupStackID];
300 }
301 /* If there is no popup-stack with such ID: */
302 else
303 {
304 /* Create new one: */
305 pPopupStack = m_stacks[strPopupStackID] = new UIPopupStack(strPopupStackID, m_stackOrientations[strPopupStackID]);
306 /* Attach popup-stack connections: */
307 connect(pPopupStack, &UIPopupStack::sigPopupPaneDone, this, &UIPopupCenter::sltPopupPaneDone);
308 connect(pPopupStack, &UIPopupStack::sigRemove, this, &UIPopupCenter::sltRemovePopupStack);
309 }
310
311 /* If there is already popup-pane with such ID: */
312 if (pPopupStack->exists(strID))
313 {
314 /* Just update existing one: */
315 pPopupStack->updatePopupPane(strID, strMessage, strDetails);
316 }
317 /* If there is no popup-pane with such ID: */
318 else
319 {
320 /* Compose button description map: */
321 QMap<int, QString> buttonDescriptions;
322 if (iButton1 != 0)
323 buttonDescriptions[iButton1] = strButtonText1;
324 if (iButton2 != 0)
325 buttonDescriptions[iButton2] = strButtonText2;
326 if (fProposeAutoConfirmation)
327 buttonDescriptions[AlertButton_Cancel | AlertOption_AutoConfirmed] = QString();
328 /* Create new one: */
329 pPopupStack->createPopupPane(strID, strMessage, strDetails, buttonDescriptions);
330 }
331
332 /* Show popup-stack: */
333 showPopupStack(pParent);
334}
335
336void UIPopupCenter::hidePopupPane(QWidget *pParent, const QString &strID)
337{
338 /* Make sure parent is set! */
339 AssertPtrReturnVoid(pParent);
340
341 /* Make sure corresponding popup-stack *exists*: */
342 const QString strPopupStackID(popupStackID(pParent));
343 if (!m_stacks.contains(strPopupStackID))
344 return;
345
346 /* Make sure corresponding popup-pane *exists*: */
347 UIPopupStack *pPopupStack = m_stacks[strPopupStackID];
348 if (!pPopupStack->exists(strID))
349 return;
350
351 /* Recall corresponding popup-pane: */
352 pPopupStack->recallPopupPane(strID);
353}
354
355void UIPopupCenter::sltPopupPaneDone(QString strID, int iResultCode)
356{
357 /* Remember auto-confirmation fact (if necessary): */
358 if (iResultCode & AlertOption_AutoConfirmed)
359 gEDataManager->setSuppressedMessages(gEDataManager->suppressedMessages() << strID);
360
361 /* Notify listeners: */
362 emit sigPopupPaneDone(strID, iResultCode);
363}
364
365void UIPopupCenter::sltRemovePopupStack(QString strID)
366{
367 /* Make sure corresponding popup-stack *exists*: */
368 if (!m_stacks.contains(strID))
369 {
370 AssertMsgFailed(("Popup-stack already destroyed!\n"));
371 return;
372 }
373
374 /* Delete popup-stack asyncronously.
375 * To avoid issues with events which already posted: */
376 UIPopupStack *pPopupStack = m_stacks[strID];
377 m_stacks.remove(strID);
378 pPopupStack->deleteLater();
379}
380
381/* static */
382QString UIPopupCenter::popupStackID(QWidget *pParent)
383{
384 /* Make sure parent is set! */
385 AssertPtrReturn(pParent, QString());
386
387 /* Special handling for Runtime UI: */
388 if (pParent->inherits("UIMachineWindow"))
389 return QString("UIMachineWindow");
390
391 /* Common handling for other cases: */
392 return pParent->metaObject()->className();
393}
394
395/* static */
396void UIPopupCenter::assignPopupStackParent(UIPopupStack *pPopupStack, QWidget *pParent, UIPopupStackType enmStackType)
397{
398 /* Make sure parent is set! */
399 AssertPtrReturnVoid(pParent);
400
401 /* Assign event-filter: */
402 pParent->window()->installEventFilter(pPopupStack);
403
404 /* Assign parent depending on passed *stack* type: */
405 switch (enmStackType)
406 {
407 case UIPopupStackType_Embedded:
408 {
409 pPopupStack->setParent(pParent);
410 break;
411 }
412 case UIPopupStackType_Separate:
413 {
414 pPopupStack->setParent(pParent, Qt::Tool | Qt::FramelessWindowHint);
415 break;
416 }
417 default: break;
418 }
419}
420
421/* static */
422void UIPopupCenter::unassignPopupStackParent(UIPopupStack *pPopupStack, QWidget *pParent)
423{
424 /* Make sure parent is set! */
425 AssertPtrReturnVoid(pParent);
426
427 /* Unassign parent: */
428 pPopupStack->setParent(0);
429
430 /* Unassign event-filter: */
431 pParent->window()->removeEventFilter(pPopupStack);
432}
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