VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UISlidingToolBar.cpp@ 103988

Last change on this file since 103988 was 101013, checked in by vboxsync, 15 months ago

FE/Qt: bugref:10513: Moving menu-bar/status-bar editors from widgets to settings/editors.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 KB
Line 
1/* $Id: UISlidingToolBar.cpp 101013 2023-09-04 18:43:56Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UISlidingToolBar class implementation.
4 */
5
6/*
7 * Copyright (C) 2014-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 <QHBoxLayout>
30
31/* GUI includes: */
32#include "UICommon.h"
33#include "UIDesktopWidgetWatchdog.h"
34#include "UISlidingToolBar.h"
35#include "UIAnimationFramework.h"
36#include "UIMachineWindow.h"
37#ifdef VBOX_WS_MAC
38# include "VBoxUtils-darwin.h"
39#endif
40
41
42UISlidingToolBar::UISlidingToolBar(QWidget *pParentWidget, QWidget *pIndentWidget, QWidget *pChildWidget, Position enmPosition)
43 : QWidget(pParentWidget, Qt::Tool | Qt::FramelessWindowHint)
44 , m_enmPosition(enmPosition)
45 , m_parentRect(pParentWidget ? pParentWidget->geometry() : QRect())
46 , m_indentRect(pIndentWidget ? pIndentWidget->geometry() : QRect())
47 , m_pAnimation(0)
48 , m_fExpanded(false)
49 , m_pMainLayout(0)
50 , m_pArea(0)
51 , m_pWidget(pChildWidget)
52{
53 /* Prepare: */
54 prepare();
55}
56
57#ifdef VBOX_WS_MAC
58bool UISlidingToolBar::event(QEvent *pEvent)
59{
60 /* Depending on event-type: */
61 switch (pEvent->type())
62 {
63 case QEvent::Resize:
64 case QEvent::WindowActivate:
65 {
66 // WORKAROUND:
67 // By some strange reason
68 // cocoa resets NSWindow::setHasShadow option
69 // for frameless windows on every window resize/activation.
70 // So we have to make sure window still has no shadows.
71 darwinSetWindowHasShadow(this, false);
72 break;
73 }
74 default:
75 break;
76 }
77 /* Call to base-class: */
78 return QWidget::event(pEvent);
79}
80#endif /* VBOX_WS_MAC */
81
82void UISlidingToolBar::showEvent(QShowEvent *)
83{
84 /* If window isn't expanded: */
85 if (!m_fExpanded)
86 {
87 /* Start expand animation: */
88 emit sigShown();
89 }
90}
91
92void UISlidingToolBar::closeEvent(QCloseEvent *pEvent)
93{
94 /* If window isn't expanded: */
95 if (!m_fExpanded)
96 {
97 /* Ignore close-event: */
98 pEvent->ignore();
99 return;
100 }
101
102 /* If animation state is Final: */
103 const QString strAnimationState = property("AnimationState").toString();
104 bool fAnimationComplete = strAnimationState == "Final";
105 if (fAnimationComplete)
106 {
107 /* Ignore close-event: */
108 pEvent->ignore();
109 /* And start collapse animation: */
110 emit sigCollapse();
111 }
112}
113
114void UISlidingToolBar::sltParentGeometryChanged(const QRect &parentRect)
115{
116 /* Update rectangle: */
117 m_parentRect = parentRect;
118 /* Adjust geometry: */
119 adjustGeometry();
120 /* Update animation: */
121 updateAnimation();
122}
123
124void UISlidingToolBar::prepare()
125{
126 /* Tell the application we are not that important: */
127 setAttribute(Qt::WA_QuitOnClose, false);
128 /* Delete window when closed: */
129 setAttribute(Qt::WA_DeleteOnClose);
130
131#if defined(VBOX_WS_MAC) || defined(VBOX_WS_WIN)
132 /* Make sure we have no background
133 * until the first one paint-event: */
134 setAttribute(Qt::WA_NoSystemBackground);
135 /* Use Qt API to enable translucency: */
136 setAttribute(Qt::WA_TranslucentBackground);
137#elif defined(VBOX_WS_NIX)
138 if (uiCommon().isCompositingManagerRunning())
139 {
140 /* Use Qt API to enable translucency: */
141 setAttribute(Qt::WA_TranslucentBackground);
142 }
143#endif /* VBOX_WS_NIX */
144
145 /* Prepare contents: */
146 prepareContents();
147 /* Prepare geometry: */
148 prepareGeometry();
149 /* Prepare animation: */
150 prepareAnimation();
151}
152
153void UISlidingToolBar::prepareContents()
154{
155 /* Create main-layout: */
156 m_pMainLayout = new QHBoxLayout(this);
157 if (m_pMainLayout)
158 {
159 /* Configure main-layout: */
160 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
161 m_pMainLayout->setSpacing(0);
162 /* Create area: */
163 m_pArea = new QWidget;
164 if (m_pArea)
165 {
166 /* Configure area: */
167 m_pArea->setAcceptDrops(true);
168 m_pArea->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
169 QPalette pal1 = m_pArea->palette();
170 pal1.setColor(QPalette::Window, QColor(Qt::transparent));
171 m_pArea->setPalette(pal1);
172 /* Make sure valid child-widget passed: */
173 if (m_pWidget)
174 {
175 /* Configure child-widget: */
176 QPalette pal2 = m_pWidget->palette();
177 pal2.setColor(QPalette::Window, QApplication::palette().color(QPalette::Window));
178 m_pWidget->setPalette(pal2);
179 /* Using abstract (old-style) connection here(!) since the base classes can be different: */
180 connect(m_pWidget, SIGNAL(sigCancelClicked()), this, SLOT(close()));
181 /* Add child-widget into area: */
182 m_pWidget->setParent(m_pArea);
183 }
184 /* Add area into main-layout: */
185 m_pMainLayout->addWidget(m_pArea);
186 }
187 }
188}
189
190void UISlidingToolBar::prepareGeometry()
191{
192 /* Prepare geometry based on parent and sub-window size-hints,
193 * But move sub-window to initial position: */
194 const QSize sh = m_pWidget->sizeHint();
195 switch (m_enmPosition)
196 {
197 case Position_Top:
198 {
199 UIDesktopWidgetWatchdog::setTopLevelGeometry(this, m_parentRect.x(), m_parentRect.y() + m_indentRect.height(),
200 qMax(m_parentRect.width(), sh.width()), sh.height());
201 m_pWidget->setGeometry(0, -sh.height(), qMax(width(), sh.width()), sh.height());
202 break;
203 }
204 case Position_Bottom:
205 {
206 UIDesktopWidgetWatchdog::setTopLevelGeometry(this, m_parentRect.x(), m_parentRect.y() + m_parentRect.height() - m_indentRect.height() - sh.height(),
207 qMax(m_parentRect.width(), sh.width()), sh.height());
208 m_pWidget->setGeometry(0, sh.height(), qMax(width(), sh.width()), sh.height());
209 break;
210 }
211 }
212
213#ifdef VBOX_WS_NIX
214 if (!uiCommon().isCompositingManagerRunning())
215 {
216 /* Use Xshape otherwise: */
217 setMask(m_pWidget->geometry());
218 }
219#endif
220
221#ifdef VBOX_WS_WIN
222 /* Raise tool-window for proper z-order. */
223 raise();
224#endif
225
226 /* Activate window after it was shown: */
227 connect(this, &UISlidingToolBar::sigShown,
228 this, &UISlidingToolBar::sltActivateWindow, Qt::QueuedConnection);
229 /* Update window geometry after parent geometry changed: */
230 /* Leave this in the old connection syntax for now: */
231 connect(parent(), SIGNAL(sigGeometryChange(const QRect&)),
232 this, SLOT(sltParentGeometryChanged(const QRect&)));
233}
234
235void UISlidingToolBar::prepareAnimation()
236{
237 /* Prepare sub-window geometry animation itself: */
238 connect(this, SIGNAL(sigShown()), this, SIGNAL(sigExpand()), Qt::QueuedConnection);
239 m_pAnimation = UIAnimation::installPropertyAnimation(this,
240 "widgetGeometry",
241 "startWidgetGeometry", "finalWidgetGeometry",
242 SIGNAL(sigExpand()), SIGNAL(sigCollapse()));
243 connect(m_pAnimation, &UIAnimation::sigStateEnteredStart, this, &UISlidingToolBar::sltMarkAsCollapsed);
244 connect(m_pAnimation, &UIAnimation::sigStateEnteredFinal, this, &UISlidingToolBar::sltMarkAsExpanded);
245 /* Update geometry animation: */
246 updateAnimation();
247}
248
249void UISlidingToolBar::adjustGeometry()
250{
251 /* Adjust geometry based on parent and sub-window size-hints: */
252 const QSize sh = m_pWidget->sizeHint();
253 switch (m_enmPosition)
254 {
255 case Position_Top:
256 {
257 UIDesktopWidgetWatchdog::setTopLevelGeometry(this, m_parentRect.x(), m_parentRect.y() + m_indentRect.height(),
258 qMax(m_parentRect.width(), sh.width()), sh.height());
259 break;
260 }
261 case Position_Bottom:
262 {
263 UIDesktopWidgetWatchdog::setTopLevelGeometry(this, m_parentRect.x(), m_parentRect.y() + m_parentRect.height() - m_indentRect.height() - sh.height(),
264 qMax(m_parentRect.width(), sh.width()), sh.height());
265 break;
266 }
267 }
268 /* And move sub-window to corresponding position: */
269 m_pWidget->setGeometry(0, 0, qMax(width(), sh.width()), sh.height());
270
271#ifdef VBOX_WS_NIX
272 if (!uiCommon().isCompositingManagerRunning())
273 {
274 /* Use Xshape otherwise: */
275 setMask(m_pWidget->geometry());
276 }
277#endif
278
279#ifdef VBOX_WS_WIN
280 /* Raise tool-window for proper z-order. */
281 raise();
282#endif
283}
284
285void UISlidingToolBar::updateAnimation()
286{
287 /* Skip if no animation created: */
288 if (!m_pAnimation)
289 return;
290
291 /* Recalculate sub-window geometry animation boundaries based on size-hint: */
292 const QSize sh = m_pWidget->sizeHint();
293 switch (m_enmPosition)
294 {
295 case Position_Top: m_startWidgetGeometry = QRect(0, -sh.height(), qMax(width(), sh.width()), sh.height()); break;
296 case Position_Bottom: m_startWidgetGeometry = QRect(0, sh.height(), qMax(width(), sh.width()), sh.height()); break;
297 }
298 m_finalWidgetGeometry = QRect(0, 0, qMax(width(), sh.width()), sh.height());
299 m_pAnimation->update();
300}
301
302void UISlidingToolBar::setWidgetGeometry(const QRect &rect)
303{
304 /* Apply sub-window geometry: */
305 m_pWidget->setGeometry(rect);
306
307#ifdef VBOX_WS_NIX
308 if (!uiCommon().isCompositingManagerRunning())
309 {
310 /* Use Xshape otherwise: */
311 setMask(m_pWidget->geometry());
312 }
313#endif
314}
315
316QRect UISlidingToolBar::widgetGeometry() const
317{
318 /* Return sub-window geometry: */
319 return m_pWidget->geometry();
320}
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