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
qquickscrollview.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 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 <QtQuick/private/qquickflickable_p.h>
10
12
13/*!
14 \qmltype ScrollView
15 \inherits Pane
16//! \nativetype QQuickScrollView
17 \inqmlmodule QtQuick.Controls
18 \since 5.9
19 \ingroup qtquickcontrols-containers
20 \ingroup qtquickcontrols-focusscopes
21 \brief Scrollable view.
22
23 ScrollView provides scrolling for user-defined content. It can be used to
24 either replace a \l Flickable, or to decorate an existing one.
25
26 \image qtquickcontrols-scrollview.png
27
28 The first example demonstrates the simplest usage of ScrollView.
29
30 \snippet qtquickcontrols-scrollview.qml file
31
32 The second example illustrates using an existing \l Flickable, that is,
33 a \l ListView.
34
35 \snippet qtquickcontrols-scrollview-listview.qml file
36
37 \note As of Qt-6.0, ScrollView automatically clips its contents if you
38 don't use a Flickable as a child. If this is not wanted, you can
39 set your own Flickable as a child, and control the \l {Item::}{clip}
40 property on the Flickable explicitly.
41
42 \section2 Sizing
43
44 As with Flickable, there are several things to keep in mind when using
45 ScrollView:
46 \list
47 \li If only a single item is used within a ScrollView, the content size is
48 automatically calculated based on the implicit size of its contained item.
49 However, if more than one item is used (or an implicit size is not
50 provided), the \l {QtQuick.Controls::Pane::}{contentWidth} and
51 \l {QtQuick.Controls::Pane::}{contentHeight} properties must
52 be set to the combined size of its contained items.
53 \li If the content size is less than or equal to the size of the ScrollView,
54 it will not be scrollable.
55 \li If you want the ScrollView to only scroll vertically, you can bind
56 \l {QtQuick.Controls::Pane::}{contentWidth} to
57 \l {QtQuick.Controls::Control::}{availableWidth}
58 (and vice versa for contentHeight). This will let the contents fill
59 out all the available space horizontally inside the ScrollView, taking
60 any padding or scroll bars into account.
61 \endlist
62
63 \section2 Scroll Bars
64
65 The horizontal and vertical scroll bars can be accessed and customized using
66 the \l {ScrollBar::horizontal}{ScrollBar.horizontal} and \l {ScrollBar::vertical}
67 {ScrollBar.vertical} attached properties. The following example adjusts the scroll
68 bar policies so that the horizontal scroll bar is always off, and the vertical
69 scroll bar is always on.
70
71 \snippet qtquickcontrols-scrollview-policy.qml file
72
73 \section2 Touch vs. Mouse Interaction
74
75 On touch, ScrollView enables flicking and makes the scroll bars non-interactive.
76
77 \image qtquickcontrols-scrollindicator.gif
78
79 When interacted with a mouse device, flicking is disabled and the scroll bars
80 are interactive.
81
82 \image qtquickcontrols-scrollbar.gif
83
84 Scroll bars can be made interactive on touch, or non-interactive when interacted
85 with a mouse device, by setting the \l {ScrollBar::}{interactive} property explicitly
86 to \c true or \c false, respectively.
87
88 \snippet qtquickcontrols-scrollview-interactive.qml file
89
90 \include varying-delegate-heights-section.qdocinc {file} {2} {ScrollBar}
91
92 \sa ScrollBar, ScrollIndicator, {Customizing ScrollView}, {Container Controls},
93 {Focus Management in Qt Quick Controls}
94*/
95
97{
98public:
99 Q_DECLARE_PUBLIC(QQuickScrollView)
100
103 QList<QQuickItem *> contentChildItems() const override;
104 QQuickItem* getFirstChild() const override;
105
107
112
113 QQuickFlickable *ensureFlickable(ContentItemFlag contentItemFlag);
114 bool setFlickable(QQuickFlickable *flickable, ContentItemFlag contentItemFlag);
115
118
119 qreal getContentWidth() const override;
120 qreal getContentHeight() const override;
121
124
125 void setScrollBarsInteractive(bool interactive);
126
127 static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj);
128 static qsizetype contentData_count(QQmlListProperty<QObject> *prop);
129 static QObject *contentData_at(QQmlListProperty<QObject> *prop, qsizetype index);
130 static void contentData_clear(QQmlListProperty<QObject> *prop);
131
132 static void contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *obj);
133 static qsizetype contentChildren_count(QQmlListProperty<QQuickItem> *prop);
134 static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index);
135 static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop);
136
137 void itemImplicitWidthChanged(QQuickItem *item) override;
138
141
143 bool wasTouched = false;
144 QQuickFlickable *flickable = nullptr;
150};
151
153{
154 if (!flickable)
155 return QList<QQuickItem *>();
156
157 return flickable->contentItem()->childItems();
158}
159
161{
162 if (!contentItem)
163 executeContentItem();
164 // This function is called by QQuickControl::contentItem() to lazily create
165 // a contentItem, so we don't need to try to set it again.
167}
168
170{
171 return contentChildItems().value(0);
172}
173
175{
176 Q_Q(QQuickScrollView);
177 if (!flickable) {
180 // Pass ourselves as the Flickable's parent item.
181 auto flickable = new QQuickFlickable(q);
182 // We almost always want to clip the flickable so that flickable
183 // contents doesn't show up outside the scrollview. The only time
184 // this is not really needed, is when the scrollview covers the whole
185 // window and the scrollbars are transient. But for that corner case, if this
186 // optimization is needed, the user can simply create his own flickable
187 // child inside the scrollview, and control clipping on it explicit.
188 flickable->setClip(true);
189 flickable->setPixelAligned(true);
190 setFlickable(flickable, contentItemFlag);
191 }
192 return flickable;
193}
194
196{
197 Q_Q(QQuickScrollView);
198 qreal oldEffectiveScrollBarWidth = effectiveScrollBarWidth;
199 if (auto *vBar = verticalScrollBar()) {
200 if (vBar->policy() == QQuickScrollBar::AlwaysOff || !vBar->isVisible())
201 effectiveScrollBarWidth = 0;
202 else
203 effectiveScrollBarWidth = vBar->width();
204 }
205 if (effectiveScrollBarWidth != oldEffectiveScrollBarWidth) {
206 if (!isUpdatingScrollBar) {
207 QScopedValueRollback<bool> rollback(isUpdatingScrollBar, true);
208 emit q->effectiveScrollBarWidthChanged();
209 }
210 }
211}
212
214{
215 Q_Q(QQuickScrollView);
216 qreal oldEffectiveScrollBarHeight = effectiveScrollBarHeight;
217 if (auto *hBar = horizontalScrollBar()) {
218 if (hBar->policy() == QQuickScrollBar::AlwaysOff || !hBar->isVisible())
219 effectiveScrollBarHeight = 0;
220 else
221 effectiveScrollBarHeight = hBar->height();
222 }
223 if (effectiveScrollBarHeight != oldEffectiveScrollBarHeight) {
224 if (!isUpdatingScrollBar) {
225 QScopedValueRollback<bool> rollback(isUpdatingScrollBar, true);
226 emit q->effectiveScrollBarHeightChanged();
227 }
228
229 }
230}
231
233{
234 if (!scrollBar)
235 return;
236
237 if (scrollBar->vertical) {
238 QObjectPrivate::disconnect(scrollBar->vertical, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarWidth);
239 QObjectPrivate::disconnect(scrollBar->vertical, &QQuickScrollBar::visibleChanged, this, &QQuickScrollViewPrivate::updateScrollBarWidth);
240 }
241 if (scrollBar->horizontal) {
242 QObjectPrivate::disconnect(scrollBar->horizontal, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarHeight);
243 QObjectPrivate::disconnect(scrollBar->horizontal, &QQuickScrollBar::visibleChanged, this, &QQuickScrollViewPrivate::updateScrollBarHeight);
244 }
245}
246
247bool QQuickScrollViewPrivate::setFlickable(QQuickFlickable *item, ContentItemFlag contentItemFlag)
248{
249 Q_Q(QQuickScrollView);
250 if (item == flickable)
251 return false;
252
253 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
254
255 if (flickable) {
256 flickable->removeEventFilter(q);
257
258 if (attached) {
259 auto *scrollBar = QQuickScrollBarAttachedPrivate::get(attached);
260 scrollBar->setFlickable(nullptr);
262 }
263
264 QObjectPrivate::disconnect(flickable->contentItem(), &QQuickItem::childrenChanged, this, &QQuickPanePrivate::contentChildrenChange);
265 QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::flickableContentWidthChanged);
266 QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::flickableContentHeightChanged);
267 }
268
269 flickable = item;
270 if (contentItemFlag == ContentItemFlag::Set)
271 q->setContentItem(flickable);
272
273 if (flickable) {
274 flickable->installEventFilter(q);
275 if (hasContentWidth)
276 flickable->setContentWidth(contentWidth);
277 else
279 if (hasContentHeight)
280 flickable->setContentHeight(contentHeight);
281 else
283
284 if (attached) {
285 auto *scrollBar = QQuickScrollBarAttachedPrivate::get(attached);
286 scrollBar->setFlickable(flickable);
287 if (scrollBar->vertical) {
288 QObjectPrivate::connect(scrollBar->vertical, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarWidth);
289 QObjectPrivate::connect(scrollBar->vertical, &QQuickScrollBar::visibleChanged, this, &QQuickScrollViewPrivate::updateScrollBarWidth);
290 }
291 if (scrollBar->horizontal) {
292 QObjectPrivate::connect(scrollBar->horizontal, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarHeight);
293 QObjectPrivate::connect(scrollBar->horizontal, &QQuickScrollBar::visibleChanged, this, &QQuickScrollViewPrivate::updateScrollBarHeight);
294 }
295 }
296
297 QObjectPrivate::connect(flickable->contentItem(), &QQuickItem::childrenChanged, this, &QQuickPanePrivate::contentChildrenChange);
298 QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::flickableContentWidthChanged);
299 QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::flickableContentHeightChanged);
300 }
301
302 return true;
303}
304
306{
307 Q_Q(QQuickScrollView);
308 if (!flickable || !componentComplete)
309 return;
310
311 const qreal cw = flickable->contentWidth();
312 if (qFuzzyCompare(cw, implicitContentWidth))
313 return;
314
316 implicitContentWidth = cw;
317 emit q->implicitContentWidthChanged();
318}
319
321{
322 Q_Q(QQuickScrollView);
323 if (!flickable || !componentComplete)
324 return;
325
326 const qreal ch = flickable->contentHeight();
327 if (qFuzzyCompare(ch, implicitContentHeight))
328 return;
329
331 implicitContentHeight = ch;
332 emit q->implicitContentHeightChanged();
333}
334
336{
338 return flickable->contentWidth();
339
340 // The scrollview wraps a flickable created by us, and nobody searched for it and
341 // modified its contentWidth. In that case, since the application does not control
342 // this flickable, we fall back to calculate the content width based on the child
343 // items inside it.
344 return QQuickPanePrivate::getContentWidth();
345}
346
348{
350 return flickable->contentHeight();
351
352 // The scrollview wraps a flickable created by us, and nobody searched for it and
353 // modified its contentHeight. In that case, since the application does not control
354 // this flickable, we fall back to calculate the content height based on the child
355 // items inside it.
356 return QQuickPanePrivate::getContentHeight();
357}
358
360{
361 Q_Q(const QQuickScrollView);
362 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
363 if (!attached)
364 return nullptr;
365 return attached->vertical();
366}
367
369{
370 Q_Q(const QQuickScrollView);
371 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
372 if (!attached)
373 return nullptr;
374 return attached->horizontal();
375}
376
378{
379 QQuickScrollBar *hbar = horizontalScrollBar();
380 if (hbar) {
381 QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(hbar);
383 p->setInteractive(interactive);
384 }
385
386 QQuickScrollBar *vbar = verticalScrollBar();
387 if (vbar) {
388 QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(vbar);
390 p->setInteractive(interactive);
391 }
392}
393
394void QQuickScrollViewPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
395{
396 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
397 // If we don't yet have a flickable assigned, and this object is a Flickable,
398 // make it our contentItem.
399 if (!p->flickable && p->setFlickable(qobject_cast<QQuickFlickable *>(obj), ContentItemFlag::Set))
400 return;
401
402 QQuickFlickable *flickable = p->ensureFlickable(ContentItemFlag::Set);
403 Q_ASSERT(flickable);
404 // Add the object that was declared as a child of us as a child object of the Flickable.
405 QQmlListProperty<QObject> data = flickable->flickableData();
406 data.append(&data, obj);
407}
408
409qsizetype QQuickScrollViewPrivate::contentData_count(QQmlListProperty<QObject> *prop)
410{
411 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
412 if (!p->flickable)
413 return 0;
414
415 QQmlListProperty<QObject> data = p->flickable->flickableData();
416 return data.count(&data);
417}
418
419QObject *QQuickScrollViewPrivate::contentData_at(QQmlListProperty<QObject> *prop, qsizetype index)
420{
421 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
422 if (!p->flickable)
423 return nullptr;
424
425 QQmlListProperty<QObject> data = p->flickable->flickableData();
426 return data.at(&data, index);
427}
428
429void QQuickScrollViewPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
430{
431 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
432 if (!p->flickable)
433 return;
434
435 QQmlListProperty<QObject> data = p->flickable->flickableData();
436 return data.clear(&data);
437}
438
439void QQuickScrollViewPrivate::contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item)
440{
441 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
442 if (!p->flickable)
443 p->setFlickable(qobject_cast<QQuickFlickable *>(item), ContentItemFlag::Set);
444
445 QQuickFlickable *flickable = p->ensureFlickable(ContentItemFlag::Set);
446 Q_ASSERT(flickable);
447 // Add the item that was declared as a child of us as a child item of the Flickable's contentItem.
448 QQmlListProperty<QQuickItem> children = flickable->flickableChildren();
449 children.append(&children, item);
450}
451
452qsizetype QQuickScrollViewPrivate::contentChildren_count(QQmlListProperty<QQuickItem> *prop)
453{
454 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
455 if (!p->flickable)
456 return 0;
457
458 QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
459 return children.count(&children);
460}
461
462QQuickItem *QQuickScrollViewPrivate::contentChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index)
463{
464 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
465 if (!p->flickable)
466 return nullptr;
467
468 QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
469 return children.at(&children, index);
470}
471
472void QQuickScrollViewPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> *prop)
473{
474 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
475 if (!p->flickable)
476 return;
477
478 QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
479 children.clear(&children);
480}
481
483{
484 // a special case for width<->height dependent content (wrapping text) in ScrollView
485 if (contentWidth < 0 && !componentComplete)
486 return;
487
488 QQuickPanePrivate::itemImplicitWidthChanged(item);
489}
490
491QQuickScrollView::QQuickScrollView(QQuickItem *parent)
492 : QQuickPane(*(new QQuickScrollViewPrivate), parent)
493{
494 Q_D(QQuickScrollView);
495 d->contentWidth = -1;
496 d->contentHeight = -1;
497
498 setFiltersChildMouseEvents(true);
499 setWheelEnabled(true);
500}
501
502QQuickScrollView::~QQuickScrollView()
503{
504 Q_D(QQuickScrollView);
505 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(this, false));
506 if (attached) {
507 auto *scrollBar = QQuickScrollBarAttachedPrivate::get(attached);
508 d->disconnectScrollBarSignals(scrollBar);
509 }
510}
511
512/*!
513 \qmlproperty real QtQuick.Controls::ScrollView::effectiveScrollBarWidth
514 \since 6.6
515
516 This property holds the effective width of the vertical scrollbar.
517 When the scrollbar is visible, this property is the current width of the
518 scrollbar. When the scroll bar is not visible or its policy is set to
519 \c QQuickScrollBar::AlwaysOff, this property is \c 0.
520
521 \sa {ScrollBar::policy}
522*/
523qreal QQuickScrollView::effectiveScrollBarWidth()
524{
525 Q_D(QQuickScrollView);
526 return d->effectiveScrollBarWidth;
527}
528
529/*!
530 \qmlproperty real QtQuick.Controls::ScrollView::effectiveScrollBarHeight
531 \since 6.6
532
533 This property holds the effective height of the horizontal scrollbar.
534 When the scrollbar is visible, this property is the current height of
535 the scrollbar. When the scroll bar is not visible or its policy is set
536 to \c QQuickScrollBar::AlwaysOff, this property is \c 0.
537
538 \sa {ScrollBar::policy}
539*/
540qreal QQuickScrollView::effectiveScrollBarHeight()
541{
542 Q_D(QQuickScrollView);
543 return d->effectiveScrollBarHeight;
544}
545
546/*!
547 \qmlproperty list<QtObject> QtQuick.Controls::ScrollView::contentData
548 \qmldefault
549
550 This property holds the list of content data.
551
552 The list contains all objects that have been declared in QML as children of the view.
553
554 \note Unlike \c contentChildren, \c contentData does include non-visual QML objects.
555
556 \sa Item::data, contentChildren
557*/
558QQmlListProperty<QObject> QQuickScrollViewPrivate::contentData()
559{
560 Q_Q(QQuickScrollView);
561 return QQmlListProperty<QObject>(q, this,
562 QQuickScrollViewPrivate::contentData_append,
563 QQuickScrollViewPrivate::contentData_count,
564 QQuickScrollViewPrivate::contentData_at,
565 QQuickScrollViewPrivate::contentData_clear);
566}
567
568/*!
569 \qmlproperty list<Item> QtQuick.Controls::ScrollView::contentChildren
570
571 This property holds the list of content children.
572
573 The list contains all items that have been declared in QML as children of the view.
574
575 \note Unlike \c contentData, \c contentChildren does not include non-visual QML objects.
576
577 \sa Item::children, contentData
578*/
580{
581 Q_Q(QQuickScrollView);
582 return QQmlListProperty<QQuickItem>(q, this,
583 QQuickScrollViewPrivate::contentChildren_append,
584 QQuickScrollViewPrivate::contentChildren_count,
585 QQuickScrollViewPrivate::contentChildren_at,
586 QQuickScrollViewPrivate::contentChildren_clear);
587}
588
589bool QQuickScrollView::childMouseEventFilter(QQuickItem *item, QEvent *event)
590{
591 Q_D(QQuickScrollView);
592 switch (event->type()) {
593 case QEvent::TouchBegin:
594 d->wasTouched = true;
595 d->setScrollBarsInteractive(false);
596 return false;
597
598 case QEvent::TouchEnd:
599 d->wasTouched = false;
600 return false;
601
602 case QEvent::MouseButtonPress:
603 // NOTE: Flickable does not handle touch events, only synthesized mouse events
604 if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized) {
605 d->wasTouched = false;
606 d->setScrollBarsInteractive(true);
607 return false;
608 }
609 return !d->wasTouched && item == d->flickable;
610
611 case QEvent::MouseMove:
612 case QEvent::MouseButtonRelease:
613 if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
614 return item == d->flickable;
615 break;
616
617 case QEvent::HoverEnter:
618 case QEvent::HoverMove:
619 if (d->wasTouched && (item == d->verticalScrollBar() || item == d->horizontalScrollBar()))
620 d->setScrollBarsInteractive(true);
621 break;
622
623 default:
624 break;
625 }
626
627 return false;
628}
629
630bool QQuickScrollView::eventFilter(QObject *object, QEvent *event)
631{
632 Q_D(QQuickScrollView);
633 if (event->type() == QEvent::Wheel) {
634 d->setScrollBarsInteractive(true);
635 if (!d->wheelEnabled) {
636 event->ignore();
637 return true;
638 }
639 }
640 return QQuickPane::eventFilter(object, event);
641}
642
643void QQuickScrollView::keyPressEvent(QKeyEvent *event)
644{
645 Q_D(QQuickScrollView);
646 QQuickPane::keyPressEvent(event);
647 switch (event->key()) {
648 case Qt::Key_Up:
649 if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
650 vbar->decrease();
651 event->accept();
652 }
653 break;
654 case Qt::Key_Down:
655 if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
656 vbar->increase();
657 event->accept();
658 }
659 break;
660 case Qt::Key_Left:
661 if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
662 hbar->decrease();
663 event->accept();
664 }
665 break;
666 case Qt::Key_Right:
667 if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
668 hbar->increase();
669 event->accept();
670 }
671 break;
672 default:
673 event->ignore();
674 break;
675 }
676}
677
678void QQuickScrollView::componentComplete()
679{
680 Q_D(QQuickScrollView);
681 QQuickPane::componentComplete();
682 if (!d->contentItem)
683 d->ensureFlickable(QQuickScrollViewPrivate::ContentItemFlag::Set);
684}
685
686void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
687{
688 Q_D(QQuickScrollView);
689 if (newItem != d->flickable) {
690 // The new flickable was not created by us. In that case, we always
691 // assume/require that it has an explicit content size assigned.
692 d->flickableHasExplicitContentWidth = true;
693 d->flickableHasExplicitContentHeight = true;
694 auto newItemAsFlickable = qobject_cast<QQuickFlickable *>(newItem);
695 if (newItem && !newItemAsFlickable)
696 qmlWarning(this) << "ScrollView only supports Flickable types as its contentItem";
697 // This is called by QQuickControlPrivate::setContentItem_helper, so no need to
698 // try to set it as the contentItem.
699 d->setFlickable(newItemAsFlickable, QQuickScrollViewPrivate::ContentItemFlag::DoNotSet);
700 // We do, however, need to set us as its parent item, as setContentItem_helper will only
701 // do so if the item doesn't already have a parent. If newItem wasn't declared as our
702 // child and was instead imperatively assigned, it may already have a parent item,
703 // which we'll need to override.
704 if (newItem) {
705 newItem->setParentItem(this);
706
707 // Make sure that the scroll bars are stacked in front of the flickable,
708 // otherwise events won't get through to them.
709 QQuickScrollBar *verticalBar = d->verticalScrollBar();
710 if (verticalBar)
711 verticalBar->stackAfter(newItem);
712 QQuickScrollBar *horizontalBar = d->horizontalScrollBar();
713 if (horizontalBar)
714 horizontalBar->stackAfter(newItem);
715 }
716 }
717 QQuickPane::contentItemChange(newItem, oldItem);
718}
719
720void QQuickScrollView::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
721{
722 Q_D(QQuickScrollView);
723 QQuickPane::contentSizeChange(newSize, oldSize);
724 if (d->flickable) {
725 // Only set the content size on the flickable if the flickable doesn't
726 // have an explicit assignment from before. Otherwise we can end up overwriting
727 // assignments done to those properties by the application. The
728 // exception is if the application has assigned a content size
729 // directly to the scrollview, which will then win even if the
730 // application has assigned something else to the flickable.
731 if (d->hasContentWidth || !d->flickableHasExplicitContentWidth) {
732 d->flickable->setContentWidth(newSize.width());
733 d->updateScrollBarWidth();
734 }
735 if (d->hasContentHeight || !d->flickableHasExplicitContentHeight) {
736 d->flickable->setContentHeight(newSize.height());
737 d->updateScrollBarHeight();
738 }
739 }
740}
741
742#if QT_CONFIG(accessibility)
743QAccessible::Role QQuickScrollView::accessibleRole() const
744{
745 return QAccessible::Pane;
746}
747#endif
748
749QT_END_NAMESPACE
750
751#include "moc_qquickscrollview_p.cpp"
void setInteractive(bool interactive)
static void contentData_append(QQmlListProperty< QObject > *prop, QObject *obj)
QList< QQuickItem * > contentChildItems() const override
static qsizetype contentData_count(QQmlListProperty< QObject > *prop)
static void contentChildren_clear(QQmlListProperty< QQuickItem > *prop)
static QQuickItem * contentChildren_at(QQmlListProperty< QQuickItem > *prop, qsizetype index)
QQuickFlickable * ensureFlickable(ContentItemFlag contentItemFlag)
void setScrollBarsInteractive(bool interactive)
static qsizetype contentChildren_count(QQmlListProperty< QQuickItem > *prop)
static void contentChildren_append(QQmlListProperty< QQuickItem > *prop, QQuickItem *obj)
qreal getContentHeight() const override
static QObject * contentData_at(QQmlListProperty< QObject > *prop, qsizetype index)
void disconnectScrollBarSignals(QQuickScrollBarAttachedPrivate *scrollBar)
void itemImplicitWidthChanged(QQuickItem *item) override
QQuickScrollBar * verticalScrollBar() const
qreal getContentWidth() const override
QQuickItem * getContentItem() override
QQuickItem * getFirstChild() const override
QQuickScrollBar * horizontalScrollBar() const
static void contentData_clear(QQmlListProperty< QObject > *prop)
bool setFlickable(QQuickFlickable *flickable, ContentItemFlag contentItemFlag)
QQmlListProperty< QQuickItem > contentChildren() override
\qmlproperty list<Item> QtQuick.Controls::ScrollView::contentChildren