1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qquickscrollindicator_p.h"
38#include "qquickcontrol_p_p.h"
39
40#include <QtQml/qqmlinfo.h>
41#include <QtQuick/private/qquickflickable_p.h>
42#include <QtQuick/private/qquickitemchangelistener_p.h>
43
44QT_BEGIN_NAMESPACE
45
46/*!
47 \qmltype ScrollIndicator
48 \inherits Control
49//! \instantiates QQuickScrollIndicator
50 \inqmlmodule QtQuick.Controls
51 \since 5.7
52 \ingroup qtquickcontrols2-indicators
53 \brief Vertical or horizontal non-interactive scroll indicator.
54
55 \image qtquickcontrols2-scrollindicator.gif
56
57 ScrollIndicator is a non-interactive indicator that indicates the current scroll
58 position. A scroll indicator can be either \l vertical or \l horizontal, and can
59 be attached to any \l Flickable, such as \l ListView and \l GridView.
60
61 \code
62 Flickable {
63 // ...
64 ScrollIndicator.vertical: ScrollIndicator { }
65 }
66 \endcode
67
68 \section1 Attaching ScrollIndicator to a Flickable
69
70 \note When ScrollIndicator is attached \l {ScrollIndicator::vertical}{vertically}
71 or \l {ScrollIndicator::horizontal}{horizontally} to a Flickable, its geometry and
72 the following properties are automatically set and updated as appropriate:
73
74 \list
75 \li \l orientation
76 \li \l position
77 \li \l size
78 \li \l active
79 \endlist
80
81 An attached ScrollIndicator re-parents itself to the target Flickable. A vertically
82 attached ScrollIndicator resizes itself to the height of the Flickable, and positions
83 itself to either side of it based on the \l {Control::mirrored}{layout direction}.
84 A horizontally attached ScrollIndicator resizes itself to the width of the Flickable,
85 and positions itself to the bottom. The automatic geometry management can be disabled
86 by specifying another parent for the attached ScrollIndicator. This can be useful, for
87 example, if the ScrollIndicator should be placed outside a clipping Flickable. This is
88 demonstrated by the following example:
89
90 \code
91 Flickable {
92 id: flickable
93 clip: true
94 // ...
95 ScrollIndicator.vertical: ScrollIndicator {
96 parent: flickable.parent
97 anchors.top: flickable.top
98 anchors.left: flickable.right
99 anchors.bottom: flickable.bottom
100 }
101 }
102 \endcode
103
104 \section1 Binding the Active State of Horizontal and Vertical Scroll Indicators
105
106 Horizontal and vertical scroll indicators do not share the \l active state with
107 each other by default. In order to keep both indicators visible whilst scrolling
108 to either direction, establish a two-way binding between the active states as
109 presented by the following example:
110
111 \snippet qtquickcontrols2-scrollindicator-active.qml 1
112
113 \section1 Non-attached Scroll Indicators
114
115 It is possible to create an instance of ScrollIndicator without using the
116 attached property API. This is useful when the behavior of the attached
117 scoll indicator is not sufficient or a \l Flickable is not in use. In the
118 following example, horizontal and vertical scroll indicators are used to
119 indicate how far the user has scrolled over the text (using \l MouseArea
120 instead of \l Flickable):
121
122 \snippet qtquickcontrols2-scrollindicator-non-attached.qml 1
123
124 \image qtquickcontrols2-scrollindicator-non-attached.png
125
126 \sa ScrollBar, {Customizing ScrollIndicator}, {Indicator Controls}
127*/
128
129static const QQuickItemPrivate::ChangeTypes changeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed;
130static const QQuickItemPrivate::ChangeTypes horizontalChangeTypes = changeTypes | QQuickItemPrivate::ImplicitHeight;
131static const QQuickItemPrivate::ChangeTypes verticalChangeTypes = changeTypes | QQuickItemPrivate::ImplicitWidth;
132
133class QQuickScrollIndicatorPrivate : public QQuickControlPrivate
134{
135 Q_DECLARE_PUBLIC(QQuickScrollIndicator)
136
137public:
138 struct VisualArea
139 {
140 VisualArea(qreal pos, qreal sz)
141 : position(pos), size(sz) { }
142 qreal position = 0;
143 qreal size = 0;
144 };
145 VisualArea visualArea() const;
146 void visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea);
147
148 void resizeContent() override;
149
150 qreal size = 0;
151 qreal minimumSize = 0;
152 qreal position = 0;
153 bool active = false;
154 Qt::Orientation orientation = Qt::Vertical;
155};
156
157QQuickScrollIndicatorPrivate::VisualArea QQuickScrollIndicatorPrivate::visualArea() const
158{
159 qreal visualPos = position;
160 if (minimumSize > size)
161 visualPos = position / (1.0 - size) * (1.0 - minimumSize);
162
163 qreal visualSize = qBound<qreal>(min: 0, val: qMax(a: size, b: minimumSize) + qMin<qreal>(a: 0, b: visualPos), max: 1.0 - visualPos);
164
165 visualPos = qBound<qreal>(min: 0, val: visualPos, max: 1.0 - visualSize);
166
167 return VisualArea(visualPos, visualSize);
168}
169
170void QQuickScrollIndicatorPrivate::visualAreaChange(const VisualArea &newVisualArea, const VisualArea &oldVisualArea)
171{
172 Q_Q(QQuickScrollIndicator);
173 if (!qFuzzyCompare(p1: newVisualArea.size, p2: oldVisualArea.size))
174 emit q->visualSizeChanged();
175 if (!qFuzzyCompare(p1: newVisualArea.position, p2: oldVisualArea.position))
176 emit q->visualPositionChanged();
177}
178
179void QQuickScrollIndicatorPrivate::resizeContent()
180{
181 Q_Q(QQuickScrollIndicator);
182 if (!contentItem)
183 return;
184
185 // - negative overshoot (pos < 0): clamp the pos to 0, and deduct the overshoot from the size
186 // - positive overshoot (pos + size > 1): clamp the size to 1-pos
187 const VisualArea visual = visualArea();
188
189 if (orientation == Qt::Horizontal) {
190 contentItem->setPosition(QPointF(q->leftPadding() + visual.position * q->availableWidth(), q->topPadding()));
191 contentItem->setSize(QSizeF(q->availableWidth() * visual.size, q->availableHeight()));
192 } else {
193 contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + visual.position * q->availableHeight()));
194 contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * visual.size));
195 }
196}
197
198QQuickScrollIndicator::QQuickScrollIndicator(QQuickItem *parent)
199 : QQuickControl(*(new QQuickScrollIndicatorPrivate), parent)
200{
201}
202
203QQuickScrollIndicatorAttached *QQuickScrollIndicator::qmlAttachedProperties(QObject *object)
204{
205 return new QQuickScrollIndicatorAttached(object);
206}
207
208/*!
209 \qmlproperty real QtQuick.Controls::ScrollIndicator::size
210
211 This property holds the size of the indicator, scaled to \c {0.0 - 1.0}.
212
213 \sa {Flickable::visibleArea.heightRatio}{Flickable::visibleArea}
214
215 This property is automatically set when the scroll indicator is
216 \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
217
218 \sa minimumSize, visualSize
219*/
220qreal QQuickScrollIndicator::size() const
221{
222 Q_D(const QQuickScrollIndicator);
223 return d->size;
224}
225
226void QQuickScrollIndicator::setSize(qreal size)
227{
228 Q_D(QQuickScrollIndicator);
229 if (qFuzzyCompare(p1: d->size, p2: size))
230 return;
231
232 auto oldVisualArea = d->visualArea();
233 d->size = size;
234 if (isComponentComplete())
235 d->resizeContent();
236 emit sizeChanged();
237 d->visualAreaChange(newVisualArea: d->visualArea(), oldVisualArea);
238}
239
240/*!
241 \qmlproperty real QtQuick.Controls::ScrollIndicator::position
242
243 This property holds the position of the indicator, scaled to \c {0.0 - 1.0}.
244
245 This property is automatically set when the scroll indicator is
246 \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
247
248 \sa {Flickable::visibleArea.yPosition}{Flickable::visibleArea}, visualPosition
249*/
250qreal QQuickScrollIndicator::position() const
251{
252 Q_D(const QQuickScrollIndicator);
253 return d->position;
254}
255
256void QQuickScrollIndicator::setPosition(qreal position)
257{
258 Q_D(QQuickScrollIndicator);
259 if (qFuzzyCompare(p1: d->position, p2: position))
260 return;
261
262 auto oldVisualArea = d->visualArea();
263 d->position = position;
264 if (isComponentComplete())
265 d->resizeContent();
266 emit positionChanged();
267 d->visualAreaChange(newVisualArea: d->visualArea(), oldVisualArea);
268}
269
270/*!
271 \qmlproperty bool QtQuick.Controls::ScrollIndicator::active
272
273 This property holds whether the indicator is active, that is, when the
274 attached Flickable is \l {Flickable::moving}{moving}.
275
276 It is possible to keep \l {Binding the Active State of Horizontal and Vertical Scroll Indicators}
277 {both horizontal and vertical indicators visible} while scrolling in either direction.
278
279 This property is automatically set when the scroll indicator is
280 \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
281*/
282bool QQuickScrollIndicator::isActive() const
283{
284 Q_D(const QQuickScrollIndicator);
285 return d->active;
286}
287
288void QQuickScrollIndicator::setActive(bool active)
289{
290 Q_D(QQuickScrollIndicator);
291 if (d->active == active)
292 return;
293
294 d->active = active;
295 emit activeChanged();
296}
297
298/*!
299 \qmlproperty enumeration QtQuick.Controls::ScrollIndicator::orientation
300
301 This property holds the orientation of the indicator.
302
303 Possible values:
304 \value Qt.Horizontal Horizontal
305 \value Qt.Vertical Vertical (default)
306
307 This property is automatically set when the scroll indicator is
308 \l {Attaching ScrollIndicator to a Flickable}{attached to a flickable}.
309
310 \sa horizontal, vertical
311*/
312Qt::Orientation QQuickScrollIndicator::orientation() const
313{
314 Q_D(const QQuickScrollIndicator);
315 return d->orientation;
316}
317
318void QQuickScrollIndicator::setOrientation(Qt::Orientation orientation)
319{
320 Q_D(QQuickScrollIndicator);
321 if (d->orientation == orientation)
322 return;
323
324 d->orientation = orientation;
325 if (isComponentComplete())
326 d->resizeContent();
327 emit orientationChanged();
328}
329
330/*!
331 \since QtQuick.Controls 2.3 (Qt 5.10)
332 \qmlproperty bool QtQuick.Controls::ScrollIndicator::horizontal
333 \readonly
334
335 This property holds whether the scroll indicator is horizontal.
336
337 \sa orientation
338*/
339bool QQuickScrollIndicator::isHorizontal() const
340{
341 Q_D(const QQuickScrollIndicator);
342 return d->orientation == Qt::Horizontal;
343}
344
345/*!
346 \since QtQuick.Controls 2.3 (Qt 5.10)
347 \qmlproperty bool QtQuick.Controls::ScrollIndicator::vertical
348 \readonly
349
350 This property holds whether the scroll indicator is vertical.
351
352 \sa orientation
353*/
354bool QQuickScrollIndicator::isVertical() const
355{
356 Q_D(const QQuickScrollIndicator);
357 return d->orientation == Qt::Vertical;
358}
359
360/*!
361 \since QtQuick.Controls 2.4 (Qt 5.11)
362 \qmlproperty real QtQuick.Controls::ScrollIndicator::minimumSize
363
364 This property holds the minimum size of the indicator, scaled to \c {0.0 - 1.0}.
365
366 \sa size, visualSize, visualPosition
367*/
368qreal QQuickScrollIndicator::minimumSize() const
369{
370 Q_D(const QQuickScrollIndicator);
371 return d->minimumSize;
372}
373
374void QQuickScrollIndicator::setMinimumSize(qreal minimumSize)
375{
376 Q_D(QQuickScrollIndicator);
377 if (qFuzzyCompare(p1: d->minimumSize, p2: minimumSize))
378 return;
379
380 auto oldVisualArea = d->visualArea();
381 d->minimumSize = minimumSize;
382 if (isComponentComplete())
383 d->resizeContent();
384 emit minimumSizeChanged();
385 d->visualAreaChange(newVisualArea: d->visualArea(), oldVisualArea);
386}
387
388/*!
389 \since QtQuick.Controls 2.4 (Qt 5.11)
390 \qmlproperty real QtQuick.Controls::ScrollIndicator::visualSize
391
392 This property holds the effective visual size of the indicator,
393 which may be limited by the \l {minimumSize}{minimum size}.
394
395 \sa size, minimumSize
396*/
397qreal QQuickScrollIndicator::visualSize() const
398{
399 Q_D(const QQuickScrollIndicator);
400 return d->visualArea().size;
401}
402
403/*!
404 \since QtQuick.Controls 2.4 (Qt 5.11)
405 \qmlproperty real QtQuick.Controls::ScrollIndicator::visualPosition
406
407 This property holds the effective visual position of the indicator,
408 which may be limited by the \l {minimumSize}{minimum size}.
409
410 \sa position, minimumSize
411*/
412qreal QQuickScrollIndicator::visualPosition() const
413{
414 Q_D(const QQuickScrollIndicator);
415 return d->visualArea().position;
416}
417
418class QQuickScrollIndicatorAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
419{
420public:
421 void activateHorizontal();
422 void activateVertical();
423
424 void layoutHorizontal(bool move = true);
425 void layoutVertical(bool move = true);
426
427 void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
428 void itemImplicitWidthChanged(QQuickItem *item) override;
429 void itemImplicitHeightChanged(QQuickItem *item) override;
430 void itemDestroyed(QQuickItem *item) override;
431
432 QQuickFlickable *flickable = nullptr;
433 QQuickScrollIndicator *horizontal = nullptr;
434 QQuickScrollIndicator *vertical = nullptr;
435};
436
437void QQuickScrollIndicatorAttachedPrivate::activateHorizontal()
438{
439 horizontal->setActive(flickable->isMovingHorizontally());
440}
441
442void QQuickScrollIndicatorAttachedPrivate::activateVertical()
443{
444 vertical->setActive(flickable->isMovingVertically());
445}
446
447void QQuickScrollIndicatorAttachedPrivate::layoutHorizontal(bool move)
448{
449 Q_ASSERT(horizontal && flickable);
450 if (horizontal->parentItem() != flickable)
451 return;
452 horizontal->setWidth(flickable->width());
453 if (move)
454 horizontal->setY(flickable->height() - horizontal->height());
455}
456
457void QQuickScrollIndicatorAttachedPrivate::layoutVertical(bool move)
458{
459 Q_ASSERT(vertical && flickable);
460 if (vertical->parentItem() != flickable)
461 return;
462 vertical->setHeight(flickable->height());
463 if (move && !QQuickItemPrivate::get(item: vertical)->isMirrored())
464 vertical->setX(flickable->width() - vertical->width());
465}
466
467void QQuickScrollIndicatorAttachedPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
468{
469 Q_UNUSED(item);
470 Q_UNUSED(change);
471 if (horizontal && horizontal->height() > 0) {
472#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry
473 bool move = qFuzzyIsNull(d: horizontal->y()) || qFuzzyCompare(p1: horizontal->y(), p2: diff.height() - horizontal->height());
474#else
475 bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), item->height() - diff.height() - horizontal->height());
476#endif
477 layoutHorizontal(move);
478 }
479 if (vertical && vertical->width() > 0) {
480#ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry
481 bool move = qFuzzyIsNull(d: vertical->x()) || qFuzzyCompare(p1: vertical->x(), p2: diff.width() - vertical->width());
482#else
483 bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), item->width() - diff.width() - vertical->width());
484#endif
485 layoutVertical(move);
486 }
487}
488
489void QQuickScrollIndicatorAttachedPrivate::itemImplicitWidthChanged(QQuickItem *item)
490{
491 if (item == vertical)
492 layoutVertical(move: true);
493}
494
495void QQuickScrollIndicatorAttachedPrivate::itemImplicitHeightChanged(QQuickItem *item)
496{
497 if (item == horizontal)
498 layoutHorizontal(move: true);
499}
500
501void QQuickScrollIndicatorAttachedPrivate::itemDestroyed(QQuickItem *item)
502{
503 if (item == horizontal)
504 horizontal = nullptr;
505 if (item == vertical)
506 vertical = nullptr;
507}
508
509QQuickScrollIndicatorAttached::QQuickScrollIndicatorAttached(QObject *parent)
510 : QObject(*(new QQuickScrollIndicatorAttachedPrivate), parent)
511{
512 Q_D(QQuickScrollIndicatorAttached);
513 d->flickable = qobject_cast<QQuickFlickable *>(object: parent);
514 if (d->flickable)
515 QQuickItemPrivate::get(item: d->flickable)->updateOrAddGeometryChangeListener(listener: d, types: QQuickGeometryChange::Size);
516 else if (parent)
517 qmlWarning(me: parent) << "ScrollIndicator must be attached to a Flickable";
518}
519
520QQuickScrollIndicatorAttached::~QQuickScrollIndicatorAttached()
521{
522 Q_D(QQuickScrollIndicatorAttached);
523 if (d->flickable) {
524 if (d->horizontal)
525 QQuickItemPrivate::get(item: d->horizontal)->removeItemChangeListener(d, types: horizontalChangeTypes);
526 if (d->vertical)
527 QQuickItemPrivate::get(item: d->vertical)->removeItemChangeListener(d,types: verticalChangeTypes);
528 // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size).
529 // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling
530 // pointer on destruction.
531 QQuickItemPrivate::get(item: d->flickable)->removeItemChangeListener(d, types: QQuickItemPrivate::Geometry);
532 }
533}
534
535/*!
536 \qmlattachedproperty ScrollIndicator QtQuick.Controls::ScrollIndicator::horizontal
537
538 This property attaches a horizontal scroll indicator to a \l Flickable.
539
540 \code
541 Flickable {
542 contentWidth: 2000
543 ScrollIndicator.horizontal: ScrollIndicator { }
544 }
545 \endcode
546
547 \sa {Attaching ScrollIndicator to a Flickable}
548*/
549QQuickScrollIndicator *QQuickScrollIndicatorAttached::horizontal() const
550{
551 Q_D(const QQuickScrollIndicatorAttached);
552 return d->horizontal;
553}
554
555void QQuickScrollIndicatorAttached::setHorizontal(QQuickScrollIndicator *horizontal)
556{
557 Q_D(QQuickScrollIndicatorAttached);
558 if (d->horizontal == horizontal)
559 return;
560
561 if (d->horizontal && d->flickable) {
562 QQuickItemPrivate::get(item: d->horizontal)->removeItemChangeListener(d, types: horizontalChangeTypes);
563 QObjectPrivate::disconnect(sender: d->flickable, signal: &QQuickFlickable::movingHorizontallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateHorizontal);
564
565 // TODO: export QQuickFlickableVisibleArea
566 QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>();
567 disconnect(sender: area, SIGNAL(widthRatioChanged(qreal)), receiver: d->horizontal, SLOT(setSize(qreal)));
568 disconnect(sender: area, SIGNAL(xPositionChanged(qreal)), receiver: d->horizontal, SLOT(setPosition(qreal)));
569 }
570
571 d->horizontal = horizontal;
572
573 if (horizontal && d->flickable) {
574 if (!horizontal->parentItem())
575 horizontal->setParentItem(d->flickable);
576 horizontal->setOrientation(Qt::Horizontal);
577
578 QQuickItemPrivate::get(item: horizontal)->addItemChangeListener(listener: d, types: horizontalChangeTypes);
579 QObjectPrivate::connect(sender: d->flickable, signal: &QQuickFlickable::movingHorizontallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateHorizontal);
580
581 // TODO: export QQuickFlickableVisibleArea
582 QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>();
583 connect(sender: area, SIGNAL(widthRatioChanged(qreal)), receiver: horizontal, SLOT(setSize(qreal)));
584 connect(sender: area, SIGNAL(xPositionChanged(qreal)), receiver: horizontal, SLOT(setPosition(qreal)));
585
586 d->layoutHorizontal();
587 horizontal->setSize(area->property(name: "widthRatio").toReal());
588 horizontal->setPosition(area->property(name: "xPosition").toReal());
589 }
590 emit horizontalChanged();
591}
592
593/*!
594 \qmlattachedproperty ScrollIndicator QtQuick.Controls::ScrollIndicator::vertical
595
596 This property attaches a vertical scroll indicator to a \l Flickable.
597
598 \code
599 Flickable {
600 contentHeight: 2000
601 ScrollIndicator.vertical: ScrollIndicator { }
602 }
603 \endcode
604
605 \sa {Attaching ScrollIndicator to a Flickable}
606*/
607QQuickScrollIndicator *QQuickScrollIndicatorAttached::vertical() const
608{
609 Q_D(const QQuickScrollIndicatorAttached);
610 return d->vertical;
611}
612
613void QQuickScrollIndicatorAttached::setVertical(QQuickScrollIndicator *vertical)
614{
615 Q_D(QQuickScrollIndicatorAttached);
616 if (d->vertical == vertical)
617 return;
618
619 if (d->vertical && d->flickable) {
620 QQuickItemPrivate::get(item: d->vertical)->removeItemChangeListener(d, types: verticalChangeTypes);
621 QObjectPrivate::disconnect(sender: d->flickable, signal: &QQuickFlickable::movingVerticallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateVertical);
622
623 // TODO: export QQuickFlickableVisibleArea
624 QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>();
625 disconnect(sender: area, SIGNAL(heightRatioChanged(qreal)), receiver: d->vertical, SLOT(setSize(qreal)));
626 disconnect(sender: area, SIGNAL(yPositionChanged(qreal)), receiver: d->vertical, SLOT(setPosition(qreal)));
627 }
628
629 d->vertical = vertical;
630
631 if (vertical && d->flickable) {
632 if (!vertical->parentItem())
633 vertical->setParentItem(d->flickable);
634 vertical->setOrientation(Qt::Vertical);
635
636 QQuickItemPrivate::get(item: vertical)->addItemChangeListener(listener: d, types: verticalChangeTypes);
637 QObjectPrivate::connect(sender: d->flickable, signal: &QQuickFlickable::movingVerticallyChanged, receiverPrivate: d, slot: &QQuickScrollIndicatorAttachedPrivate::activateVertical);
638
639 // TODO: export QQuickFlickableVisibleArea
640 QObject *area = d->flickable->property(name: "visibleArea").value<QObject *>();
641 connect(sender: area, SIGNAL(heightRatioChanged(qreal)), receiver: vertical, SLOT(setSize(qreal)));
642 connect(sender: area, SIGNAL(yPositionChanged(qreal)), receiver: vertical, SLOT(setPosition(qreal)));
643
644 d->layoutVertical();
645 vertical->setSize(area->property(name: "heightRatio").toReal());
646 vertical->setPosition(area->property(name: "yPosition").toReal());
647 }
648 emit verticalChanged();
649}
650
651#if QT_CONFIG(quicktemplates2_multitouch)
652void QQuickScrollIndicator::touchEvent(QTouchEvent *event)
653{
654 event->ignore(); // QTBUG-61785
655}
656#endif
657
658#if QT_CONFIG(accessibility)
659QAccessible::Role QQuickScrollIndicator::accessibleRole() const
660{
661 return QAccessible::Indicator;
662}
663#endif
664
665QT_END_NAMESPACE
666

source code of qtquickcontrols2/src/quicktemplates2/qquickscrollindicator.cpp