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