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 dragPoint = point;
289 q->setPressed(true);
290 return true;
291}
292
293bool QQuickScrollBarPrivate::handleMove(const QPointF &point, ulong timestamp)
294{
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 setPositionFromDrag(pos, point);
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 setPositionFromDrag(pos, point);
331 offset = 0.0;
332 dragPoint = {};
333 q->setPressed(false);
334 return true;
335}
336
338{
339 Q_Q(QQuickScrollBar);
340 QQuickControlPrivate::handleUngrab();
341 offset = 0.0;
342 dragPoint = {};
343 q->setPressed(false);
344}
345
346void QQuickScrollBarPrivate::visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea)
347{
348 Q_Q(QQuickScrollBar);
349 if (!qFuzzyCompare(newVisualArea.size, oldVisualArea.size))
350 emit q->visualSizeChanged();
351 if (!qFuzzyCompare(newVisualArea.position, oldVisualArea.position))
352 emit q->visualPositionChanged();
353}
354
355void QQuickScrollBarPrivate::updateHover(const QPointF &pos, std::optional<bool> newHoverState)
356{
357 Q_Q(QQuickScrollBar);
358 auto updateHoverOnButton = [&](QQuickIndicatorButton *sbButton) {
359 if (sbButton) {
360 bool hovered = newHoverState.value_or(false);
361 if (!newHoverState.has_value()) {
362 if (QQuickItem *indicator = sbButton->indicator())
363 hovered = indicator->contains(q->mapToItem(indicator, pos));
364 }
365 sbButton->setHovered(hovered);
366 }
367 };
368 updateHoverOnButton(q->decreaseVisual());
369 updateHoverOnButton(q->increaseVisual());
370}
371
372QQuickScrollBar::QQuickScrollBar(QQuickItem *parent)
373 : QQuickControl(*(new QQuickScrollBarPrivate), parent)
374{
375 Q_D(QQuickScrollBar);
376 d->decreaseVisual = new QQuickIndicatorButton(this);
377 d->increaseVisual = new QQuickIndicatorButton(this);
378 d->setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Fixed);
379 setKeepMouseGrab(true);
380 setAcceptedMouseButtons(Qt::LeftButton);
381#if QT_CONFIG(quicktemplates2_multitouch)
382 setAcceptTouchEvents(true);
383#endif
384#if QT_CONFIG(cursor)
385 setCursor(Qt::ArrowCursor);
386#endif
387}
388
389QQuickScrollBarAttached *QQuickScrollBar::qmlAttachedProperties(QObject *object)
390{
391 return new QQuickScrollBarAttached(object);
392}
393
394/*!
395 \qmlproperty real QtQuick.Controls::ScrollBar::size
396
397 This property holds the size of the scroll bar, scaled to \c {0.0 - 1.0}.
398
399 \sa {Flickable::visibleArea.heightRatio}{Flickable::visibleArea}
400
401 This property is automatically set when the scroll bar is
402 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
403
404 \sa minimumSize, visualSize
405*/
406qreal QQuickScrollBar::size() const
407{
408 Q_D(const QQuickScrollBar);
409 return d->size;
410}
411
412void QQuickScrollBar::setSize(qreal size)
413{
414 Q_D(QQuickScrollBar);
415 if (!qt_is_finite(size))
416 return;
417 size = qBound(0.0, size, 1.0);
418 if (qFuzzyCompare(d->size, size))
419 return;
420
421 const auto oldVisualArea = d->visualArea();
422 d->size = size;
423 if (d->size + d->position > 1.0) {
424 d->setPosition(1.0 - d->size, false);
425 }
426 // positionAt() depends on the size.
427 d->reanchorDragOffset(d->position);
428
429 if (isComponentComplete())
430 d->resizeContent();
431 emit sizeChanged();
432 d->visualAreaChange(d->visualArea(), oldVisualArea);
433}
434
435/*!
436 \qmlproperty real QtQuick.Controls::ScrollBar::position
437
438 This property holds the position of the scroll bar, scaled to \c {0.0 - 1.0}.
439
440 The largest valid scrollbar position is \c {(1.0 - size)}. This gives
441 correct behavior for the most used case where moving the scrollbar
442 to the end will put the end of the document at the lower end of the
443 visible area of the connected Flickable.
444
445 \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea}
446
447 This property is automatically set when the scroll bar is
448 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
449
450 \sa visualPosition
451*/
452qreal QQuickScrollBar::position() const
453{
454 Q_D(const QQuickScrollBar);
455 return d->position;
456}
457
458void QQuickScrollBar::setPosition(qreal position)
459{
460 Q_D(QQuickScrollBar);
461 d->setPosition(position);
462}
463
464void QQuickScrollBarPrivate::setPosition(qreal newPosition, bool notifyVisualChange)
465{
466 // An attached Flickable writes the drag's own position back here unchanged, and those
467 // writes must not touch offset - see setPositionFromDrag().
468 if (qt_is_finite(newPosition) && !qFuzzyCompare(position, newPosition))
469 reanchorDragOffset(newPosition);
470 updatePosition(newPosition, notifyVisualChange);
471}
472
473void QQuickScrollBarPrivate::setPositionFromDrag(qreal newPosition, const QPointF &point)
474{
475 dragPoint = point;
476 // Bypass setPosition(): offset is already accounted for in newPosition, so re-anchoring it
477 // would fold the clamping and the snapping applied by the caller back into it.
478 updatePosition(newPosition, true /*notifyVisualChange*/);
479}
480
481void QQuickScrollBarPrivate::updatePosition(qreal newPosition, bool notifyVisualChange)
482{
483 Q_Q(QQuickScrollBar);
484 if (!qt_is_finite(newPosition) || qFuzzyCompare(position, newPosition))
485 return;
486
487 auto oldVisualArea = visualArea();
488 position = newPosition;
489 if (q->isComponentComplete())
491 emit q->positionChanged();
492 if (notifyVisualChange)
493 visualAreaChange(visualArea(), oldVisualArea);
494
495#if QT_CONFIG(accessibility)
496 if (QAccessible::isActive() && isAccessible) {
497 if (QAccessibleInterface *accessible = QAccessible::queryAccessibleInterface(q)) {
498 if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
499 QAccessibleValueChangeEvent event(q, valueInterface->currentValue());
500 QAccessible::updateAccessibility(&event);
501 }
502 }
503 }
504#endif
505}
506
508{
509 // offset is the distance between the handle and the pointer holding it. Moving the handle,
510 // or changing what positionAt() returns, makes that distance stale: measure it again, or
511 // the next handleMove() would put the handle back where it was (QTBUG-130890).
512 if (pressed)
513 offset = positionAt(dragPoint) - newPosition;
514}
515
516/*!
517 \qmlproperty real QtQuick.Controls::ScrollBar::stepSize
518
519 This property holds the step size. The default value is \c 0.0.
520
521 \sa snapMode, increase(), decrease()
522*/
523qreal QQuickScrollBar::stepSize() const
524{
525 Q_D(const QQuickScrollBar);
526 return d->stepSize;
527}
528
529void QQuickScrollBar::setStepSize(qreal step)
530{
531 Q_D(QQuickScrollBar);
532 if (!qt_is_finite(step) || qFuzzyCompare(d->stepSize, step))
533 return;
534
535 d->stepSize = step;
536 emit stepSizeChanged();
537}
538
539/*!
540 \qmlproperty bool QtQuick.Controls::ScrollBar::active
541
542 This property holds whether the scroll bar is active, i.e. when it's \l pressed
543 or the attached Flickable is \l {Flickable::moving}{moving}.
544
545 It is possible to keep \l {Binding the Active State of Horizontal and Vertical Scroll Bars}
546 {both horizontal and vertical bars visible} while scrolling in either direction.
547
548 This property is automatically set when the scroll bar is
549 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
550*/
551bool QQuickScrollBar::isActive() const
552{
553 Q_D(const QQuickScrollBar);
554 return d->active;
555}
556
557void QQuickScrollBar::setActive(bool active)
558{
559 Q_D(QQuickScrollBar);
560 if (d->active == active)
561 return;
562
563 d->active = active;
564 emit activeChanged();
565}
566
567/*!
568 \qmlproperty bool QtQuick.Controls::ScrollBar::pressed
569
570 This property holds whether the scroll bar is pressed.
571*/
572bool QQuickScrollBar::isPressed() const
573{
574 Q_D(const QQuickScrollBar);
575 return d->pressed;
576}
577
578void QQuickScrollBar::setPressed(bool pressed)
579{
580 Q_D(QQuickScrollBar);
581 if (!pressed) {
582 if (QQuickIndicatorButton *button = decreaseVisual())
583 button->setPressed(false);
584 if (QQuickIndicatorButton *button = increaseVisual())
585 button->setPressed(false);
586 }
587 if (d->pressed == pressed)
588 return;
589
590 d->pressed = pressed;
591 setAccessibleProperty("pressed", pressed);
592 d->updateActive();
593 emit pressedChanged();
594}
595
596/*!
597 \qmlproperty enumeration QtQuick.Controls::ScrollBar::orientation
598
599 This property holds the orientation of the scroll bar.
600
601 Possible values:
602 \value Qt.Horizontal Horizontal
603 \value Qt.Vertical Vertical (default)
604
605 This property is automatically set when the scroll bar is
606 \l {Attaching ScrollBar to a Flickable}{attached to a flickable}.
607
608 \sa horizontal, vertical
609*/
610Qt::Orientation QQuickScrollBar::orientation() const
611{
612 Q_D(const QQuickScrollBar);
613 return d->orientation;
614}
615
616void QQuickScrollBar::setOrientation(Qt::Orientation orientation)
617{
618 Q_D(QQuickScrollBar);
619 if (d->orientation == orientation)
620 return;
621
622 if (orientation == Qt::Horizontal)
623 d->setSizePolicy(QLayoutPolicy::Preferred, QLayoutPolicy::Fixed);
624 else
625 d->setSizePolicy(QLayoutPolicy::Fixed, QLayoutPolicy::Preferred);
626
627 d->orientation = orientation;
628 if (isComponentComplete())
629 d->resizeContent();
630 emit orientationChanged();
631}
632
633/*!
634 \since QtQuick.Controls 2.2 (Qt 5.9)
635 \qmlproperty enumeration QtQuick.Controls::ScrollBar::snapMode
636
637 This property holds the snap mode.
638
639 Possible values:
640 \value ScrollBar.NoSnap The scrollbar does not snap (default).
641 \value ScrollBar.SnapAlways The scrollbar snaps while dragged.
642 \value ScrollBar.SnapOnRelease The scrollbar does not snap while being dragged, but only after released.
643
644 In the following table, the various modes are illustrated with animations.
645 The movement and the \l stepSize (\c 0.25) are identical in each animation.
646
647 \table
648 \header
649 \row \li \b Value \li \b Example
650 \row \li \c ScrollBar.NoSnap
651 \li \image qtquickcontrols-scrollbar-nosnap.gif
652 {Scroll bar without snap mode, sliding freely}
653 \row \li \c ScrollBar.SnapAlways
654 \li \image qtquickcontrols-scrollbar-snapalways.gif
655 {Scroll bar snapping to items while dragging}
656 \row \li \c ScrollBar.SnapOnRelease
657 \li \image qtquickcontrols-scrollbar-snaponrelease.gif
658 {Scroll bar snapping to items on release}
659 \endtable
660
661 \sa stepSize
662*/
663QQuickScrollBar::SnapMode QQuickScrollBar::snapMode() const
664{
665 Q_D(const QQuickScrollBar);
666 return d->snapMode;
667}
668
669void QQuickScrollBar::setSnapMode(SnapMode mode)
670{
671 Q_D(QQuickScrollBar);
672 if (d->snapMode == mode)
673 return;
674
675 d->snapMode = mode;
676 emit snapModeChanged();
677}
678
679/*!
680 \since QtQuick.Controls 2.2 (Qt 5.9)
681 \qmlproperty bool QtQuick.Controls::ScrollBar::interactive
682
683 This property holds whether the scroll bar is interactive. The default value is \c true.
684
685 A non-interactive scroll bar is visually and behaviorally similar to \l ScrollIndicator.
686 This property is useful for switching between typical mouse- and touch-orientated UIs
687 with interactive and non-interactive scroll bars, respectively.
688*/
689bool QQuickScrollBar::isInteractive() const
690{
691 Q_D(const QQuickScrollBar);
692 return d->interactive;
693}
694
695void QQuickScrollBar::setInteractive(bool interactive)
696{
697 Q_D(QQuickScrollBar);
698 d->explicitInteractive = true;
699 d->setInteractive(interactive);
700}
701
702void QQuickScrollBar::resetInteractive()
703{
704 Q_D(QQuickScrollBar);
705 d->explicitInteractive = false;
706 d->setInteractive(true);
707}
708
709/*!
710 \since QtQuick.Controls 2.2 (Qt 5.9)
711 \qmlproperty enumeration QtQuick.Controls::ScrollBar::policy
712
713 This property holds the policy of the scroll bar. The default policy is \c ScrollBar.AsNeeded.
714
715 Possible values:
716 \value ScrollBar.AsNeeded The scroll bar is only shown when the content is too large to fit.
717 \value ScrollBar.AlwaysOff The scroll bar is never shown.
718 \value ScrollBar.AlwaysOn The scroll bar is always shown.
719
720 The following example keeps the vertical scroll bar always visible:
721
722 \snippet qtquickcontrols-scrollbar-policy-alwayson.qml 1
723
724 Styles may use this property in combination with the \l active property
725 in order to implement transient scroll bars. Transient scroll bars are
726 hidden shortly after the last interaction event (hover or press). This
727 is typically done by animating the opacity of the scroll bar. To override
728 this behavior, set the policy to \c ScrollBar.AlwaysOn or
729 \c ScrollBar.AlwaysOff, depending on the size of the content compared to
730 its view. For example, for a vertical \l ListView:
731
732 \snippet qtquickcontrols-scrollbar-policy-alwayson-when-needed.qml 1
733*/
734QQuickScrollBar::Policy QQuickScrollBar::policy() const
735{
736 Q_D(const QQuickScrollBar);
737 return d->policy;
738}
739
740void QQuickScrollBar::setPolicy(Policy policy)
741{
742 Q_D(QQuickScrollBar);
743 if (d->policy == policy)
744 return;
745
746 d->policy = policy;
747 emit policyChanged();
748}
749
750/*!
751 \since QtQuick.Controls 2.3 (Qt 5.10)
752 \qmlproperty bool QtQuick.Controls::ScrollBar::horizontal
753 \readonly
754
755 This property holds whether the scroll bar is horizontal.
756
757 \sa orientation
758*/
759bool QQuickScrollBar::isHorizontal() const
760{
761 Q_D(const QQuickScrollBar);
762 return d->orientation == Qt::Horizontal;
763}
764
765/*!
766 \since QtQuick.Controls 2.3 (Qt 5.10)
767 \qmlproperty bool QtQuick.Controls::ScrollBar::vertical
768 \readonly
769
770 This property holds whether the scroll bar is vertical.
771
772 \sa orientation
773*/
774bool QQuickScrollBar::isVertical() const
775{
776 Q_D(const QQuickScrollBar);
777 return d->orientation == Qt::Vertical;
778}
779
780/*!
781 \since QtQuick.Controls 2.4 (Qt 5.11)
782 \qmlproperty real QtQuick.Controls::ScrollBar::minimumSize
783
784 This property holds the minimum size of the scroll bar, scaled to \c {0.0 - 1.0}.
785
786 \sa size, visualSize, visualPosition
787*/
788qreal QQuickScrollBar::minimumSize() const
789{
790 Q_D(const QQuickScrollBar);
791 return d->minimumSize;
792}
793
794void QQuickScrollBar::setMinimumSize(qreal minimumSize)
795{
796 Q_D(QQuickScrollBar);
797 if (!qt_is_finite(minimumSize) || qFuzzyCompare(d->minimumSize, minimumSize))
798 return;
799
800 auto oldVisualArea = d->visualArea();
801 d->minimumSize = qBound(0.0, minimumSize, 1.0);
802 if (isComponentComplete())
803 d->resizeContent();
804 emit minimumSizeChanged();
805 d->visualAreaChange(d->visualArea(), oldVisualArea);
806}
807
808/*!
809 \since QtQuick.Controls 2.4 (Qt 5.11)
810 \qmlproperty real QtQuick.Controls::ScrollBar::visualSize
811 \readonly
812
813 This property holds the effective visual size of the scroll bar,
814 which may be limited by the \l {minimumSize}{minimum size}.
815
816 \sa size, minimumSize
817*/
818qreal QQuickScrollBar::visualSize() const
819{
820 Q_D(const QQuickScrollBar);
821 return d->visualArea().size;
822}
823
824/*!
825 \since QtQuick.Controls 2.4 (Qt 5.11)
826 \qmlproperty real QtQuick.Controls::ScrollBar::visualPosition
827 \readonly
828
829 This property holds the effective visual position of the scroll bar,
830 which may be limited by the \l {minimumSize}{minimum size}.
831
832 \sa position, minimumSize
833*/
834qreal QQuickScrollBar::visualPosition() const
835{
836 Q_D(const QQuickScrollBar);
837 return d->visualArea().position;
838}
839
840QQuickIndicatorButton *QQuickScrollBar::decreaseVisual()
841{
842 Q_D(QQuickScrollBar);
843 return d->decreaseVisual;
844}
845
846QQuickIndicatorButton *QQuickScrollBar::increaseVisual()
847{
848 Q_D(QQuickScrollBar);
849 return d->increaseVisual;
850}
851
852/*!
853 \qmlmethod void QtQuick.Controls::ScrollBar::increase()
854
855 Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0.
856
857 \sa stepSize
858*/
859void QQuickScrollBar::increase()
860{
861 Q_D(QQuickScrollBar);
862 qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
863 bool wasActive = d->active;
864 setActive(true);
865 setPosition(qMin<qreal>(1.0 - d->size, d->position + step));
866 setActive(wasActive);
867}
868
869/*!
870 \qmlmethod void QtQuick.Controls::ScrollBar::decrease()
871
872 Decreases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0.
873
874 \sa stepSize
875*/
876void QQuickScrollBar::decrease()
877{
878 Q_D(QQuickScrollBar);
879 qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
880 bool wasActive = d->active;
881 setActive(true);
882 setPosition(qMax<qreal>(0.0, d->position - step));
883 setActive(wasActive);
884}
885
886void QQuickScrollBar::mousePressEvent(QMouseEvent *event)
887{
888 Q_D(QQuickScrollBar);
889 QQuickControl::mousePressEvent(event);
890 d->handleMove(event->position(), event->timestamp());
891}
892
893#if QT_CONFIG(quicktemplates2_hover)
894void QQuickScrollBar::hoverChange()
895{
896 Q_D(QQuickScrollBar);
897 d->updateActive();
898}
899
900void QQuickScrollBar::hoverEnterEvent(QHoverEvent *event)
901{
902 Q_D(QQuickScrollBar);
903 QQuickControl::hoverEnterEvent(event);
904 d->updateHover(event->position());
905 event->ignore();
906}
907
908void QQuickScrollBar::hoverMoveEvent(QHoverEvent *event)
909{
910 Q_D(QQuickScrollBar);
911 QQuickControl::hoverMoveEvent(event);
912 d->updateHover(event->position());
913 event->ignore();
914}
915
916void QQuickScrollBar::hoverLeaveEvent(QHoverEvent *event)
917{
918 Q_D(QQuickScrollBar);
919 QQuickControl::hoverLeaveEvent(event);
920
921 d->updateHover(QPoint(), false); //position is not needed when we force it to unhover
922 event->ignore();
923}
924#endif
925
926void QQuickScrollBar::classBegin()
927{
928 Q_D(QQuickScrollBar);
929 QQuickControl::classBegin();
930
931 QQmlContext *context = qmlContext(this);
932 if (context) {
933 QQmlEngine::setContextForObject(d->decreaseVisual, context);
934 QQmlEngine::setContextForObject(d->increaseVisual, context);
935 }
936}
937
938void QQuickScrollBar::componentComplete()
939{
940 Q_D(QQuickScrollBar);
941 QQuickIndicatorButtonPrivate::get(d->decreaseVisual)->executeIndicator(true);
942 QQuickIndicatorButtonPrivate::get(d->increaseVisual)->executeIndicator(true);
943
944 QQuickControl::componentComplete();
945}
946
947#if QT_CONFIG(accessibility)
948void QQuickScrollBar::accessibilityActiveChanged(bool active)
949{
950 QQuickControl::accessibilityActiveChanged(active);
951
952 Q_D(QQuickScrollBar);
953 if (active) {
954 setAccessibleProperty("pressed", d->pressed);
955
956 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this)) {
957 connect(accessibleAttached, &QQuickAccessibleAttached::increaseAction, this, &QQuickScrollBar::increase);
958 connect(accessibleAttached, &QQuickAccessibleAttached::decreaseAction, this, &QQuickScrollBar::decrease);
959 }
960 } else {
961 if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this)) {
962 disconnect(accessibleAttached, &QQuickAccessibleAttached::increaseAction, this, &QQuickScrollBar::increase);
963 disconnect(accessibleAttached, &QQuickAccessibleAttached::decreaseAction, this, &QQuickScrollBar::decrease);
964 }
965 }
966}
967
968QAccessible::Role QQuickScrollBar::accessibleRole() const
969{
970 return QAccessible::ScrollBar;
971}
972#endif
973
975{
976 if (flickable) {
977 // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size).
978 // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling
979 // pointer on destruction.
980 QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
981 QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
982 if (horizontal)
984 if (vertical)
986 }
987
988 flickable = item;
989
990 if (item) {
991 // Don't know how to combine these calls into one, and as long as they're separate calls,
992 // the remove* calls above need to be separate too, otherwise they will have no effect.
993 QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size);
994 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(this, QQuickItemPrivate::Destroyed);
995 if (horizontal)
997 if (vertical)
999 }
1000}
1001
1003{
1004 Q_ASSERT(flickable && horizontal);
1005
1006 connect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal);
1007
1008 // TODO: export QQuickFlickableVisibleArea
1009 QObject *area = flickable->property("visibleArea").value<QObject *>();
1010 QObject::connect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal)));
1011 QObject::connect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal)));
1012
1013 // ensure that the ScrollBar is stacked above the Flickable in a ScrollView
1014 QQuickItem *parent = horizontal->parentItem();
1015 if (parent && parent == flickable->parentItem())
1016 horizontal->stackAfter(flickable);
1017
1018 // If a scroll bar was previously hidden (due to e.g. setting a new contentItem
1019 // on a ScrollView), we need to make sure that we un-hide it.
1020 if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) {
1021 const auto visibility = horizontal->policy() != QQuickScrollBar::AlwaysOff
1022 ? QQuickControlPrivate::UnhideVisibility::Show : QQuickControlPrivate::UnhideVisibility::Hide;
1023 QQuickControlPrivate::unhideOldItem(control, horizontal, visibility);
1024 }
1025
1027 horizontal->setSize(area->property("widthRatio").toReal());
1028 horizontal->setPosition(area->property("xPosition").toReal());
1029}
1030
1032{
1033 Q_ASSERT(flickable && vertical);
1034
1035 connect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical);
1036
1037 // TODO: export QQuickFlickableVisibleArea
1038 QObject *area = flickable->property("visibleArea").value<QObject *>();
1039 QObject::connect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal)));
1040 QObject::connect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal)));
1041
1042 // ensure that the ScrollBar is stacked above the Flickable in a ScrollView
1043 QQuickItem *parent = vertical->parentItem();
1044 if (parent && parent == flickable->parentItem())
1045 vertical->stackAfter(flickable);
1046
1047 if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) {
1048 const auto visibility = vertical->policy() != QQuickScrollBar::AlwaysOff
1049 ? QQuickControlPrivate::UnhideVisibility::Show : QQuickControlPrivate::UnhideVisibility::Hide;
1050 QQuickControlPrivate::unhideOldItem(control, vertical, visibility);
1051 }
1052
1054 vertical->setSize(area->property("heightRatio").toReal());
1055 vertical->setPosition(area->property("yPosition").toReal());
1056}
1057
1059{
1060 Q_ASSERT(horizontal);
1061
1062 QQuickControlPrivate::hideOldItem(horizontal);
1063 // ScrollBar.qml has a binding to visible and ScrollView.qml has a binding to parent.
1064 // If we just set visible to false and parent to null, these bindings will overwrite
1065 // them upon component completion as part of the binding evaluation.
1066 // That's why we remove the binding completely.
1067 const QQmlProperty visibleProperty(horizontal, QStringLiteral("visible"));
1068 const QQmlProperty parentProperty(horizontal, QStringLiteral("parent"));
1069 QQmlPropertyPrivate::removeBinding(visibleProperty);
1070 QQmlPropertyPrivate::removeBinding(parentProperty);
1071
1072 if (!flickable)
1073 return;
1074
1075 disconnect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal);
1076
1077 // TODO: export QQuickFlickableVisibleArea
1078 QObject *area = flickable->property("visibleArea").value<QObject *>();
1079 QObject::disconnect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal)));
1080 QObject::disconnect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal)));
1081}
1082
1084{
1085 Q_ASSERT(vertical);
1086
1087 QQuickControlPrivate::hideOldItem(vertical);
1088 const QQmlProperty visibleProperty(vertical, QStringLiteral("visible"));
1089 const QQmlProperty parentProperty(vertical, QStringLiteral("parent"));
1090 QQmlPropertyPrivate::removeBinding(visibleProperty);
1091 QQmlPropertyPrivate::removeBinding(parentProperty);
1092
1093 if (!flickable)
1094 return;
1095
1096 disconnect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical);
1097
1098 // TODO: export QQuickFlickableVisibleArea
1099 QObject *area = flickable->property("visibleArea").value<QObject *>();
1100 QObject::disconnect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal)));
1101 QObject::disconnect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal)));
1102}
1103
1105{
1106 QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(horizontal);
1107 p->moving = flickable->isMovingHorizontally();
1109}
1110
1112{
1113 QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(vertical);
1114 p->moving = flickable->isMovingVertically();
1116}
1117
1118// TODO: QQuickFlickable::maxXYExtent()
1123
1125{
1126 if (!flickable)
1127 return;
1128
1130
1131 const qreal viewwidth = f->width();
1132 const qreal maxxextent = -f->maxXExtent() + f->minXExtent();
1133 const qreal cx = horizontal->position() * (maxxextent + viewwidth) - f->minXExtent();
1134
1135 if (!qIsNaN(cx) && !qFuzzyCompare(cx, flickable->contentX()))
1136 flickable->setContentX(cx);
1137}
1138
1140{
1141 if (!flickable)
1142 return;
1143
1145
1146 const qreal viewheight = f->height();
1147 const qreal maxyextent = -f->maxYExtent() + f->minYExtent();
1148 const qreal cy = vertical->position() * (maxyextent + viewheight) - f->minYExtent();
1149
1150 if (!qIsNaN(cy) && !qFuzzyCompare(cy, flickable->contentY()))
1151 flickable->setContentY(cy);
1152}
1153
1158
1160{
1161 Q_ASSERT(horizontal && flickable);
1162 if (horizontal->parentItem() != flickable)
1163 return;
1164 horizontal->setWidth(flickable->width());
1165 if (move)
1166 horizontal->setY(flickable->height() - horizontal->height());
1167}
1168
1170{
1171 Q_ASSERT(vertical && flickable);
1172 if (vertical->parentItem() != flickable)
1173 return;
1174 vertical->setHeight(flickable->height());
1175 if (move)
1176 vertical->setX(vertical->isMirrored() ? 0 : flickable->width() - vertical->width());
1177}
1178
1179void QQuickScrollBarAttachedPrivate::itemGeometryChanged(QQuickItem *item, const QQuickGeometryChange change, const QRectF &diff)
1180{
1181 Q_UNUSED(item);
1182 Q_UNUSED(change);
1183 if (horizontal && horizontal->height() > 0) {
1184#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry
1185 bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), diff.height() - horizontal->height());
1186#else
1187 bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), item->height() - diff.height() - horizontal->height());
1188#endif
1189 if (flickable)
1191 }
1192 if (vertical && vertical->width() > 0) {
1193#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry
1194 bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), diff.width() - vertical->width());
1195#else
1196 bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), item->width() - diff.width() - vertical->width());
1197#endif
1198 if (flickable)
1199 layoutVertical(move);
1200 }
1201}
1202
1204{
1205 if (item == vertical && flickable)
1206 layoutVertical(true);
1207}
1208
1210{
1211 if (item == horizontal && flickable)
1213}
1214
1216{
1217 if (item == flickable)
1218 flickable = nullptr;
1219 if (item == horizontal)
1220 horizontal = nullptr;
1221 if (item == vertical)
1222 vertical = nullptr;
1223}
1224
1225QQuickScrollBarAttached::QQuickScrollBarAttached(QObject *parent)
1226 : QObject(*(new QQuickScrollBarAttachedPrivate), parent)
1227{
1228 Q_D(QQuickScrollBarAttached);
1229 d->setFlickable(qobject_cast<QQuickFlickable *>(parent));
1230
1231 if (parent && !d->flickable && !qobject_cast<QQuickScrollView *>(parent))
1232 qmlWarning(parent) << "ScrollBar attached property must be attached to an object deriving from Flickable or ScrollView";
1233}
1234
1235QQuickScrollBarAttached::~QQuickScrollBarAttached()
1236{
1237 Q_D(QQuickScrollBarAttached);
1238 if (d->horizontal) {
1239 QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QsbHorizontalChangeTypes);
1240 d->horizontal = nullptr;
1241 }
1242 if (d->vertical) {
1243 QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QsbVerticalChangeTypes);
1244 d->vertical = nullptr;
1245 }
1246 d->setFlickable(nullptr);
1247}
1248
1249/*!
1250 \qmlattachedproperty ScrollBar QtQuick.Controls::ScrollBar::horizontal
1251
1252 This property attaches a horizontal scroll bar to a \l Flickable.
1253
1254 \code
1255 Flickable {
1256 contentWidth: 2000
1257 ScrollBar.horizontal: ScrollBar { }
1258 }
1259 \endcode
1260
1261 \sa {Attaching ScrollBar to a Flickable}
1262*/
1263QQuickScrollBar *QQuickScrollBarAttached::horizontal() const
1264{
1265 Q_D(const QQuickScrollBarAttached);
1266 return d->horizontal;
1267}
1268
1269void QQuickScrollBarAttached::setHorizontal(QQuickScrollBar *horizontal)
1270{
1271 Q_D(QQuickScrollBarAttached);
1272 if (d->horizontal == horizontal)
1273 return;
1274
1275 if (d->horizontal) {
1276 QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QsbHorizontalChangeTypes);
1277 QObjectPrivate::disconnect(d->horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal);
1278
1279 // Call this regardless of whether we have a flickable, because we need to clean up the old
1280 // horizontal item.
1281 d->cleanupHorizontal();
1282 }
1283
1284 d->horizontal = horizontal;
1285
1286 if (horizontal) {
1287 if (!horizontal->parentItem())
1288 horizontal->setParentItem(qobject_cast<QQuickItem *>(parent()));
1289 horizontal->setOrientation(Qt::Horizontal);
1290
1291 QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, QsbHorizontalChangeTypes);
1292 QObjectPrivate::connect(horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal);
1293
1294 if (d->flickable)
1295 d->initHorizontal();
1296 }
1297 emit horizontalChanged();
1298}
1299
1300/*!
1301 \qmlattachedproperty ScrollBar QtQuick.Controls::ScrollBar::vertical
1302
1303 This property attaches a vertical scroll bar to a \l Flickable.
1304
1305 \code
1306 Flickable {
1307 contentHeight: 2000
1308 ScrollBar.vertical: ScrollBar { }
1309 }
1310 \endcode
1311
1312 \sa {Attaching ScrollBar to a Flickable}
1313*/
1314QQuickScrollBar *QQuickScrollBarAttached::vertical() const
1315{
1316 Q_D(const QQuickScrollBarAttached);
1317 return d->vertical;
1318}
1319
1320void QQuickScrollBarAttached::setVertical(QQuickScrollBar *vertical)
1321{
1322 Q_D(QQuickScrollBarAttached);
1323 if (d->vertical == vertical)
1324 return;
1325
1326 if (d->vertical) {
1327 QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QsbVerticalChangeTypes);
1328 QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical);
1329 QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical);
1330
1331 // Call this regardless of whether we have a flickable, because we need to clean up the old
1332 // vertical item.
1333 d->cleanupVertical();
1334 }
1335
1336 d->vertical = vertical;
1337
1338 if (vertical) {
1339 if (!vertical->parentItem())
1340 vertical->setParentItem(qobject_cast<QQuickItem *>(parent()));
1341 vertical->setOrientation(Qt::Vertical);
1342
1343 QQuickItemPrivate::get(vertical)->addItemChangeListener(d, QsbVerticalChangeTypes);
1344 QObjectPrivate::connect(vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical);
1345 QObjectPrivate::connect(vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical);
1346
1347 if (d->flickable)
1348 d->initVertical();
1349 }
1350 emit verticalChanged();
1351}
1352
1353QT_END_NAMESPACE
1354
1355#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 reanchorDragOffset(qreal position)
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
void setPositionFromDrag(qreal position, const QPointF &point)
qreal logicalPosition(qreal position) const
void updatePosition(qreal position, bool notifyVisualChange)
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