VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIPopupStack.cpp@ 76553

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: UIPopupStack.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIPopupStack class implementation.
4 */
5
6/*
7 * Copyright (C) 2013-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifdef VBOX_WITH_PRECOMPILED_HEADERS
19# include <precomp.h>
20#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
21
22/* Qt includes: */
23# include <QEvent>
24# include <QMainWindow>
25# include <QMenuBar>
26# include <QScrollArea>
27# include <QStatusBar>
28# include <QVBoxLayout>
29
30/* GUI includes: */
31# include "VBoxGlobal.h"
32# include "UIPopupStack.h"
33# include "UIPopupStackViewport.h"
34
35#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
36
37
38UIPopupStack::UIPopupStack(const QString &strID, UIPopupStackOrientation enmOrientation)
39 : m_strID(strID)
40 , m_enmOrientation(enmOrientation)
41 , m_pScrollArea(0)
42 , m_pScrollViewport(0)
43 , m_iParentMenuBarHeight(0)
44 , m_iParentStatusBarHeight(0)
45{
46 /* Prepare: */
47 prepare();
48}
49
50bool UIPopupStack::exists(const QString &strID) const
51{
52 /* Redirect question to viewport: */
53 return m_pScrollViewport->exists(strID);
54}
55
56void UIPopupStack::createPopupPane(const QString &strID,
57 const QString &strMessage, const QString &strDetails,
58 const QMap<int, QString> &buttonDescriptions)
59{
60 /* Redirect request to viewport: */
61 m_pScrollViewport->createPopupPane(strID,
62 strMessage, strDetails,
63 buttonDescriptions);
64
65 /* Propagate size: */
66 propagateSize();
67}
68
69void UIPopupStack::updatePopupPane(const QString &strID,
70 const QString &strMessage, const QString &strDetails)
71{
72 /* Redirect request to viewport: */
73 m_pScrollViewport->updatePopupPane(strID,
74 strMessage, strDetails);
75}
76
77void UIPopupStack::recallPopupPane(const QString &strID)
78{
79 /* Redirect request to viewport: */
80 m_pScrollViewport->recallPopupPane(strID);
81}
82
83void UIPopupStack::setOrientation(UIPopupStackOrientation enmOrientation)
84{
85 /* Make sure orientation has changed: */
86 if (m_enmOrientation == enmOrientation)
87 return;
88
89 /* Update orientation: */
90 m_enmOrientation = enmOrientation;
91 sltAdjustGeometry();
92}
93
94void UIPopupStack::setParent(QWidget *pParent)
95{
96 /* Call to base-class: */
97 QWidget::setParent(pParent);
98 /* Recalculate parent menu-bar height: */
99 m_iParentMenuBarHeight = parentMenuBarHeight(pParent);
100 /* Recalculate parent status-bar height: */
101 m_iParentStatusBarHeight = parentStatusBarHeight(pParent);
102}
103
104void UIPopupStack::setParent(QWidget *pParent, Qt::WindowFlags flags)
105{
106 /* Call to base-class: */
107 QWidget::setParent(pParent, flags);
108 /* Recalculate parent menu-bar height: */
109 m_iParentMenuBarHeight = parentMenuBarHeight(pParent);
110 /* Recalculate parent status-bar height: */
111 m_iParentStatusBarHeight = parentStatusBarHeight(pParent);
112}
113
114bool UIPopupStack::eventFilter(QObject *pWatched, QEvent *pEvent)
115{
116 /* Call to base-class if that is not parent event: */
117 if (!parent() || pWatched != parent())
118 return QWidget::eventFilter(pWatched, pEvent);
119
120 /* Handle parent geometry events: */
121 switch (pEvent->type())
122 {
123 case QEvent::Resize:
124 {
125 /* Propagate size: */
126 propagateSize();
127 /* Adjust geometry: */
128 sltAdjustGeometry();
129 break;
130 }
131 case QEvent::Move:
132 {
133 /* Adjust geometry: */
134 sltAdjustGeometry();
135 break;
136 }
137 default:
138 break; /* Shuts up MSC. */
139 }
140
141 /* Call to base-class: */
142 return QWidget::eventFilter(pWatched, pEvent);
143}
144
145void UIPopupStack::showEvent(QShowEvent*)
146{
147 /* Propagate size: */
148 propagateSize();
149 /* Adjust geometry: */
150 sltAdjustGeometry();
151}
152
153void UIPopupStack::sltAdjustGeometry()
154{
155 /* Make sure parent is currently set: */
156 if (!parent())
157 return;
158
159 /* Read parent geometry: */
160 QRect geo(parentWidget()->geometry());
161 if (!parentWidget()->isWindow())
162 geo.moveTo(parentWidget()->mapToGlobal(QPoint(0, 0)));
163
164 /* Determine size: */
165 int iWidth = parentWidget()->width();
166 int iHeight = parentWidget()->height();
167 /* Subtract menu-bar and status-bar heights: */
168 iHeight -= (m_iParentMenuBarHeight + m_iParentStatusBarHeight);
169 /* Check if minimum height is even less than current: */
170 if (m_pScrollViewport)
171 {
172 /* Get minimum viewport height: */
173 int iMinimumHeight = m_pScrollViewport->minimumSizeHint().height();
174 /* Subtract layout margins: */
175 int iLeft, iTop, iRight, iBottom;
176 m_pMainLayout->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
177 iMinimumHeight += (iTop + iBottom);
178 /* Compare minimum and current height: */
179 iHeight = qMin(iHeight, iMinimumHeight);
180 }
181
182 /* Determine origin: */
183 int iX = 0;
184 int iY = 0;
185 /* Shift for top-level window: */
186 if (isWindow())
187 {
188 iX += geo.x();
189 iY += geo.y();
190 }
191 switch (m_enmOrientation)
192 {
193 case UIPopupStackOrientation_Top:
194 {
195 /* Just add menu-bar height: */
196 iY += m_iParentMenuBarHeight;
197 break;
198 }
199 case UIPopupStackOrientation_Bottom:
200 {
201 /* Shift to bottom: */
202 iY += (geo.height() - iHeight);
203 /* And subtract status-bar height: */
204 iY -= m_iParentStatusBarHeight;
205 break;
206 }
207 }
208
209 /* Adjust geometry: */
210 VBoxGlobal::setTopLevelGeometry(this, iX, iY, iWidth, iHeight);
211}
212
213void UIPopupStack::sltPopupPaneRemoved(QString)
214{
215 /* Move focus to the parent: */
216 if (parentWidget())
217 parentWidget()->setFocus();
218}
219
220void UIPopupStack::sltPopupPanesRemoved()
221{
222 /* Ask popup-center to remove us: */
223 emit sigRemove(m_strID);
224}
225
226void UIPopupStack::prepare()
227{
228 /* Configure background: */
229 setAutoFillBackground(false);
230#if defined(VBOX_WS_WIN) || defined (VBOX_WS_MAC)
231 /* Using Qt API to enable translucent background for the Win/Mac host: */
232 setAttribute(Qt::WA_TranslucentBackground);
233#endif
234
235#ifdef VBOX_WS_MAC
236 /* Do not hide popup-stack: */
237 setAttribute(Qt::WA_MacAlwaysShowToolWindow);
238#endif
239
240 /* Prepare content: */
241 prepareContent();
242}
243
244void UIPopupStack::prepareContent()
245{
246 /* Create main-layout: */
247 m_pMainLayout = new QVBoxLayout(this);
248 {
249 /* Configure main-layout: */
250 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
251 /* Create scroll-area: */
252 m_pScrollArea = new QScrollArea;
253 {
254 /* Configure scroll-area: */
255 VBoxGlobal::setCursor(m_pScrollArea, Qt::ArrowCursor);
256 m_pScrollArea->setWidgetResizable(true);
257 m_pScrollArea->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
258 m_pScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
259 //m_pScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
260 QPalette pal = m_pScrollArea->palette();
261 pal.setColor(QPalette::Window, QColor(Qt::transparent));
262 m_pScrollArea->setPalette(pal);
263 /* Create scroll-viewport: */
264 m_pScrollViewport = new UIPopupStackViewport;
265 {
266 /* Configure scroll-viewport: */
267 VBoxGlobal::setCursor(m_pScrollViewport, Qt::ArrowCursor);
268 /* Connect scroll-viewport: */
269 connect(this, &UIPopupStack::sigProposeStackViewportSize,
270 m_pScrollViewport, &UIPopupStackViewport::sltHandleProposalForSize);
271 connect(m_pScrollViewport, SIGNAL(sigSizeHintChanged()),
272 this, SLOT(sltAdjustGeometry()));
273 connect(m_pScrollViewport, SIGNAL(sigPopupPaneDone(QString, int)),
274 this, SIGNAL(sigPopupPaneDone(QString, int)));
275 connect(m_pScrollViewport, SIGNAL(sigPopupPaneRemoved(QString)),
276 this, SLOT(sltPopupPaneRemoved(QString)));
277 connect(m_pScrollViewport, SIGNAL(sigPopupPanesRemoved()),
278 this, SLOT(sltPopupPanesRemoved()));
279 }
280 /* Assign scroll-viewport to scroll-area: */
281 m_pScrollArea->setWidget(m_pScrollViewport);
282 }
283 /* Add scroll-area to layout: */
284 m_pMainLayout->addWidget(m_pScrollArea);
285 }
286}
287
288void UIPopupStack::propagateSize()
289{
290 /* Make sure parent is currently set: */
291 if (!parent())
292 return;
293
294 /* Get parent size: */
295 QSize newSize = parentWidget()->size();
296 /* Subtract left/right layout margins: */
297 if (m_pMainLayout)
298 {
299 int iLeft, iTop, iRight, iBottom;
300 m_pMainLayout->getContentsMargins(&iLeft, &iTop, &iRight, &iBottom);
301 newSize.setWidth(newSize.width() - (iLeft + iRight));
302 newSize.setHeight(newSize.height() - (iTop + iBottom));
303 }
304 /* Subtract scroll-area frame-width: */
305 if (m_pScrollArea)
306 {
307 newSize.setWidth(newSize.width() - (2 * m_pScrollArea->frameWidth()));
308 newSize.setHeight(newSize.height() - (2 * m_pScrollArea->frameWidth()));
309 }
310 newSize.setHeight(newSize.height() - (m_iParentMenuBarHeight + m_iParentStatusBarHeight));
311
312 /* Propose resulting size to viewport: */
313 emit sigProposeStackViewportSize(newSize);
314}
315
316/* static */
317int UIPopupStack::parentMenuBarHeight(QWidget *pParent)
318{
319 /* Menu-bar can exist only on QMainWindow sub-class: */
320 if (pParent)
321 {
322 if (QMainWindow *pMainWindow = qobject_cast<QMainWindow*>(pParent))
323 {
324 /* Search for existing menu-bar child: */
325 if (QMenuBar *pMenuBar = pMainWindow->findChild<QMenuBar*>())
326 return pMenuBar->height();
327 }
328 }
329 /* Zero by default: */
330 return 0;
331}
332
333/* static */
334int UIPopupStack::parentStatusBarHeight(QWidget *pParent)
335{
336 /* Status-bar can exist only on QMainWindow sub-class: */
337 if (pParent)
338 {
339 if (QMainWindow *pMainWindow = qobject_cast<QMainWindow*>(pParent))
340 {
341 /* Search for existing status-bar child: */
342 if (QStatusBar *pStatusBar = pMainWindow->findChild<QStatusBar*>())
343 if (pStatusBar->isVisible())
344 return pStatusBar->height();
345
346 }
347 }
348 /* Zero by default: */
349 return 0;
350}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use