VirtualBox

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

Last change on this file was 104313, checked in by vboxsync, 5 weeks ago

FE/Qt. bugref:10622. Using new UITranslationEventListener in the settings related GUI classes.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use