Qt 6.x
The Qt SDK
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
5#include "qquickpane_p_p.h"
7
8#include <QtQuick/private/qquickflickable_p.h>
9
11
16
94{
95public:
96 Q_DECLARE_PUBLIC(QQuickScrollView)
97
100 QList<QQuickItem *> contentChildItems() const override;
101
102 QQuickItem *getContentItem() override;
103
104 enum class ContentItemFlag {
105 DoNotSet,
106 Set
107 };
108
111
114
115 qreal getContentWidth() const override;
116 qreal getContentHeight() const override;
117
120
121 void setScrollBarsInteractive(bool interactive);
122
127
132
134
137
139 bool wasTouched = false;
146};
147
149{
150 if (!flickable)
151 return QList<QQuickItem *>();
152
153 return flickable->contentItem()->childItems();
154}
155
157{
158 if (!contentItem)
160 // This function is called by QQuickControl::contentItem() to lazily create
161 // a contentItem, so we don't need to try to set it again.
163}
164
166{
167 Q_Q(QQuickScrollView);
168 if (!flickable) {
171 // Pass ourselves as the Flickable's parent item.
172 auto flickable = new QQuickFlickable(q);
173 // We almost always want to clip the flickable so that flickable
174 // contents doesn't show up outside the scrollview. The only time
175 // this is not really needed, is when the scrollview covers the whole
176 // window and the scrollbars are transient. But for that corner case, if this
177 // optimization is needed, the user can simply create his own flickable
178 // child inside the scrollview, and control clipping on it explicit.
179 flickable->setClip(true);
181 setFlickable(flickable, contentItemFlag);
182 }
183 return flickable;
184}
185
187{
188 Q_Q(QQuickScrollView);
189 qreal oldEffectiveScrollBarWidth = effectiveScrollBarWidth;
190 if (auto *vBar = verticalScrollBar()) {
191 if (vBar->policy() == QQuickScrollBar::AlwaysOff || !vBar->isVisible())
193 else
194 effectiveScrollBarWidth = vBar->width();
195 }
196 if (effectiveScrollBarWidth != oldEffectiveScrollBarWidth) {
197 if (!isUpdatingScrollBar) {
199 emit q->effectiveScrollBarWidthChanged();
200 }
201 }
202}
203
205{
206 Q_Q(QQuickScrollView);
207 qreal oldEffectiveScrollBarHeight = effectiveScrollBarHeight;
208 if (auto *hBar = horizontalScrollBar()) {
209 if (hBar->policy() == QQuickScrollBar::AlwaysOff || !hBar->isVisible())
211 else
212 effectiveScrollBarHeight = hBar->height();
213 }
214 if (effectiveScrollBarHeight != oldEffectiveScrollBarHeight) {
215 if (!isUpdatingScrollBar) {
217 emit q->effectiveScrollBarHeightChanged();
218 }
219
220 }
221}
222
224{
225 if (!scrollBar)
226 return;
227
228 if (scrollBar->vertical) {
229 QObjectPrivate::disconnect(scrollBar->vertical, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarWidth);
231 }
232 if (scrollBar->horizontal) {
233 QObjectPrivate::disconnect(scrollBar->horizontal, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarHeight);
235 }
236}
237
239{
240 Q_Q(QQuickScrollView);
241 if (item == flickable)
242 return false;
243
244 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
245
246 if (flickable) {
248
249 if (attached) {
251 scrollBar->setFlickable(nullptr);
253 }
254
258 }
259
260 flickable = item;
261 if (contentItemFlag == ContentItemFlag::Set)
262 q->setContentItem(flickable);
263
264 if (flickable) {
266 if (hasContentWidth)
268 else
272 else
274
275 if (attached) {
277 scrollBar->setFlickable(flickable);
278 if (scrollBar->vertical) {
279 QObjectPrivate::connect(scrollBar->vertical, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarWidth);
281 }
282 if (scrollBar->horizontal) {
283 QObjectPrivate::connect(scrollBar->horizontal, &QQuickScrollBar::policyChanged, this, &QQuickScrollViewPrivate::updateScrollBarHeight);
285 }
286 }
287
291 }
292
293 return true;
294}
295
297{
298 Q_Q(QQuickScrollView);
300 return;
301
302 const qreal cw = flickable->contentWidth();
304 return;
305
308 emit q->implicitContentWidthChanged();
309}
310
312{
313 Q_Q(QQuickScrollView);
315 return;
316
317 const qreal ch = flickable->contentHeight();
319 return;
320
323 emit q->implicitContentHeightChanged();
324}
325
327{
329 return flickable->contentWidth();
330
331 // The scrollview wraps a flickable created by us, and nobody searched for it and
332 // modified its contentWidth. In that case, since the application does not control
333 // this flickable, we fall back to calculate the content width based on the child
334 // items inside it.
336}
337
339{
341 return flickable->contentHeight();
342
343 // The scrollview wraps a flickable created by us, and nobody searched for it and
344 // modified its contentHeight. In that case, since the application does not control
345 // this flickable, we fall back to calculate the content height based on the child
346 // items inside it.
348}
349
351{
352 Q_Q(const QQuickScrollView);
353 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
354 if (!attached)
355 return nullptr;
356 return attached->vertical();
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->horizontal();
366}
367
369{
371 if (hbar) {
373 if (!p->explicitInteractive)
374 p->setInteractive(interactive);
375 }
376
378 if (vbar) {
380 if (!p->explicitInteractive)
381 p->setInteractive(interactive);
382 }
383}
384
386{
387 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
388 // If we don't yet have a flickable assigned, and this object is a Flickable,
389 // make it our contentItem.
390 if (!p->flickable && p->setFlickable(qobject_cast<QQuickFlickable *>(obj), ContentItemFlag::Set))
391 return;
392
393 QQuickFlickable *flickable = p->ensureFlickable(ContentItemFlag::Set);
395 // Add the object that was declared as a child of us as a child object of the Flickable.
397 data.append(&data, obj);
398}
399
401{
402 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
403 if (!p->flickable)
404 return 0;
405
406 QQmlListProperty<QObject> data = p->flickable->flickableData();
407 return data.count(&data);
408}
409
411{
412 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
413 if (!p->flickable)
414 return nullptr;
415
416 QQmlListProperty<QObject> data = p->flickable->flickableData();
417 return data.at(&data, index);
418}
419
421{
422 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
423 if (!p->flickable)
424 return;
425
426 QQmlListProperty<QObject> data = p->flickable->flickableData();
427 return data.clear(&data);
428}
429
431{
432 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
433 if (!p->flickable)
434 p->setFlickable(qobject_cast<QQuickFlickable *>(item), ContentItemFlag::Set);
435
436 QQuickFlickable *flickable = p->ensureFlickable(ContentItemFlag::Set);
438 // Add the item that was declared as a child of us as a child item of the Flickable's contentItem.
440 children.append(&children, item);
441}
442
444{
445 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
446 if (!p->flickable)
447 return 0;
448
449 QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
450 return children.count(&children);
451}
452
454{
455 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
456 if (!p->flickable)
457 return nullptr;
458
459 QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
460 return children.at(&children, index);
461}
462
464{
465 QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
466 if (!p->flickable)
467 return;
468
469 QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
470 children.clear(&children);
471}
472
474{
475 // a special case for width<->height dependent content (wrapping text) in ScrollView
477 return;
478
480}
481
484{
485 Q_D(QQuickScrollView);
486 d->contentWidth = -1;
487 d->contentHeight = -1;
488
490 setWheelEnabled(true);
491}
492
494{
495 Q_D(QQuickScrollView);
496 QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(this, false));
497 if (attached) {
499 d->disconnectScrollBarSignals(scrollBar);
500 }
501}
502
514{
515 Q_D(QQuickScrollView);
516 return d->effectiveScrollBarWidth;
517}
518
530{
531 Q_D(QQuickScrollView);
532 return d->effectiveScrollBarHeight;
533}
534
548{
549 Q_Q(QQuickScrollView);
550 return QQmlListProperty<QObject>(q, this,
555}
556
569{
570 Q_Q(QQuickScrollView);
571 return QQmlListProperty<QQuickItem>(q, this,
576}
577
579{
580 Q_D(QQuickScrollView);
581 switch (event->type()) {
583 d->wasTouched = true;
584 d->setScrollBarsInteractive(false);
585 return false;
586
587 case QEvent::TouchEnd:
588 d->wasTouched = false;
589 return false;
590
592 // NOTE: Flickable does not handle touch events, only synthesized mouse events
593 if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized) {
594 d->wasTouched = false;
595 d->setScrollBarsInteractive(true);
596 return false;
597 }
598 return !d->wasTouched && item == d->flickable;
599
602 if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
603 return item == d->flickable;
604 break;
605
608 if (d->wasTouched && (item == d->verticalScrollBar() || item == d->horizontalScrollBar()))
609 d->setScrollBarsInteractive(true);
610 break;
611
612 default:
613 break;
614 }
615
616 return false;
617}
618
620{
621 Q_D(QQuickScrollView);
622 if (event->type() == QEvent::Wheel) {
623 d->setScrollBarsInteractive(true);
624 if (!d->wheelEnabled) {
625 event->ignore();
626 return true;
627 }
628 }
629 return QQuickPane::eventFilter(object, event);
630}
631
633{
634 Q_D(QQuickScrollView);
636 switch (event->key()) {
637 case Qt::Key_Up:
638 if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
639 vbar->decrease();
640 event->accept();
641 }
642 break;
643 case Qt::Key_Down:
644 if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
645 vbar->increase();
646 event->accept();
647 }
648 break;
649 case Qt::Key_Left:
650 if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
651 hbar->decrease();
652 event->accept();
653 }
654 break;
655 case Qt::Key_Right:
656 if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
657 hbar->increase();
658 event->accept();
659 }
660 break;
661 default:
662 event->ignore();
663 break;
664 }
665}
666
668{
669 Q_D(QQuickScrollView);
671 if (!d->contentItem)
673}
674
676{
677 Q_D(QQuickScrollView);
678 if (newItem != d->flickable) {
679 // The new flickable was not created by us. In that case, we always
680 // assume/require that it has an explicit content size assigned.
681 d->flickableHasExplicitContentWidth = true;
682 d->flickableHasExplicitContentHeight = true;
683 auto newItemAsFlickable = qobject_cast<QQuickFlickable *>(newItem);
684 if (newItem && !newItemAsFlickable)
685 qmlWarning(this) << "ScrollView only supports Flickable types as its contentItem";
686 // This is called by QQuickControlPrivate::setContentItem_helper, so no need to
687 // try to set it as the contentItem.
688 d->setFlickable(newItemAsFlickable, QQuickScrollViewPrivate::ContentItemFlag::DoNotSet);
689 // We do, however, need to set us as its parent item, as setContentItem_helper will only
690 // do so if the item doesn't already have a parent. If newItem wasn't declared as our
691 // child and was instead imperatively assigned, it may already have a parent item,
692 // which we'll need to override.
693 if (newItem) {
694 newItem->setParentItem(this);
695
696 // Make sure that the scroll bars are stacked in front of the flickable,
697 // otherwise events won't get through to them.
698 QQuickScrollBar *verticalBar = d->verticalScrollBar();
699 if (verticalBar)
700 verticalBar->stackAfter(newItem);
701 QQuickScrollBar *horizontalBar = d->horizontalScrollBar();
702 if (horizontalBar)
703 horizontalBar->stackAfter(newItem);
704 }
705 }
706 QQuickPane::contentItemChange(newItem, oldItem);
707}
708
709void QQuickScrollView::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
710{
711 Q_D(QQuickScrollView);
712 QQuickPane::contentSizeChange(newSize, oldSize);
713 if (d->flickable) {
714 // Only set the content size on the flickable if the flickable doesn't
715 // have an explicit assignment from before. Otherwise we can end up overwriting
716 // assignments done to those properties by the application. The
717 // exception is if the application has assigned a content size
718 // directly to the scrollview, which will then win even if the
719 // application has assigned something else to the flickable.
720 if (d->hasContentWidth || !d->flickableHasExplicitContentWidth) {
721 d->flickable->setContentWidth(newSize.width());
722 d->updateScrollBarWidth();
723 }
724 if (d->hasContentHeight || !d->flickableHasExplicitContentHeight) {
725 d->flickable->setContentHeight(newSize.height());
726 d->updateScrollBarHeight();
727 }
728 }
729}
730
731#if QT_CONFIG(accessibility)
732QAccessible::Role QQuickScrollView::accessibleRole() const
733{
734 return QAccessible::Pane;
735}
736#endif
737
739
740#include "moc_qquickscrollview_p.cpp"
\inmodule QtCore
Definition qcoreevent.h:45
@ MouseMove
Definition qcoreevent.h:63
@ MouseButtonPress
Definition qcoreevent.h:60
@ TouchBegin
Definition qcoreevent.h:241
@ HoverEnter
Definition qcoreevent.h:175
@ HoverMove
Definition qcoreevent.h:177
@ MouseButtonRelease
Definition qcoreevent.h:61
The QKeyEvent class describes a key event.
Definition qevent.h:423
Definition qlist.h:74
\inmodule QtGui
Definition qevent.h:195
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:298
static bool disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot)
Definition qobject_p.h:327
\inmodule QtCore
Definition qobject.h:90
void installEventFilter(QObject *filterObj)
Installs an event filter filterObj on this object.
Definition qobject.cpp:2269
virtual bool eventFilter(QObject *watched, QEvent *event)
Filters events if this object has been installed as an event filter for the watched object.
Definition qobject.cpp:1518
void removeEventFilter(QObject *obj)
Removes an event filter object obj from this object.
Definition qobject.cpp:2300
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
Definition qqmllist.h:24
ClearFunction clear
Definition qqmllist.h:87
AtFunction at
Definition qqmllist.h:86
CountFunction count
Definition qqmllist.h:85
QQuickDeferredPointer< QQuickItem > contentItem
virtual void executeContentItem(bool complete=false)
void setWheelEnabled(bool enabled)
void setPixelAligned(bool align)
FINALQQmlListProperty< QObject > flickableData
void setContentWidth(qreal)
void contentWidthChanged()
void contentHeightChanged()
QQuickItem * contentItem
QQmlListProperty< QQuickItem > flickableChildren
void setContentHeight(qreal)
quint32 componentComplete
QQmlListProperty< QQuickItem > children()
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
void setFiltersChildMouseEvents(bool filter)
Sets whether pointer events intended for this item's children should be filtered through this item.
QList< QQuickItem * > childItems() const
Returns the children of this item.
virtual void keyPressEvent(QKeyEvent *event)
This event handler can be reimplemented in a subclass to receive key press events for an item.
void setParentItem(QQuickItem *parent)
void visibleChanged()
void stackAfter(const QQuickItem *)
Moves the specified sibling item to the index after this item within the list of children.
void childrenChanged()
void setClip(bool)
void contentChildrenChange()
void itemImplicitWidthChanged(QQuickItem *item) override
qreal getContentWidth() const override
qreal getContentHeight() const override
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
virtual void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
static QQuickScrollBarAttachedPrivate * get(QQuickScrollBarAttached *attached)
QQuickScrollBar * horizontal
static QQuickScrollBarPrivate * get(QQuickScrollBar *bar)
static void contentData_append(QQmlListProperty< QObject > *prop, QObject *obj)
QList< QQuickItem * > contentChildItems() const override
QQmlListProperty< QObject > contentData() override
\qmlproperty list<QtObject> QtQuick.Controls::ScrollView::contentData \qmldefault
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
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
qreal effectiveScrollBarWidth
\qmlproperty real QtQuick.Controls::ScrollView::effectiveScrollBarWidth
QQuickScrollView(QQuickItem *parent=nullptr)
qreal effectiveScrollBarHeight
\qmlproperty real QtQuick.Controls::ScrollView::effectiveScrollBarHeight
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override
bool eventFilter(QObject *object, QEvent *event) override
Filters events if this object has been installed as an event filter for the watched object.
bool childMouseEventFilter(QQuickItem *item, QEvent *event) override
Reimplement this method to filter the pointer events that are received by this item's children.
void keyPressEvent(QKeyEvent *event) override
This event handler can be reimplemented in a subclass to receive key press events for an item.
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize) override
\inmodule QtCore
Definition qsize.h:207
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:321
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:324
Combined button and popup list for selecting options.
@ MouseEventNotSynthesized
@ Key_Right
Definition qnamespace.h:674
@ Key_Left
Definition qnamespace.h:672
@ Key_Up
Definition qnamespace.h:673
@ Key_Down
Definition qnamespace.h:675
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
GLuint index
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLchar * source
struct _cl_event * event
GLhandleARB obj
[2]
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static const struct TessellationWindingOrderTab cw[]
#define emit
ptrdiff_t qsizetype
Definition qtypes.h:70
double qreal
Definition qtypes.h:92
QScrollBar * scrollBar
QGraphicsItem * item
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent