Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickscrollbar.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
8
9#include <QtQml/qqmlinfo.h>
10#include <QtQuick/private/qquickflickable_p.h>
11#if QT_CONFIG(accessibility)
12#include <QtQuick/private/qquickaccessibleattached_p.h>
13#endif
14
16
17/*!
18 \qmltype ScrollBar
19 \inherits Control
20//! \nativetype QQuickScrollBar
21 \inqmlmodule QtQuick.Controls
22 \since 5.7
23 \ingroup qtquickcontrols-indicators
24 \brief Vertical or horizontal interactive scroll bar.
25
26 \image qtquickcontrols-scrollbar.gif
27
28 ScrollBar is an interactive bar that can be used to scroll to a specific
29 position. A scroll bar can be either \l vertical or \l horizontal, and can
30 be attached to any \l Flickable, such as \l ListView and \l GridView.
31 It can also be used with \l ScrollView.
32
33 \code
34 Flickable {
35 // ...
36 ScrollBar.vertical: ScrollBar { }
37 }
38 \endcode
39
40 \section1 Attaching ScrollBar to a Flickable
41
42 When ScrollBar is attached \l {ScrollBar::vertical}{vertically} or
43 \l {ScrollBar::horizontal}{horizontally} to a Flickable, its geometry and
44 the following properties are automatically set and updated as appropriate:
45
46 \list
47 \li \l orientation
48 \li \l position
49 \li \l {ScrollBar::} {size}
50 \li \l active
51 \endlist
52
53 An attached ScrollBar re-parents itself to the target Flickable. A vertically
54 attached ScrollBar resizes itself to the height of the Flickable, and positions
55 itself to either side of it based on the \l {Control::mirrored}{layout direction}.
56 A horizontally attached ScrollBar resizes itself to the width of the Flickable,
57 and positions itself to the bottom. The automatic geometry management can be disabled
58 by specifying another parent for the attached ScrollBar. This can be useful, for
59 example, if the ScrollBar should be placed outside a clipping Flickable. This is
60 demonstrated by the following example:
61
62 \code
63 Flickable {
64 id: flickable
65 clip: true
66 // ...
67 ScrollBar.vertical: ScrollBar {
68 parent: flickable.parent
69 anchors.top: flickable.top
70 anchors.left: flickable.right
71 anchors.bottom: flickable.bottom
72 }
73 }
74 \endcode
75
76 Notice that ScrollBar does not filter key events of the Flickable it is
77 attached to. The following example illustrates how to implement scrolling
78 with up and down keys:
79
80 \code
81 Flickable {
82 focus: true
83
84 Keys.onUpPressed: scrollBar.decrease()
85 Keys.onDownPressed: scrollBar.increase()
86
87 ScrollBar.vertical: ScrollBar { id: scrollBar }
88 }
89 \endcode
90
91 \section1 Binding the Active State of Horizontal and Vertical Scroll Bars
92
93 Horizontal and vertical scroll bars do not share the \l active state with
94 each other by default. In order to keep both bars visible whilst scrolling
95 to either direction, establish a two-way binding between the active states
96 as presented by the following example:
97
98 \snippet qtquickcontrols-scrollbar-active.qml 1
99
100 \section1 Non-attached Scroll Bars
101
102 It is possible to create an instance of ScrollBar without using the
103 attached property API. This is useful when the behavior of the attached
104 scroll bar is not sufficient or a \l Flickable is not in use. In the
105 following example, horizontal and vertical scroll bars are used to
106 scroll over the text without using \l Flickable:
107
108 \snippet qtquickcontrols-scrollbar-non-attached.qml 1
109
110 \image qtquickcontrols-scrollbar-non-attached.png
111
112 When using a non-attached ScrollBar, the following must be done manually:
113
114 \list
115 \li Layout the scroll bar (with the \l {Item::}{x} and \l {Item::}{y} or
116 \l {Item::}{anchors} property, for example).
117 \li Set the \l size and \l position properties to determine the size and position
118 of the scroll bar in relation to the scrolled item.
119 \li Set the \l active property to determine when the scroll bar will be
120 visible.
121 \endlist
122
123 \include varying-delegate-heights-section.qdocinc {file} {1} {ScrollBar}
124
125 \sa ScrollIndicator, ScrollView, {Customizing ScrollBar}, {Indicator Controls}
126*/
127
128static const QQuickItemPrivate::ChangeTypes QsbChangeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed;
129static const QQuickItemPrivate::ChangeTypes QsbHorizontalChangeTypes = QsbChangeTypes | QQuickItemPrivate::ImplicitHeight;
130static const QQuickItemPrivate::ChangeTypes QsbVerticalChangeTypes = QsbChangeTypes | QQuickItemPrivate::ImplicitWidth;
131
133{
134 qreal visualPos = position;
135
136 if (minimumSize > size && size != 1.0)
137 visualPos = position / (1.0 - size) * (1.0 - minimumSize);
138
139 qreal maximumSize = qMax<qreal>(0.0, 1.0 - visualPos);
140 qreal visualSize = qMax<qreal>(minimumSize,
141 qMin<qreal>(qMax(size, minimumSize) + qMin<qreal>(0, visualPos),
142 maximumSize));
143
144 visualPos = qMax<qreal>(0,qMin<qreal>(visualPos,qMax<qreal>(0, 1.0 - visualSize)));
145
146 return VisualArea(visualPos, visualSize);
147}
148
150{
151 if (minimumSize > size && minimumSize != 1.0)
152 return position * (1.0 - size) / (1.0 - minimumSize);
153 return position;
154}
155
157{
158 const qreal effectiveStep = stepSize * (1.0 - size);
159 if (qFuzzyIsNull(effectiveStep))
160 return position;
161
162 return qRound(position / effectiveStep) * effectiveStep;
163}
164
165qreal QQuickScrollBarPrivate::positionAt(const QPointF &point) const
166{
167 Q_Q(const QQuickScrollBar);
168 if (orientation == Qt::Horizontal)
169 return logicalPosition(point.x() - q->leftPadding()) / q->availableWidth();
170 else
171 return logicalPosition(point.y() - q->topPadding()) / q->availableHeight();
172}
173
175{
176 Q_Q(QQuickScrollBar);
177 if (interactive == enabled)
178 return;
179
180 interactive = enabled;
181 if (interactive) {
182 q->setAcceptedMouseButtons(Qt::LeftButton);
183#if QT_CONFIG(quicktemplates2_multitouch)
184 q->setAcceptTouchEvents(true);
185#endif
186#if QT_CONFIG(cursor)
187 q->setCursor(Qt::ArrowCursor);
188#endif
189 } else {
190 q->setAcceptedMouseButtons(Qt::NoButton);
191#if QT_CONFIG(quicktemplates2_multitouch)
192 q->setAcceptTouchEvents(false);
193#endif
194#if QT_CONFIG(cursor)
195 q->unsetCursor();
196#endif
197 q->ungrabMouse();
198 }
199 emit q->interactiveChanged();
200}
201
203{
204 Q_Q(QQuickScrollBar);
205#if QT_CONFIG(quicktemplates2_hover)
206 bool hover = hovered;
207#else
208 bool hover = false;
209#endif
210 q->setActive(moving || (interactive && (pressed || hover)));
211}
212
214{
215 Q_Q(QQuickScrollBar);
216 if (!contentItem)
217 return;
218
219 // - negative overshoot (pos < 0): clamp the pos to 0, and deduct the overshoot from the size
220 // - positive overshoot (pos + size > 1): clamp the size to 1-pos
221 const VisualArea visual = visualArea();
222
223 if (orientation == Qt::Horizontal) {
224 contentItem->setPosition(QPointF(q->leftPadding() + visual.position * q->availableWidth(), q->topPadding()));
225 contentItem->setSize(QSizeF(q->availableWidth() * visual.size, q->availableHeight()));
226 } else {
227 contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + visual.position * q->availableHeight()));
228 contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * visual.size));
229 }
230}
231
233{
234 Q_Q(QQuickScrollBar);
235 QQuickControlPrivate::itemImplicitWidthChanged(item);
236 QQuickIndicatorButton *indicatorButton = q->decreaseVisual();
237 if (!indicatorButton || item != indicatorButton->indicator()) {
238 indicatorButton = q->increaseVisual();
239 if (!indicatorButton || item != indicatorButton->indicator())
240 return;
241 }
242 if (indicatorButton)
243 emit indicatorButton->implicitIndicatorWidthChanged();
244}
245
247{
248 Q_Q(QQuickScrollBar);
249 QQuickControlPrivate::itemImplicitHeightChanged(item);
250 QQuickIndicatorButton *indicatorButton = q->decreaseVisual();
251 if (!indicatorButton || item != indicatorButton->indicator()) {
252 indicatorButton = q->increaseVisual();
253 if (!indicatorButton || item != indicatorButton->indicator())
254 return;
255 }
256 if (indicatorButton)
257 emit indicatorButton->implicitIndicatorHeightChanged();
258}
259
260bool QQuickScrollBarPrivate::handlePress(const QPointF &point, ulong timestamp)
261{
262 Q_Q(QQuickScrollBar);
263 QQuickControlPrivate::handlePress(point, timestamp);
264 if (QQuickIndicatorButton *indicatorButton = q->decreaseVisual()) {
265 QQuickItem *decreaseArrow = indicatorButton->indicator();
266 if (decreaseArrow && decreaseArrow->contains(q->mapToItem(decreaseArrow, point + QPointF(0.5, 0.5)))) {
267 indicatorButton->setPressed(true);
268 q->decrease();
269 return true;
270 }
271 }
272
273 if (QQuickIndicatorButton *increaseObject = q->increaseVisual()) {
274 QQuickItem *increaseArrow = increaseObject->indicator();
275 if (increaseArrow && increaseArrow->contains(q->mapToItem(increaseArrow, point + QPointF(0.5, 0.5)))) {
276 increaseObject->setPressed(true);
277 q->increase();
278 return true;
279 }
280 }
281
282 offset = positionAt(point) - position;
283 qreal sz = qMax(size, logicalPosition(minimumSize));
284 if (offset < 0 || offset > sz)
285 offset = sz / 2;
286 q->setPressed(true);
287 return true;
288}
289
290bool QQuickScrollBarPrivate::handleMove(const QPointF &point, ulong timestamp)
291{
292 Q_Q(QQuickScrollBar);
293 QQuickControlPrivate::handleMove(point, timestamp);
294
295 /*
296 * handleMove() will be called as soon as you hold the mouse button down *anywhere* on the
297 * ScrollBar, including the increase/decrease button indicator areas. So without the following
298 * early return, it would move the scrollbar handle to one of its extremeties. That would
299 * ruin the behavior we would like when clicking e.g. the "increase button": To step the
300 * scrollbar gently.
301 */
302 if (!pressed)
303 return true;
304
305 qreal pos = qMax<qreal>(0.0, qMin<qreal>(positionAt(point) - offset, 1.0 - size));
306 if (snapMode == QQuickScrollBar::SnapAlways)
307 pos = snapPosition(pos);
308 q->setPosition(pos);
309 return true;
310}
311
312bool QQuickScrollBarPrivate::handleRelease(const QPointF &point, ulong timestamp)
313{
314 Q_Q(QQuickScrollBar);
315 QQuickControlPrivate::handleRelease(point, timestamp);
316
317 if (orientation == Qt::Vertical) {
318 if (point.y() < q->topPadding() || point.y() >= (q->height() - q->bottomPadding()))
319 return true;
320 } else /* orientation == Qt::Horizontal */{
321 if (point.x() < q->leftPadding() || point.x() >= (q->width() - q->rightPadding()))
322 return true;
323 }
324
325 qreal pos = qMax<qreal>(0.0, qMin<qreal>(positionAt(point) - offset, 1.0 - size));
326 if (snapMode != QQuickScrollBar::NoSnap)
327 pos = snapPosition(pos);
328 q->setPosition(pos);
329 offset = 0.0;
330 q->setPressed(false);
331 return true;
332}
333
335{
336 Q_Q(QQuickScrollBar);
337 QQuickControlPrivate::handleUngrab();
338 offset = 0.0;
339 q->setPressed(false);
340}
341
342void QQuickScrollBarPrivate::visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea)
343{
344 Q_Q(QQuickScrollBar);
345 if (!qFuzzyCompare(newVisualArea.size, oldVisualArea.size))
346 emit q->visualSizeChanged();
347 if (!qFuzzyCompare(newVisualArea.position, oldVisualArea.position))
348 emit q->visualPositionChanged();
349}
350
351void QQuickScrollBarPrivate::updateHover(const QPointF &pos, std::optional<bool> newHoverState)
352{
353 Q_Q(QQuickScrollBar);
354 auto updateHoverOnButton = [&](QQuickIndicatorButton *sbButton) {
355 if (sbButton) {
356 bool hovered = newHoverState.value_or(false);
357 if (!newHoverState.has_value()) {
358 if (QQuickItem *indicator = sbButton->indicator())
359 hovered = indicator->contains(q->mapToItem(indicator, pos));
360 }
361 sbButton->setHovered(hovered);
362 }
363 };
364 updateHoverOnButton(q->decreaseVisual());
365 updateHoverOnButton(q->increaseVisual());
366}
367
368QQuickScrollBar::QQuickScrollBar(QQuickItem *parent)
369 : QQuickControl(*(new QQuickScrollBarPrivate), parent)
370{
371 Q_D(QQuickScrollBar);
372 d->decreaseVisual = new QQuickIndicatorButton(this);
373 d->increaseVisual = new QQuickIndicatorButton(this);
374 d->setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Fixed);
375 setKeepMouseGrab(true);
376 setAcceptedMouseButtons(Qt::LeftButton);
377#if QT_CONFIG(quicktemplates2_multitouch)
378 setAcceptTouchEvents(true);
379#endif
380#if QT_CONFIG(cursor)
381 setCursor(Qt::ArrowCursor);
382#endif
383}
384
385QQuickScrollBarAttached *QQuickScrollBar::qmlAttachedProperties(QObject *object)
386{
387 return new QQuickScrollBarAttached(object);
388}
389
390/*!
391 \qmlproperty real QtQuick.Controls::ScrollBar::size
392
393 This property holds the size of the scroll bar, scaled to \c {0.0 - 1.0}.
394
395 \sa {Flickable::visibleArea.heightRatio}{Flickable::visibleArea}
396
397 This property is automatically set when the scroll bar is
398 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
399
400 \sa minimumSize, visualSize
401*/
402qreal QQuickScrollBar::size() const
403{
404 Q_D(const QQuickScrollBar);
405 return d->size;
406}
407
408void QQuickScrollBar::setSize(qreal size)
409{
410 Q_D(QQuickScrollBar);
411 if (!qt_is_finite(size))
412 return;
413 size = qBound(0.0, size, 1.0);
414 if (qFuzzyCompare(d->size, size))
415 return;
416
417 const auto oldVisualArea = d->visualArea();
418 d->size = size;
419 if (d->size + d->position > 1.0) {
420 d->setPosition(1.0 - d->size, false);
421 }
422
423 if (isComponentComplete())
424 d->resizeContent();
425 emit sizeChanged();
426 d->visualAreaChange(d->visualArea(), oldVisualArea);
427}
428
429/*!
430 \qmlproperty real QtQuick.Controls::ScrollBar::position
431
432 This property holds the position of the scroll bar, scaled to \c {0.0 - 1.0}.
433
434 The largest valid scrollbar position is \c {(1.0 - size)}. This gives
435 correct behavior for the most used case where moving the scrollbar
436 to the end will put the end of the document at the lower end of the
437 visible area of the connected Flickable.
438
439 \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea}
440
441 This property is automatically set when the scroll bar is
442 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
443
444 \sa visualPosition
445*/
446qreal QQuickScrollBar::position() const
447{
448 Q_D(const QQuickScrollBar);
449 return d->position;
450}
451
452void QQuickScrollBar::setPosition(qreal position)
453{
454 Q_D(QQuickScrollBar);
455 d->setPosition(position);
456}
457
458void QQuickScrollBarPrivate::setPosition(qreal newPosition, bool notifyVisualChange)
459{
460 Q_Q(QQuickScrollBar);
461 if (!qt_is_finite(newPosition) || qFuzzyCompare(position, newPosition))
462 return;
463
464 auto oldVisualArea = visualArea();
465 position = newPosition;
466 if (q->isComponentComplete())
468 emit q->positionChanged();
469 if (notifyVisualChange)
470 visualAreaChange(visualArea(), oldVisualArea);
471
472#if QT_CONFIG(accessibility)
473 if (QAccessible::isActive()) {
474 if (QAccessibleInterface *accessible = QAccessible::queryAccessibleInterface(q)) {
475 QAccessibleValueInterface *valueInterface = accessible->valueInterface();
476 Q_ASSERT(valueInterface);
477 QAccessibleValueChangeEvent event(q, valueInterface->currentValue());
478 QAccessible::updateAccessibility(&event);
479 }
480 }
481#endif
482}
483
484/*!
485 \qmlproperty real QtQuick.Controls::ScrollBar::stepSize
486
487 This property holds the step size. The default value is \c 0.0.
488
489 \sa snapMode, increase(), decrease()
490*/
491qreal QQuickScrollBar::stepSize() const
492{
493 Q_D(const QQuickScrollBar);
494 return d->stepSize;
495}
496
497void QQuickScrollBar::setStepSize(qreal step)
498{
499 Q_D(QQuickScrollBar);
500 if (!qt_is_finite(step) || qFuzzyCompare(d->stepSize, step))
501 return;
502
503 d->stepSize = step;
504 emit stepSizeChanged();
505}
506
507/*!
508 \qmlproperty bool QtQuick.Controls::ScrollBar::active
509
510 This property holds whether the scroll bar is active, i.e. when it's \l pressed
511 or the attached Flickable is \l {Flickable::moving}{moving}.
512
513 It is possible to keep \l {Binding the Active State of Horizontal and Vertical Scroll Bars}
514 {both horizontal and vertical bars visible} while scrolling in either direction.
515
516 This property is automatically set when the scroll bar is
517 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
518*/
519bool QQuickScrollBar::isActive() const
520{
521 Q_D(const QQuickScrollBar);
522 return d->active;
523}
524
525void QQuickScrollBar::setActive(bool active)
526{
527 Q_D(QQuickScrollBar);
528 if (d->active == active)
529 return;
530
531 d->active = active;
532 emit activeChanged();
533}
534
535/*!
536 \qmlproperty bool QtQuick.Controls::ScrollBar::pressed
537
538 This property holds whether the scroll bar is pressed.
539*/
540bool QQuickScrollBar::isPressed() const
541{
542 Q_D(const QQuickScrollBar);
543 return d->pressed;
544}
545
546void QQuickScrollBar::setPressed(bool pressed)
547{
548 Q_D(QQuickScrollBar);
549 if (!pressed) {
550 if (QQuickIndicatorButton *button = decreaseVisual())
551 button->setPressed(false);
552 if (QQuickIndicatorButton *button = increaseVisual())
553 button->setPressed(false);
554 }
555 if (d->pressed == pressed)
556 return;
557
558 d->pressed = pressed;
559 setAccessibleProperty("pressed", pressed);
560 d->updateActive();
561 emit pressedChanged();
562}
563
564/*!
565 \qmlproperty enumeration QtQuick.Controls::ScrollBar::orientation
566
567 This property holds the orientation of the scroll bar.
568
569 Possible values:
570 \value Qt.Horizontal Horizontal
571 \value Qt.Vertical Vertical (default)
572
573 This property is automatically set when the scroll bar is
574 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
575
576 \sa horizontal, vertical
577*/
578Qt::Orientation QQuickScrollBar::orientation() const
579{
580 Q_D(const QQuickScrollBar);
581 return d->orientation;
582}
583
584void QQuickScrollBar::setOrientation(Qt::Orientation orientation)
585{
586 Q_D(QQuickScrollBar);
587 if (d->orientation == orientation)
588 return;
589
590 if (orientation == Qt::Horizontal)
591 d->setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Fixed);
592 else
593 d->setSizePolicy(QLayoutPolicy::Fixed, QLayoutPolicy::Preferred);
594
595 d->orientation = orientation;
596 if (isComponentComplete())
597 d->resizeContent();
598 emit orientationChanged();
599}
600
601/*!
602 \since QtQuick.Controls 2.2 (Qt 5.9)
603 \qmlproperty enumeration QtQuick.Controls::ScrollBar::snapMode
604
605 This property holds the snap mode.
606
607 Possible values:
608 \value ScrollBar.NoSnap The scrollbar does not snap (default).
609 \value ScrollBar.SnapAlways The scrollbar snaps while dragged.
610 \value ScrollBar.SnapOnRelease The scrollbar does not snap while being dragged, but only after released.
611
612 In the following table, the various modes are illustrated with animations.
613 The movement and the \l stepSize (\c 0.25) are identical in each animation.
614
615 \table
616 \header
617 \row \li \b Value \li \b Example
618 \row \li \c ScrollBar.NoSnap \li \image qtquickcontrols-scrollbar-nosnap.gif
619 \row \li \c ScrollBar.SnapAlways \li \image qtquickcontrols-scrollbar-snapalways.gif
620 \row \li \c ScrollBar.SnapOnRelease \li \image qtquickcontrols-scrollbar-snaponrelease.gif
621 \endtable
622
623 \sa stepSize
624*/
625QQuickScrollBar::SnapMode QQuickScrollBar::snapMode() const
626{
627 Q_D(const QQuickScrollBar);
628 return d->snapMode;
629}
630
631void QQuickScrollBar::setSnapMode(SnapMode mode)
632{
633 Q_D(QQuickScrollBar);
634 if (d->snapMode == mode)
635 return;
636
637 d->snapMode = mode;
638 emit snapModeChanged();
639}
640
641/*!
642 \since QtQuick.Controls 2.2 (Qt 5.9)
643 \qmlproperty bool QtQuick.Controls::ScrollBar::interactive
644
645 This property holds whether the scroll bar is interactive. The default value is \c true.
646
647 A non-interactive scroll bar is visually and behaviorally similar to \l ScrollIndicator.
648 This property is useful for switching between typical mouse- and touch-orientated UIs
649 with interactive and non-interactive scroll bars, respectively.
650*/
651bool QQuickScrollBar::isInteractive() const
652{
653 Q_D(const QQuickScrollBar);
654 return d->interactive;
655}
656
657void QQuickScrollBar::setInteractive(bool interactive)
658{
659 Q_D(QQuickScrollBar);
660 d->explicitInteractive = true;
661 d->setInteractive(interactive);
662}
663
664void QQuickScrollBar::resetInteractive()
665{
666 Q_D(QQuickScrollBar);
667 d->explicitInteractive = false;
668 d->setInteractive(true);
669}
670
671/*!
672 \since QtQuick.Controls 2.2 (Qt 5.9)
673 \qmlproperty enumeration QtQuick.Controls::ScrollBar::policy
674
675 This property holds the policy of the scroll bar. The default policy is \c ScrollBar.AsNeeded.
676
677 Possible values:
678 \value ScrollBar.AsNeeded The scroll bar is only shown when the content is too large to fit.
679 \value ScrollBar.AlwaysOff The scroll bar is never shown.
680 \value ScrollBar.AlwaysOn The scroll bar is always shown.
681
682 The following example keeps the vertical scroll bar always visible:
683
684 \snippet qtquickcontrols-scrollbar-policy-alwayson.qml 1
685
686 Styles may use this property in combination with the \l active property
687 in order to implement transient scroll bars. Transient scroll bars are
688 hidden shortly after the last interaction event (hover or press). This
689 is typically done by animating the opacity of the scroll bar. To override
690 this behavior, set the policy to \c ScrollBar.AlwaysOn or
691 \c ScrollBar.AlwaysOff, depending on the size of the content compared to
692 its view. For example, for a vertical \l ListView:
693
694 \snippet qtquickcontrols-scrollbar-policy-alwayson-when-needed.qml 1
695*/
696QQuickScrollBar::Policy QQuickScrollBar::policy() const
697{
698 Q_D(const QQuickScrollBar);
699 return d->policy;
700}
701
702void QQuickScrollBar::setPolicy(Policy policy)
703{
704 Q_D(QQuickScrollBar);
705 if (d->policy == policy)
706 return;
707
708 d->policy = policy;
709 emit policyChanged();
710}
711
712/*!
713 \since QtQuick.Controls 2.3 (Qt 5.10)
714 \qmlproperty bool QtQuick.Controls::ScrollBar::horizontal
715 \readonly
716
717 This property holds whether the scroll bar is horizontal.
718
719 \sa orientation
720*/
721bool QQuickScrollBar::isHorizontal() const
722{
723 Q_D(const QQuickScrollBar);
724 return d->orientation == Qt::Horizontal;
725}
726
727/*!
728 \since QtQuick.Controls 2.3 (Qt 5.10)
729 \qmlproperty bool QtQuick.Controls::ScrollBar::vertical
730 \readonly
731
732 This property holds whether the scroll bar is vertical.
733
734 \sa orientation
735*/
736bool QQuickScrollBar::isVertical() const
737{
738 Q_D(const QQuickScrollBar);
739 return d->orientation == Qt::Vertical;
740}
741
742/*!
743 \since QtQuick.Controls 2.4 (Qt 5.11)
744 \qmlproperty real QtQuick.Controls::ScrollBar::minimumSize
745
746 This property holds the minimum size of the scroll bar, scaled to \c {0.0 - 1.0}.
747
748 \sa size, visualSize, visualPosition
749*/
750qreal QQuickScrollBar::minimumSize() const
751{
752 Q_D(const QQuickScrollBar);
753 return d->minimumSize;
754}
755
756void QQuickScrollBar::setMinimumSize(qreal minimumSize)
757{
758 Q_D(QQuickScrollBar);
759 if (!qt_is_finite(minimumSize) || qFuzzyCompare(d->minimumSize, minimumSize))
760 return;
761
762 auto oldVisualArea = d->visualArea();
763 d->minimumSize = qBound(0.0, minimumSize, 1.0);
764 if (isComponentComplete())
765 d->resizeContent();
766 emit minimumSizeChanged();
767 d->visualAreaChange(d->visualArea(), oldVisualArea);
768}
769
770/*!
771 \since QtQuick.Controls 2.4 (Qt 5.11)
772 \qmlproperty real QtQuick.Controls::ScrollBar::visualSize
773 \readonly
774
775 This property holds the effective visual size of the scroll bar,
776 which may be limited by the \l {minimumSize}{minimum size}.
777
778 \sa size, minimumSize
779*/
780qreal QQuickScrollBar::visualSize() const
781{
782 Q_D(const QQuickScrollBar);
783 return d->visualArea().size;
784}
785
786/*!
787 \since QtQuick.Controls 2.4 (Qt 5.11)
788 \qmlproperty real QtQuick.Controls::ScrollBar::visualPosition
789 \readonly
790
791 This property holds the effective visual position of the scroll bar,
792 which may be limited by the \l {minimumSize}{minimum size}.
793
794 \sa position, minimumSize
795*/
796qreal QQuickScrollBar::visualPosition() const
797{
798 Q_D(const QQuickScrollBar);
799 return d->visualArea().position;
800}
801
802QQuickIndicatorButton *QQuickScrollBar::decreaseVisual()
803{
804 Q_D(QQuickScrollBar);
805 return d->decreaseVisual;
806}
807
808QQuickIndicatorButton *QQuickScrollBar::increaseVisual()
809{
810 Q_D(QQuickScrollBar);
811 return d->increaseVisual;
812}
813
814/*!
815 \qmlmethod void QtQuick.Controls::ScrollBar::increase()
816
817 Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0.
818
819 \sa stepSize
820*/
821void QQuickScrollBar::increase()
822{
823 Q_D(QQuickScrollBar);
824 qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
825 bool wasActive = d->active;
826 setActive(true);
827 setPosition(qMin<qreal>(1.0 - d->size, d->position + step));
828 setActive(wasActive);
829}
830
831/*!
832 \qmlmethod void QtQuick.Controls::ScrollBar::decrease()
833
834 Decreases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0.
835
836 \sa stepSize
837*/
838void QQuickScrollBar::decrease()
839{
840 Q_D(QQuickScrollBar);
841 qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
842 bool wasActive = d->active;
843 setActive(true);
844 setPosition(qMax<qreal>(0.0, d->position - step));
845 setActive(wasActive);
846}
847
848void QQuickScrollBar::mousePressEvent(QMouseEvent *event)
849{
850 Q_D(QQuickScrollBar);
851 QQuickControl::mousePressEvent(event);
852 d->handleMove(event->position(), event->timestamp());
853}
854
855#if QT_CONFIG(quicktemplates2_hover)
856void QQuickScrollBar::hoverChange()
857{
858 Q_D(QQuickScrollBar);
859 d->updateActive();
860}
861
862void QQuickScrollBar::hoverEnterEvent(QHoverEvent *event)
863{
864 Q_D(QQuickScrollBar);
865 QQuickControl::hoverEnterEvent(event);
866 d->updateHover(event->position());
867 event->ignore();
868}
869
870void QQuickScrollBar::hoverMoveEvent(QHoverEvent *event)
871{
872 Q_D(QQuickScrollBar);
873 QQuickControl::hoverMoveEvent(event);
874 d->updateHover(event->position());
875 event->ignore();
876}
877
878void QQuickScrollBar::hoverLeaveEvent(QHoverEvent *event)
879{
880 Q_D(QQuickScrollBar);
881 QQuickControl::hoverLeaveEvent(event);
882
883 d->updateHover(QPoint(), false); //position is not needed when we force it to unhover
884 event->ignore();
885}
886#endif
887
888void QQuickScrollBar::classBegin()
889{
890 Q_D(QQuickScrollBar);
891 QQuickControl::classBegin();
892
893 QQmlContext *context = qmlContext(this);
894 if (context) {
895 QQmlEngine::setContextForObject(d->decreaseVisual, context);
896 QQmlEngine::setContextForObject(d->increaseVisual, context);
897 }
898}
899
900void QQuickScrollBar::componentComplete()
901{
902 Q_D(QQuickScrollBar);
903 QQuickIndicatorButtonPrivate::get(d->decreaseVisual)->executeIndicator(true);
904 QQuickIndicatorButtonPrivate::get(d->increaseVisual)->executeIndicator(true);
905
906 QQuickControl::componentComplete();
907}
908
909#if QT_CONFIG(accessibility)
910void QQuickScrollBar::accessibilityActiveChanged(bool active)
911{
912 QQuickControl::accessibilityActiveChanged(active);
913
914 Q_D(QQuickScrollBar);
915 if (active) {
916 setAccessibleProperty("pressed", d->pressed);
917
918 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this)) {
919 connect(accessibleAttached, &QQuickAccessibleAttached::increaseAction, this, &QQuickScrollBar::increase);
920 connect(accessibleAttached, &QQuickAccessibleAttached::decreaseAction, this, &QQuickScrollBar::decrease);
921 }
922 } else {
923 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this)) {
924 disconnect(accessibleAttached, &QQuickAccessibleAttached::increaseAction, this, &QQuickScrollBar::increase);
925 disconnect(accessibleAttached, &QQuickAccessibleAttached::decreaseAction, this, &QQuickScrollBar::decrease);
926 }
927 }
928}
929
930QAccessible::Role QQuickScrollBar::accessibleRole() const
931{
932 return QAccessible::ScrollBar;
933}
934#endif
935
937{
938 if (flickable) {
939 // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size).
940 // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling
941 // pointer on destruction.
942 QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
943 QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
944 if (horizontal)
946 if (vertical)
948 }
949
950 flickable = item;
951
952 if (item) {
953 // Don't know how to combine these calls into one, and as long as they're separate calls,
954 // the remove* calls above need to be separate too, otherwise they will have no effect.
955 QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size);
956 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(this, QQuickItemPrivate::Destroyed);
957 if (horizontal)
959 if (vertical)
961 }
962}
963
965{
966 Q_ASSERT(flickable && horizontal);
967
968 connect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal);
969
970 // TODO: export QQuickFlickableVisibleArea
971 QObject *area = flickable->property("visibleArea").value<QObject *>();
972 QObject::connect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal)));
973 QObject::connect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal)));
974
975 // ensure that the ScrollBar is stacked above the Flickable in a ScrollView
976 QQuickItem *parent = horizontal->parentItem();
977 if (parent && parent == flickable->parentItem())
978 horizontal->stackAfter(flickable);
979
980 // If a scroll bar was previously hidden (due to e.g. setting a new contentItem
981 // on a ScrollView), we need to make sure that we un-hide it.
982 if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) {
983 const auto visibility = horizontal->policy() != QQuickScrollBar::AlwaysOff
984 ? QQuickControlPrivate::UnhideVisibility::Show : QQuickControlPrivate::UnhideVisibility::Hide;
985 QQuickControlPrivate::unhideOldItem(control, horizontal, visibility);
986 }
987
989 horizontal->setSize(area->property("widthRatio").toReal());
990 horizontal->setPosition(area->property("xPosition").toReal());
991}
992
994{
995 Q_ASSERT(flickable && vertical);
996
997 connect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical);
998
999 // TODO: export QQuickFlickableVisibleArea
1000 QObject *area = flickable->property("visibleArea").value<QObject *>();
1001 QObject::connect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal)));
1002 QObject::connect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal)));
1003
1004 // ensure that the ScrollBar is stacked above the Flickable in a ScrollView
1005 QQuickItem *parent = vertical->parentItem();
1006 if (parent && parent == flickable->parentItem())
1007 vertical->stackAfter(flickable);
1008
1009 if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) {
1010 const auto visibility = vertical->policy() != QQuickScrollBar::AlwaysOff
1011 ? QQuickControlPrivate::UnhideVisibility::Show : QQuickControlPrivate::UnhideVisibility::Hide;
1012 QQuickControlPrivate::unhideOldItem(control, vertical, visibility);
1013 }
1014
1016 vertical->setSize(area->property("heightRatio").toReal());
1017 vertical->setPosition(area->property("yPosition").toReal());
1018}
1019
1021{
1022 Q_ASSERT(horizontal);
1023
1024 QQuickControlPrivate::hideOldItem(horizontal);
1025 // ScrollBar.qml has a binding to visible and ScrollView.qml has a binding to parent.
1026 // If we just set visible to false and parent to null, these bindings will overwrite
1027 // them upon component completion as part of the binding evaluation.
1028 // That's why we remove the binding completely.
1029 const QQmlProperty visibleProperty(horizontal, QStringLiteral("visible"));
1030 const QQmlProperty parentProperty(horizontal, QStringLiteral("parent"));
1031 QQmlPropertyPrivate::removeBinding(visibleProperty);
1032 QQmlPropertyPrivate::removeBinding(parentProperty);
1033
1034 if (!flickable)
1035 return;
1036
1037 disconnect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal);
1038
1039 // TODO: export QQuickFlickableVisibleArea
1040 QObject *area = flickable->property("visibleArea").value<QObject *>();
1041 QObject::disconnect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal)));
1042 QObject::disconnect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal)));
1043}
1044
1046{
1047 Q_ASSERT(vertical);
1048
1049 QQuickControlPrivate::hideOldItem(vertical);
1050 const QQmlProperty visibleProperty(vertical, QStringLiteral("visible"));
1051 const QQmlProperty parentProperty(vertical, QStringLiteral("parent"));
1052 QQmlPropertyPrivate::removeBinding(visibleProperty);
1053 QQmlPropertyPrivate::removeBinding(parentProperty);
1054
1055 if (!flickable)
1056 return;
1057
1058 disconnect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical);
1059
1060 // TODO: export QQuickFlickableVisibleArea
1061 QObject *area = flickable->property("visibleArea").value<QObject *>();
1062 QObject::disconnect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal)));
1063 QObject::disconnect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal)));
1064}
1065
1067{
1068 QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(horizontal);
1069 p->moving = flickable->isMovingHorizontally();
1071}
1072
1074{
1075 QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(vertical);
1076 p->moving = flickable->isMovingVertically();
1078}
1079
1080// TODO: QQuickFlickable::maxXYExtent()
1085
1087{
1088 if (!flickable)
1089 return;
1090
1092
1093 const qreal viewwidth = f->width();
1094 const qreal maxxextent = -f->maxXExtent() + f->minXExtent();
1095 const qreal cx = horizontal->position() * (maxxextent + viewwidth) - f->minXExtent();
1096
1097 if (!qIsNaN(cx) && !qFuzzyCompare(cx, flickable->contentX()))
1098 flickable->setContentX(cx);
1099}
1100
1102{
1103 if (!flickable)
1104 return;
1105
1107
1108 const qreal viewheight = f->height();
1109 const qreal maxyextent = -f->maxYExtent() + f->minYExtent();
1110 const qreal cy = vertical->position() * (maxyextent + viewheight) - f->minYExtent();
1111
1112 if (!qIsNaN(cy) && !qFuzzyCompare(cy, flickable->contentY()))
1113 flickable->setContentY(cy);
1114}
1115
1120
1122{
1123 Q_ASSERT(horizontal && flickable);
1124 if (horizontal->parentItem() != flickable)
1125 return;
1126 horizontal->setWidth(flickable->width());
1127 if (move)
1128 horizontal->setY(flickable->height() - horizontal->height());
1129}
1130
1132{
1133 Q_ASSERT(vertical && flickable);
1134 if (vertical->parentItem() != flickable)
1135 return;
1136 vertical->setHeight(flickable->height());
1137 if (move)
1138 vertical->setX(vertical->isMirrored() ? 0 : flickable->width() - vertical->width());
1139}
1140
1141void QQuickScrollBarAttachedPrivate::itemGeometryChanged(QQuickItem *item, const QQuickGeometryChange change, const QRectF &diff)
1142{
1143 Q_UNUSED(item);
1144 Q_UNUSED(change);
1145 if (horizontal && horizontal->height() > 0) {
1146#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry
1147 bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), diff.height() - horizontal->height());
1148#else
1149 bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), item->height() - diff.height() - horizontal->height());
1150#endif
1151 if (flickable)
1153 }
1154 if (vertical && vertical->width() > 0) {
1155#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry
1156 bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), diff.width() - vertical->width());
1157#else
1158 bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), item->width() - diff.width() - vertical->width());
1159#endif
1160 if (flickable)
1161 layoutVertical(move);
1162 }
1163}
1164
1166{
1167 if (item == vertical && flickable)
1168 layoutVertical(true);
1169}
1170
1172{
1173 if (item == horizontal && flickable)
1175}
1176
1178{
1179 if (item == flickable)
1180 flickable = nullptr;
1181 if (item == horizontal)
1182 horizontal = nullptr;
1183 if (item == vertical)
1184 vertical = nullptr;
1185}
1186
1187QQuickScrollBarAttached::QQuickScrollBarAttached(QObject *parent)
1188 : QObject(*(new QQuickScrollBarAttachedPrivate), parent)
1189{
1190 Q_D(QQuickScrollBarAttached);
1191 d->setFlickable(qobject_cast<QQuickFlickable *>(parent));
1192
1193 if (parent && !d->flickable && !qobject_cast<QQuickScrollView *>(parent))
1194 qmlWarning(parent) << "ScrollBar attached property must be attached to an object deriving from Flickable or ScrollView";
1195}
1196
1197QQuickScrollBarAttached::~QQuickScrollBarAttached()
1198{
1199 Q_D(QQuickScrollBarAttached);
1200 if (d->horizontal) {
1201 QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QsbHorizontalChangeTypes);
1202 d->horizontal = nullptr;
1203 }
1204 if (d->vertical) {
1205 QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QsbVerticalChangeTypes);
1206 d->vertical = nullptr;
1207 }
1208 d->setFlickable(nullptr);
1209}
1210
1211/*!
1212 \qmlattachedproperty ScrollBar QtQuick.Controls::ScrollBar::horizontal
1213
1214 This property attaches a horizontal scroll bar to a \l Flickable.
1215
1216 \code
1217 Flickable {
1218 contentWidth: 2000
1219 ScrollBar.horizontal: ScrollBar { }
1220 }
1221 \endcode
1222
1223 \sa {Attaching ScrollBar to a Flickable}
1224*/
1225QQuickScrollBar *QQuickScrollBarAttached::horizontal() const
1226{
1227 Q_D(const QQuickScrollBarAttached);
1228 return d->horizontal;
1229}
1230
1231void QQuickScrollBarAttached::setHorizontal(QQuickScrollBar *horizontal)
1232{
1233 Q_D(QQuickScrollBarAttached);
1234 if (d->horizontal == horizontal)
1235 return;
1236
1237 if (d->horizontal) {
1238 QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QsbHorizontalChangeTypes);
1239 QObjectPrivate::disconnect(d->horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal);
1240
1241 // Call this regardless of whether we have a flickable, because we need to clean up the old
1242 // horizontal item.
1243 d->cleanupHorizontal();
1244 }
1245
1246 d->horizontal = horizontal;
1247
1248 if (horizontal) {
1249 if (!horizontal->parentItem())
1250 horizontal->setParentItem(qobject_cast<QQuickItem *>(parent()));
1251 horizontal->setOrientation(Qt::Horizontal);
1252
1253 QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, QsbHorizontalChangeTypes);
1254 QObjectPrivate::connect(horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal);
1255
1256 if (d->flickable)
1257 d->initHorizontal();
1258 }
1259 emit horizontalChanged();
1260}
1261
1262/*!
1263 \qmlattachedproperty ScrollBar QtQuick.Controls::ScrollBar::vertical
1264
1265 This property attaches a vertical scroll bar to a \l Flickable.
1266
1267 \code
1268 Flickable {
1269 contentHeight: 2000
1270 ScrollBar.vertical: ScrollBar { }
1271 }
1272 \endcode
1273
1274 \sa {Attaching ScrollBar to a Flickable}
1275*/
1276QQuickScrollBar *QQuickScrollBarAttached::vertical() const
1277{
1278 Q_D(const QQuickScrollBarAttached);
1279 return d->vertical;
1280}
1281
1282void QQuickScrollBarAttached::setVertical(QQuickScrollBar *vertical)
1283{
1284 Q_D(QQuickScrollBarAttached);
1285 if (d->vertical == vertical)
1286 return;
1287
1288 if (d->vertical) {
1289 QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QsbVerticalChangeTypes);
1290 QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical);
1291 QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical);
1292
1293 // Call this regardless of whether we have a flickable, because we need to clean up the old
1294 // vertical item.
1295 d->cleanupVertical();
1296 }
1297
1298 d->vertical = vertical;
1299
1300 if (vertical) {
1301 if (!vertical->parentItem())
1302 vertical->setParentItem(qobject_cast<QQuickItem *>(parent()));
1303 vertical->setOrientation(Qt::Vertical);
1304
1305 QQuickItemPrivate::get(vertical)->addItemChangeListener(d, QsbVerticalChangeTypes);
1306 QObjectPrivate::connect(vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical);
1307 QObjectPrivate::connect(vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical);
1308
1309 if (d->flickable)
1310 d->initVertical();
1311 }
1312 emit verticalChanged();
1313}
1314
1315QT_END_NAMESPACE
1316
1317#include "moc_qquickscrollbar_p.cpp"
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override
void setFlickable(QQuickFlickable *flickable)
void layoutHorizontal(bool move=true)
void itemImplicitHeightChanged(QQuickItem *item) override
void itemDestroyed(QQuickItem *item) override
void itemImplicitWidthChanged(QQuickItem *item) override
void itemImplicitHeightChanged(QQuickItem *item) override
bool handlePress(const QPointF &point, ulong timestamp) override
qreal snapPosition(qreal position) const
void itemImplicitWidthChanged(QQuickItem *item) override
void updateHover(const QPointF &pos, std::optional< bool > newHoverState={})
bool handleRelease(const QPointF &point, ulong timestamp) override
bool handleMove(const QPointF &point, ulong timestamp) override
void visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea)
qreal positionAt(const QPointF &point) const
void setPosition(qreal position, bool notifyVisualChange=true)
void setInteractive(bool interactive)
void resizeContent() override
qreal logicalPosition(qreal position) const
VisualArea visualArea() const
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE const QQuickItemPrivate::ChangeTypes QsbChangeTypes
Vertical or horizontal interactive scroll bar.
static const QQuickItemPrivate::ChangeTypes QsbVerticalChangeTypes
static const QQuickItemPrivate::ChangeTypes QsbHorizontalChangeTypes