VirtualBox

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

Last change on this file since 103988 was 98103, checked in by vboxsync, 21 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: UIGraphicsScrollArea.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGraphicsScrollArea class implementation.
4 */
5
6/*
7 * Copyright (C) 2019-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 <QGraphicsScene>
30#include <QGraphicsView>
31
32/* GUI includes: */
33#include "UIGraphicsScrollArea.h"
34#include "UIGraphicsScrollBar.h"
35#ifdef VBOX_WS_MAC
36# include "VBoxUtils.h"
37#endif
38
39
40UIGraphicsScrollArea::UIGraphicsScrollArea(Qt::Orientation enmOrientation, QGraphicsScene *pScene /* = 0 */)
41 : m_enmOrientation(enmOrientation)
42 , m_fAutoHideMode(true)
43 , m_pScrollBar(0)
44 , m_pViewport(0)
45{
46 pScene->addItem(this);
47 prepare();
48}
49
50UIGraphicsScrollArea::UIGraphicsScrollArea(Qt::Orientation enmOrientation, QIGraphicsWidget *pParent /* = 0 */)
51 : QIGraphicsWidget(pParent)
52 , m_enmOrientation(enmOrientation)
53 , m_fAutoHideMode(true)
54 , m_pScrollBar(0)
55 , m_pViewport(0)
56{
57 prepare();
58}
59
60QSizeF UIGraphicsScrollArea::minimumSizeHint() const
61{
62 /* Minimum size-hint of scroll-bar by default: */
63 QSizeF msh = m_pScrollBar->minimumSizeHint();
64 if (m_pViewport)
65 {
66 switch (m_enmOrientation)
67 {
68 case Qt::Horizontal:
69 {
70 /* Expand it with viewport height: */
71 const int iWidgetHeight = m_pViewport->size().height();
72 if (m_fAutoHideMode)
73 {
74 if (msh.height() < iWidgetHeight)
75 msh.setHeight(iWidgetHeight);
76 }
77 else
78 msh.setHeight(msh.height() + iWidgetHeight);
79 break;
80 }
81 case Qt::Vertical:
82 {
83 /* Expand it with viewport width: */
84 const int iWidgetWidth = m_pViewport->size().width();
85 if (m_fAutoHideMode)
86 {
87 if (msh.width() < iWidgetWidth)
88 msh.setWidth(iWidgetWidth);
89 }
90 else
91 msh.setWidth(msh.width() + iWidgetWidth);
92 break;
93 }
94 }
95 }
96 return msh;
97}
98
99void UIGraphicsScrollArea::setViewport(QIGraphicsWidget *pViewport)
100{
101 /* Forget previous widget: */
102 if (m_pViewport)
103 {
104 m_pViewport->removeEventFilter(this);
105 m_pViewport->setParentItem(0);
106 m_pViewport = 0;
107 }
108
109 /* Remember passed widget: */
110 if (pViewport)
111 {
112 m_pViewport = pViewport;
113 m_pViewport->setParentItem(this);
114 m_pViewport->installEventFilter(this);
115 }
116
117 /* Layout widgets: */
118 layoutWidgets();
119}
120
121QIGraphicsWidget *UIGraphicsScrollArea::viewport() const
122{
123 return m_pViewport;
124}
125
126int UIGraphicsScrollArea::scrollingValue() const
127{
128 return m_pScrollBar->value();
129}
130
131void UIGraphicsScrollArea::setScrollingValue(int iValue)
132{
133 iValue = qMax(iValue, 0);
134 iValue = qMin(iValue, m_pScrollBar->maximum());
135 m_pScrollBar->setValue(iValue);
136}
137
138void UIGraphicsScrollArea::scrollBy(int iDelta)
139{
140 m_pScrollBar->setValue(m_pScrollBar->value() + iDelta);
141}
142
143void UIGraphicsScrollArea::makeSureRectIsVisible(const QRectF &rect)
144{
145 /* Make sure rect size is bound by the scroll-area size: */
146 QRectF actualRect = rect;
147 QSizeF actualRectSize = actualRect.size();
148 actualRectSize = actualRectSize.boundedTo(size());
149 actualRect.setSize(actualRectSize);
150
151 /* Acquire scroll-area scene position: */
152 const QPointF saPos = mapToScene(QPointF(0, 0));
153
154 switch (m_enmOrientation)
155 {
156 /* Scroll viewport horizontally: */
157 case Qt::Horizontal:
158 {
159 /* If rectangle is at least partially right of visible area: */
160 if (actualRect.x() + actualRect.width() - saPos.x() > size().width())
161 m_pScrollBar->setValue(m_pScrollBar->value() + actualRect.x() + actualRect.width() - saPos.x() - size().width());
162 /* If rectangle is at least partially left of visible area: */
163 else if (actualRect.x() - saPos.x() < 0)
164 m_pScrollBar->setValue(m_pScrollBar->value() + actualRect.x() - saPos.x());
165 break;
166 }
167 /* Scroll viewport vertically: */
168 case Qt::Vertical:
169 {
170 /* If rectangle is at least partially under visible area: */
171 if (actualRect.y() + actualRect.height() - saPos.y() > size().height())
172 m_pScrollBar->setValue(m_pScrollBar->value() + actualRect.y() + actualRect.height() - saPos.y() - size().height());
173 /* If rectangle is at least partially above visible area: */
174 else if (actualRect.y() - saPos.y() < 0)
175 m_pScrollBar->setValue(m_pScrollBar->value() + actualRect.y() - saPos.y());
176 break;
177 }
178 }
179}
180
181bool UIGraphicsScrollArea::eventFilter(QObject *pObject, QEvent *pEvent)
182{
183 /* Handle layout requests for m_pViewport if set: */
184 if ( m_pViewport
185 && pObject == m_pViewport
186 && pEvent->type() == QEvent::LayoutRequest)
187 layoutWidgets();
188
189 /* Handle wheel events for first scene view if set: */
190 if ( scene()
191 && !scene()->views().isEmpty()
192 && pObject == scene()->views().first()
193 && pEvent->type() == QEvent::Wheel)
194 {
195 QWheelEvent *pWheelEvent = static_cast<QWheelEvent*>(pEvent);
196 const QPoint angleDelta = pWheelEvent->angleDelta();
197#ifdef VBOX_WS_MAC
198 const QPoint pixelDelta = pWheelEvent->pixelDelta();
199#endif
200 switch (m_enmOrientation)
201 {
202 /* Scroll viewport horizontally: */
203 case Qt::Horizontal:
204 {
205 if (angleDelta.x() > 0)
206#ifdef VBOX_WS_MAC
207 m_pScrollBar->setValue(m_pScrollBar->value() - pixelDelta.y());
208#else
209 m_pScrollBar->setValue(m_pScrollBar->value() - m_pScrollBar->step());
210#endif
211 else if (angleDelta.x() < 0)
212#ifdef VBOX_WS_MAC
213 m_pScrollBar->setValue(m_pScrollBar->value() - pixelDelta.y());
214#else
215 m_pScrollBar->setValue(m_pScrollBar->value() + m_pScrollBar->step());
216#endif
217 break;
218 }
219 /* Scroll viewport vertically: */
220 case Qt::Vertical:
221 {
222 if (angleDelta.y() > 0)
223#ifdef VBOX_WS_MAC
224 m_pScrollBar->setValue(m_pScrollBar->value() - pixelDelta.y());
225#else
226 m_pScrollBar->setValue(m_pScrollBar->value() - m_pScrollBar->step());
227#endif
228 else if (angleDelta.y() < 0)
229#ifdef VBOX_WS_MAC
230 m_pScrollBar->setValue(m_pScrollBar->value() - pixelDelta.y());
231#else
232 m_pScrollBar->setValue(m_pScrollBar->value() + m_pScrollBar->step());
233#endif
234 break;
235 }
236 }
237 }
238
239 /* Call to base-class: */
240 return QIGraphicsWidget::eventFilter(pObject, pEvent);
241}
242
243void UIGraphicsScrollArea::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
244{
245 /* Call to base-class: */
246 QIGraphicsWidget::resizeEvent(pEvent);
247
248 /* Layout widgets: */
249 layoutWidgets();
250}
251
252void UIGraphicsScrollArea::sltHandleScrollBarValueChange(int iValue)
253{
254 switch (m_enmOrientation)
255 {
256 /* Shift viewport horizontally: */
257 case Qt::Horizontal: m_pViewport->setPos(-iValue, 0); break;
258 /* Shift viewport vertically: */
259 case Qt::Vertical: m_pViewport->setPos(0, -iValue); break;
260 }
261}
262
263void UIGraphicsScrollArea::prepare()
264{
265 /* Prepare/layout widgets: */
266 prepareWidgets();
267 layoutWidgets();
268}
269
270void UIGraphicsScrollArea::prepareWidgets()
271{
272#ifdef VBOX_WS_MAC
273 /* Check whether scroll-bar is in auto-hide (overlay) mode: */
274 m_fAutoHideMode = darwinIsScrollerStyleOverlay();
275#endif
276
277 /* Create scroll-bar: */
278 m_pScrollBar = new UIGraphicsScrollBar(m_enmOrientation, m_fAutoHideMode, this);
279 if (m_pScrollBar)
280 {
281 m_pScrollBar->setZValue(1);
282 connect(m_pScrollBar, &UIGraphicsScrollBar::sigValueChanged,
283 this, &UIGraphicsScrollArea::sltHandleScrollBarValueChange);
284 }
285}
286
287void UIGraphicsScrollArea::layoutWidgets()
288{
289 switch (m_enmOrientation)
290 {
291 case Qt::Horizontal:
292 {
293 /* Align scroll-bar horizontally: */
294 m_pScrollBar->resize(size().width(), m_pScrollBar->minimumSizeHint().height());
295 m_pScrollBar->setPos(0, size().height() - m_pScrollBar->size().height());
296 if (m_pViewport)
297 {
298 /* Adjust scroll-bar maximum value according to viewport width: */
299 const int iWidth = size().width();
300 const int iWidgetWidth = m_pViewport->size().width();
301 if (iWidgetWidth > iWidth)
302 m_pScrollBar->setMaximum(iWidgetWidth - iWidth);
303 else
304 m_pScrollBar->setMaximum(0);
305 }
306 break;
307 }
308 case Qt::Vertical:
309 {
310 /* Align scroll-bar vertically: */
311 m_pScrollBar->resize(m_pScrollBar->minimumSizeHint().width(), size().height());
312 m_pScrollBar->setPos(size().width() - m_pScrollBar->size().width(), 0);
313 if (m_pViewport)
314 {
315 /* Adjust scroll-bar maximum value according to viewport height: */
316 const int iHeight = size().height();
317 const int iWidgetHeight = m_pViewport->size().height();
318 if (iWidgetHeight > iHeight)
319 m_pScrollBar->setMaximum(iWidgetHeight - iHeight);
320 else
321 m_pScrollBar->setMaximum(0);
322 }
323 break;
324 }
325 }
326
327 /* Make scroll-bar visible only when there is viewport and maximum more than minimum: */
328 m_pScrollBar->setVisible(m_pViewport && m_pScrollBar->maximum() > m_pScrollBar->minimum());
329
330 if (m_pViewport)
331 {
332 switch (m_enmOrientation)
333 {
334 case Qt::Horizontal:
335 {
336 /* Calculate geometry deduction: */
337 const int iDeduction = !m_fAutoHideMode && m_pScrollBar->isVisible() ? m_pScrollBar->minimumSizeHint().height() : 0;
338 /* Align viewport and shift it horizontally: */
339 m_pViewport->resize(m_pViewport->minimumSizeHint().width(), size().height() - iDeduction);
340 m_pViewport->setPos(-m_pScrollBar->value(), 0);
341 break;
342 }
343 case Qt::Vertical:
344 {
345 /* Calculate geometry deduction: */
346 const int iDeduction = !m_fAutoHideMode && m_pScrollBar->isVisible() ? m_pScrollBar->minimumSizeHint().width() : 0;
347 /* Align viewport and shift it vertically: */
348 m_pViewport->resize(size().width() - iDeduction, m_pViewport->minimumSizeHint().height());
349 m_pViewport->setPos(0, -m_pScrollBar->value());
350 break;
351 }
352 }
353 }
354}
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