VirtualBox

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

© 2023 Oracle
ContactPrivacy policyTerms of Use