VirtualBox

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

Last change on this file was 103795, checked in by vboxsync, 3 months ago

FE/Qt: bugref:10450: Get rid of old Qt hack for versions less than 5.11.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use