VirtualBox

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

Last change on this file was 104290, checked in by vboxsync, 5 weeks ago

FE/Qt. bugref:10622. Using new UITranslationEventListener in the runtime UI related classes.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use