VirtualBox

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

Last change on this file since 100347 was 100064, checked in by vboxsync, 18 months ago

FE/Qt: bugref:10421. Replacing VBOX_WS_X11 with VBOX_WS_NIX.

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