VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: UIModalWindowManager.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIModalWindowManager 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 "UIModalWindowManager.h"
30#ifdef VBOX_GUI_WITH_NETWORK_MANAGER
31# include "UINetworkRequestManager.h"
32#endif
33#include "UIProgressDialog.h"
34
35/* Other VBox includes: */
36#include <VBox/sup.h>
37
38
39/* static */
40UIModalWindowManager *UIModalWindowManager::s_pInstance = 0;
41UIModalWindowManager *UIModalWindowManager::instance() { return s_pInstance; }
42
43/* static */
44void UIModalWindowManager::create()
45{
46 /* Make sure instance is NOT created yet: */
47 if (s_pInstance)
48 {
49 AssertMsgFailed(("UIModalWindowManager instance is already created!"));
50 return;
51 }
52
53 /* Create instance: */
54 new UIModalWindowManager;
55}
56
57/* static */
58void UIModalWindowManager::destroy()
59{
60 /* Make sure instance is NOT destroyed yet: */
61 if (!s_pInstance)
62 {
63 AssertMsgFailed(("UIModalWindowManager instance is already destroyed!"));
64 return;
65 }
66
67 /* Destroy instance: */
68 delete s_pInstance;
69}
70
71UIModalWindowManager::UIModalWindowManager()
72 : m_pMainWindowShown(0)
73{
74 /* Assign instance: */
75 s_pInstance = this;
76}
77
78UIModalWindowManager::~UIModalWindowManager()
79{
80 /* Unassign instance: */
81 s_pInstance = 0;
82}
83
84QWidget *UIModalWindowManager::realParentWindow(QWidget *pWidget)
85{
86 /* Null if widget pointer is null: */
87 if (!pWidget)
88 return 0;
89
90 /* Get the top-level window for the passed-widget: */
91 QWidget *pTopLevelWindow = pWidget->window();
92
93 /* Search through all the stack(s) we have: */
94 foreach (const QList<QWidget*> &iteratedWindowStack, m_windows)
95 {
96 /* Search through all the window(s) iterated-stack contains: */
97 foreach (QWidget *pIteratedWindow, iteratedWindowStack)
98 {
99 /* If possible-parent-window found: */
100 if (pIteratedWindow == pTopLevelWindow)
101 {
102 /* Return the 'top' of the iterated-window-stack as the result: */
103 QWidget *pTopWindow = iteratedWindowStack.last();
104 preprocessRealParent(pTopWindow);
105 return pTopWindow;
106 }
107 }
108 }
109
110 /* If we unable to found the possible-parent-window among all ours,
111 * we have to add it as the new-window-stack only element: */
112 registerNewParent(pTopLevelWindow);
113 /* And return as the result: */
114 return pTopLevelWindow;
115}
116
117bool UIModalWindowManager::isWindowInTheModalWindowStack(QWidget *pWindow)
118{
119 return contains(pWindow);
120}
121
122bool UIModalWindowManager::isWindowOnTheTopOfTheModalWindowStack(QWidget *pWindow)
123{
124 return contains(pWindow, true);
125}
126
127void UIModalWindowManager::registerNewParent(QWidget *pWindow, QWidget *pParentWindow /* = 0 */)
128{
129 /* Make sure passed-widget-pointer is not null: */
130 if (!pWindow)
131 {
132 AssertMsgFailed(("Passed pointer is NULL!"));
133 return;
134 }
135
136 /* Make sure passed-widget is of 'top-level window' type: */
137 if (!pWindow->isWindow())
138 {
139 AssertMsgFailed(("Passed widget is NOT top-level window!"));
140 return;
141 }
142
143 /* Make sure passed-parent-widget is of 'top-level window' type: */
144 if (pParentWindow && !pParentWindow->isWindow())
145 {
146 AssertMsgFailed(("Passed parent widget is NOT top-level window!"));
147 return;
148 }
149
150 /* If parent-window really passed: */
151 if (pParentWindow)
152 {
153 /* Make sure we have passed-parent-window registered already.
154 * If so, we have to make sure its the 'top' element in his stack also.
155 * If so, we have to register passed-window as the new 'top' in that stack. */
156 for (int iIteratedStackIndex = 0; iIteratedStackIndex < m_windows.size(); ++iIteratedStackIndex)
157 {
158 /* Get current-stack: */
159 QList<QWidget*> &iteratedWindowStack = m_windows[iIteratedStackIndex];
160 /* Search through all the window(s) iterated-stack contains: */
161 int iIteratedWindwStackSize = iteratedWindowStack.size();
162 for (int iIteratedWindowIndex = 0; iIteratedWindowIndex < iIteratedWindwStackSize; ++iIteratedWindowIndex)
163 {
164 /* Get iterated-window: */
165 QWidget *pIteratedWindow = iteratedWindowStack[iIteratedWindowIndex];
166 /* If passed-parent-window found: */
167 if (pIteratedWindow == pParentWindow)
168 {
169 /* Make sure it was the last one of the iterated-window(s): */
170 if (iIteratedWindowIndex != iIteratedWindwStackSize - 1)
171 {
172 AssertMsgFailed(("Passed parent window is not on the top of his current-stack!"));
173 return;
174 }
175 /* Register passed-window as the new 'top' in iterated-window-stack: */
176 iteratedWindowStack << pWindow;
177 connect(pWindow, &QWidget::destroyed, this, &UIModalWindowManager::sltRemoveFromStack);
178 return;
179 }
180 }
181 }
182 /* Passed-parent-window was not found: */
183 AssertMsgFailed(("Passed parent window is not registered!"));
184 return;
185 }
186 /* If no parent-window passed: */
187 else
188 {
189 /* Register passed-window as the only one item in new-window-stack: */
190 QList<QWidget*> newWindowStack(QList<QWidget*>() << pWindow);
191 m_windows << newWindowStack;
192 connect(pWindow, &QWidget::destroyed, this, &UIModalWindowManager::sltRemoveFromStack);
193 }
194
195 /* Notify listeners that their stack may have changed: */
196 emit sigStackChanged();
197}
198
199void UIModalWindowManager::sltRemoveFromStack(QObject *pObject)
200{
201 /* Make sure passed-object still valid: */
202 if (!pObject)
203 return;
204
205 /* Object is already of QObject type,
206 * because inheritance wrapper(s) destructor(s) already called
207 * so we can't search through the m_windows stack
208 * using the standard algorithm functionality.
209 * Lets do it manually: */
210 for (int iIteratedStackIndex = 0; iIteratedStackIndex < m_windows.size(); ++iIteratedStackIndex)
211 {
212 /* Get iterated-stack: */
213 QList<QWidget*> &iteratedWindowStack = m_windows[iIteratedStackIndex];
214 /* Search through all the window(s) iterated-stack contains: */
215 int iIteratedWindowStackSize = iteratedWindowStack.size();
216 for (int iIteratedWindowIndex = 0; iIteratedWindowIndex < iIteratedWindowStackSize; ++iIteratedWindowIndex)
217 {
218 /* Get iterated-window: */
219 QWidget *pIteratedWindow = iteratedWindowStack[iIteratedWindowIndex];
220 /* If passed-object is almost-destroyed iterated-window: */
221 if (pIteratedWindow == pObject)
222 {
223 /* Make sure it was the last added window: */
224 AssertMsg(iIteratedWindowIndex == iIteratedWindowStackSize - 1, ("Removing element from the middle of the stack!"));
225 /* Cleanup window pointer: */
226 iteratedWindowStack.removeAt(iIteratedWindowIndex);
227 /* And stack itself if necessary: */
228 if (iteratedWindowStack.isEmpty())
229 m_windows.removeAt(iIteratedStackIndex);
230 }
231 }
232 }
233
234 /* Notify listeners that their stack may have changed: */
235 emit sigStackChanged();
236}
237
238bool UIModalWindowManager::contains(QWidget *pParentWindow, bool fAsTheTopOfStack /* = false */)
239{
240 /* False if passed-parent-widget pointer is null: */
241 if (!pParentWindow)
242 {
243 AssertMsgFailed(("Passed pointer is NULL!"));
244 return false;
245 }
246
247 /* False if passed-parent-widget is not of 'top-level window' type: */
248 if (!pParentWindow->isWindow())
249 {
250 AssertMsgFailed(("Passed widget is NOT top-level window!"));
251 return false;
252 }
253
254 /* Search through all the stack(s) we have: */
255 foreach (const QList<QWidget*> &iteratedWindowStack, m_windows)
256 {
257 /* Search through all the window(s) iterated-stack contains: */
258 int iIteratedWindowStackSize = iteratedWindowStack.size();
259 for (int iIteratedWidnowIndex = 0; iIteratedWidnowIndex < iIteratedWindowStackSize; ++iIteratedWidnowIndex)
260 {
261 /* Get iterated-window: */
262 QWidget *pIteratedWindow = iteratedWindowStack[iIteratedWidnowIndex];
263 /* If passed-parent-window found: */
264 if (pIteratedWindow == pParentWindow)
265 {
266 /* True if we are not looking for 'top' of the stack or its the 'top': */
267 return !fAsTheTopOfStack || iIteratedWidnowIndex == iIteratedWindowStackSize - 1;
268 }
269 }
270 }
271
272 /* False by default: */
273 return false;
274}
275
276/* static */
277void UIModalWindowManager::preprocessRealParent(QWidget *pParent)
278{
279 /* Progress dialog can be hidden while we are trying to use it as top-most modal parent,
280 * We should show it in such cases because else on MacOS X there will be a problem. */
281 if (UIProgressDialog *pProgressDialog = qobject_cast<UIProgressDialog*>(pParent))
282 pProgressDialog->show();
283}
284
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use