Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquicklistview.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
4#include "qquicklistview_p.h"
7
8#include <private/qqmlobjectmodel_p.h>
9#include <QtQml/qqmlexpression.h>
10#include <QtQml/qqmlengine.h>
11#include <QtQml/qqmlinfo.h>
12#include <QtGui/qevent.h>
13#include <QtCore/qcoreapplication.h>
14#include <QtCore/qmath.h>
15
16#include <private/qquicksmoothedanimation_p_p.h>
17#include <private/qqmlcomponent_p.h>
18
20
21#ifndef QML_FLICK_SNAPONETHRESHOLD
22#define QML_FLICK_SNAPONETHRESHOLD 30
23#endif
24
25Q_LOGGING_CATEGORY(lcEvents, "qt.quick.listview.events")
26
27class FxListItemSG;
28
30{
31public:
32 Q_DECLARE_PUBLIC(QQuickListView)
33 static QQuickListViewPrivate* get(QQuickListView *item) { return item->d_func(); }
34
35 Qt::Orientation layoutOrientation() const override;
36 bool isContentFlowReversed() const override;
37 bool isRightToLeft() const;
38 bool isBottomToTop() const;
39
40 qreal positionAt(int index) const override;
41 qreal endPositionAt(int index) const override;
42 qreal originPosition() const override;
43 qreal lastPosition() const override;
44
45 FxViewItem *itemBefore(int modelIndex) const;
46 QString sectionAt(int modelIndex);
47 qreal snapPosAt(qreal pos);
48 FxViewItem *snapItemAt(qreal pos);
49
50 void init() override;
51 void clear(bool onDestruction) override;
52
53 bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) override;
54 bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) override;
55 void visibleItemsChanged() override;
56
57 void removeItem(FxViewItem *item);
58
59 FxViewItem *newViewItem(int index, QQuickItem *item) override;
60 void initializeViewItem(FxViewItem *item) override;
61 bool releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag) override;
62 void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) override;
63 void repositionPackageItemAt(QQuickItem *item, int index) override;
64 void resetFirstItemPosition(qreal pos = 0.0) override;
65 void adjustFirstItem(qreal forwards, qreal backwards, int) override;
66 void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult) override;
67
68 void createHighlight(bool onDestruction = false) override;
69 void updateHighlight() override;
70 void resetHighlightPosition() override;
71 bool movingFromHighlight() override;
72
73 void setPosition(qreal pos) override;
74 void layoutVisibleItems(int fromModelIndex = 0) override;
75
76 bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView) override;
77#if QT_CONFIG(quick_viewtransitions)
78 void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) override;
79#endif
80
81 void updateSectionCriteria() override;
82 void updateSections() override;
83 QQuickItem *getSectionItem(const QString &section);
84 void releaseSectionItem(QQuickItem *item);
85 void releaseSectionItems();
86 void updateInlineSection(FxListItemSG *);
87 void updateCurrentSection();
88 void updateStickySections();
89
90 qreal headerSize() const override;
91 qreal footerSize() const override;
92 bool showHeaderForIndex(int index) const override;
93 bool showFooterForIndex(int index) const override;
94 void updateHeader() override;
95 void updateFooter() override;
96 bool hasStickyHeader() const override;
97 bool hasStickyFooter() const override;
98
99 void initializeComponentItem(QQuickItem *item) const override;
100
101 void changedVisibleIndex(int newIndex) override;
102 void initializeCurrentItem() override;
103
104 void updateAverage();
105
106 void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) override;
107 void fixupPosition() override;
108 void fixup(AxisData &data, qreal minExtent, qreal maxExtent) override;
109 bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
110 QQuickTimeLineCallback::Callback fixupCallback, QEvent::Type eventType, qreal velocity) override;
111
112 QQuickItemViewAttached *getAttachedObject(const QObject *object) const override;
113
114 void fixupHeader();
115 void fixupHeaderCompleted();
116
117 bool wantsPointerEvent(const QPointerEvent *event) override;
118
124
127
128 std::unique_ptr<QSmoothedAnimation> highlightPosAnimator;
129 std::unique_ptr<QSmoothedAnimation> highlightWidthAnimator;
130 std::unique_ptr<QSmoothedAnimation> highlightHeightAnimator;
134
137 static const int sectionCacheSize = 5;
138 QQuickItem *sectionCache[sectionCacheSize];
145
147
152
153 bool correctFlick : 1;
156
158 : orient(QQuickListView::Vertical)
159 , visiblePos(0)
160 , averageSize(100.0), spacing(0.0)
161 , snapMode(QQuickListView::NoSnap)
162 , headerPositioning(QQuickListView::InlineHeader)
163 , footerPositioning(QQuickListView::InlineFooter)
164 , highlightPosAnimator(nullptr), highlightWidthAnimator(nullptr), highlightHeightAnimator(nullptr)
165 , highlightMoveVelocity(400), highlightResizeVelocity(400), highlightResizeDuration(-1)
166 , sectionCriteria(nullptr), currentSectionItem(nullptr), nextSectionItem(nullptr)
167 , overshootDist(0.0), desiredViewportPosition(0.0), fixupHeaderPosition(0.0)
168 , headerNeedsSeparateFixup(false), desiredHeaderVisible(false)
169 , correctFlick(false), inFlickCorrection(false), wantedMousePress(false)
170 {
171 highlightMoveDuration = -1; //override default value set in base class
172 }
173
174 friend class QQuickViewSection;
175
176 static void setSectionHelper(QQmlContext *context, QQuickItem *sectionItem, const QString &section);
177};
178
179//----------------------------------------------------------------------------
180
182 : QObject(parent), m_criteria(FullString), m_delegate(nullptr), m_labelPositioning(InlineLabels)
184{
185}
186
188{
189 if (property != m_property) {
190 m_property = property;
192 // notify view that the contents of the sections must be recalculated
193 m_view->updateSectionCriteria();
194 }
195}
196
198{
199 if (criteria != m_criteria) {
200 m_criteria = criteria;
202 // notify view that the contents of the sections must be recalculated
203 m_view->updateSectionCriteria();
204 }
205}
206
208{
209 if (delegate != m_delegate) {
210 if (m_delegate)
211 m_view->releaseSectionItems();
212 m_delegate = delegate;
214 m_view->forceLayoutPolish();
215 }
216}
217
219{
220 if (m_criteria == FirstCharacter)
221 return value.isEmpty() ? QString() : value.at(0);
222 else
223 return value;
224}
225
227{
228 if (m_labelPositioning != l) {
229 m_labelPositioning = l;
231 m_view->forceLayoutPolish();
232 }
233}
234
235//----------------------------------------------------------------------------
236
238{
239public:
241 {
242 }
243
244 inline QQuickItem *section() const {
245 return item && attached ? static_cast<QQuickListViewAttached*>(attached)->m_sectionItem : nullptr;
246 }
248 static_cast<QQuickListViewAttached*>(attached)->m_sectionItem = s;
249 }
250
251 qreal position() const override {
252 if (section()) {
255 else
256 return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -section()->width()-section()->x() : section()->x());
257 } else {
258 return itemPosition();
259 }
260 }
264 else
266 }
267 qreal size() const override {
268 if (section())
270 else
272 }
273 qreal itemSize() const {
275 }
276 qreal sectionSize() const override {
277 if (section())
279 return 0.0;
280 }
281 qreal endPosition() const override {
284 ? -itemY()
285 : itemY() + itemHeight());
286 } else {
288 ? -itemX()
289 : itemX() + itemWidth());
290 }
291 }
292 void setPosition(qreal pos, bool immediate = false) {
293 // position the section immediately even if there is a transition
294 if (section()) {
297 section()->setY(-section()->height()-pos);
298 else
299 section()->setY(pos);
300 } else {
302 section()->setX(-section()->width()-pos);
303 else
304 section()->setX(pos);
305 }
306 }
307 moveTo(pointForPosition(pos), immediate);
308 }
312 else
314 }
315 bool contains(qreal x, qreal y) const override {
316 return (x >= itemX() && x < itemX() + itemWidth() &&
317 y >= itemY() && y < itemY() + itemHeight());
318 }
319
321
322private:
323 QPointF pointForPosition(qreal pos) const {
326 if (section())
327 pos += section()->height();
328 return QPointF(itemX(), -itemHeight() - pos);
329 } else {
330 if (section())
331 pos += section()->height();
332 return QPointF(itemX(), pos);
333 }
334 } else {
336 if (section())
337 pos += section()->width();
338 return QPointF(-itemWidth() - pos, itemY());
339 } else {
340 if (section())
341 pos += section()->width();
342 return QPointF(pos, itemY());
343 }
344 }
345 }
346};
347
371public:
374 , backwards(iEnd < iBegin)
375 {
377 [&] (const QQmlChangeSet &changeSet, bool /*reset*/)
378 {
379 for (const QQmlChangeSet::Change &rem : changeSet.removes()) {
380 idxEnd -= rem.count;
381 if (rem.start() <= index) {
382 index -= rem.count;
383 if (index < rem.start() + rem.count)
384 removedAtIndex = true; // model index was removed
385 }
386 }
387 for (const QQmlChangeSet::Change &ins : changeSet.inserts()) {
388 idxEnd += ins.count;
389 if (ins.start() <= index)
390 index += ins.count;
391 }
392 }
393 );
394 index = iBegin;
395 idxEnd = iEnd;
396 }
397
398 bool hasNext() const {
399 return backwards ? index > idxEnd : index < idxEnd;
400 }
401
402 void next() { index += (backwards ? -1 : +1); }
403
405 {
406 disconnect();
407 }
408
410 {
411 if (conn) {
413 conn = QMetaObject::Connection(); // set to nullptr
414 }
415 }
416 int index = 0;
418 unsigned removedAtIndex : 1;
419 unsigned backwards : 1;
420private:
422};
423
424
425//----------------------------------------------------------------------------
426
428{
429 return isRightToLeft() || isBottomToTop();
430}
431
433{
434 return static_cast<Qt::Orientation>(orient);
435}
436
438{
439 Q_Q(const QQuickListView);
440 return orient == QQuickListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
441}
442
444{
446}
447
448// Returns the item before modelIndex, if created.
449// May return an item marked for removal.
451{
452 if (modelIndex < visibleIndex)
453 return nullptr;
454 int idx = 1;
455 int lastIndex = -1;
456 while (idx < visibleItems.size()) {
458 if (item->index != -1)
459 lastIndex = item->index;
460 if (item->index == modelIndex)
461 return visibleItems.at(idx-1);
462 ++idx;
463 }
464 if (lastIndex == modelIndex-1)
465 return visibleItems.constLast();
466 return nullptr;
467}
468
470{
471 Q_Q(QQuickListView);
473 if (isBottomToTop())
474 q->QQuickFlickable::setContentY(-pos-size());
475 else
476 q->QQuickFlickable::setContentY(pos);
477 } else {
478 if (isRightToLeft())
479 q->QQuickFlickable::setContentX(-pos-size());
480 else
481 q->QQuickFlickable::setContentX(pos);
482 }
483}
484
486{
487 qreal pos = 0;
488 if (!visibleItems.isEmpty()) {
490 if (visibleIndex > 0)
492 }
493 return pos;
494}
495
497{
498 qreal pos = 0;
499 if (!visibleItems.isEmpty()) {
500 int invisibleCount = INT_MIN;
501 int delayRemovedCount = 0;
502 for (int i = visibleItems.size()-1; i >= 0; --i) {
504 if (item->index != -1) {
505 // Find the invisible count after the last visible item with known index
506 invisibleCount = model->count() - (item->index + 1 + delayRemovedCount);
507 break;
508 } else if (item->attached->delayRemove()) {
509 ++delayRemovedCount;
510 }
511 }
512 if (invisibleCount == INT_MIN) {
513 // All visible items are in delayRemove state
514 invisibleCount = model->count();
515 }
516 pos = (*(visibleItems.constEnd() - 1))->endPosition();
517 if (invisibleCount > 0)
518 pos += invisibleCount * (averageSize + spacing);
519 } else if (model && model->count()) {
520 pos = (model->count() * averageSize + (model->count()-1) * spacing);
521 }
522 return pos;
523}
524
526{
527 if (FxViewItem *item = visibleItem(modelIndex)) {
528 return item->position();
529 }
530 if (!visibleItems.isEmpty()) {
531 if (modelIndex < visibleIndex) {
532 int count = visibleIndex - modelIndex;
533 qreal cs = 0;
534 if (modelIndex == currentIndex && currentItem) {
535 cs = currentItem->size() + spacing;
536 --count;
537 }
538 return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
539 } else {
540 int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
541 return (*(visibleItems.constEnd() - 1))->endPosition() + spacing + count * (averageSize + spacing);
542 }
543 }
544 return 0;
545}
546
548{
549 if (FxViewItem *item = visibleItem(modelIndex))
550 return item->endPosition();
551 if (!visibleItems.isEmpty()) {
552 if (modelIndex < visibleIndex) {
553 int count = visibleIndex - modelIndex;
554 return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing;
555 } else {
556 int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
557 return (*(visibleItems.constEnd() - 1))->endPosition() + count * (averageSize + spacing);
558 }
559 }
560 return 0;
561}
562
564{
565 if (FxViewItem *item = visibleItem(modelIndex))
566 return item->attached->section();
567
568 QString section;
569 if (sectionCriteria && modelIndex >= 0 && modelIndex < itemCount) {
570 QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
571 section = sectionCriteria->sectionString(propValue);
572 }
573
574 return section;
575}
576
578{
579 if (FxListItemSG *snapItem = static_cast<FxListItemSG*>(snapItemAt(pos)))
580 return snapItem->itemPosition();
581 if (visibleItems.size()) {
582 qreal firstPos = (*visibleItems.constBegin())->position();
583 qreal endPos = (*(visibleItems.constEnd() - 1))->position();
584 if (pos < firstPos) {
585 return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
586 } else if (pos > endPos)
587 return endPos + qRound((pos - endPos) / averageSize) * averageSize;
588 }
590}
591
593{
595 FxViewItem *snapItem = nullptr;
596 FxViewItem *prevItem = nullptr;
597 qreal prevItemSize = 0;
598 for (FxViewItem *item : std::as_const(visibleItems)) {
599 if (item->index == -1)
600 continue;
601
602 const FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
603 qreal itemTop = listItem->position();
604 qreal itemSize = listItem->size();
605 if (highlight && itemTop >= pos && listItem->endPosition() <= pos + highlight->size())
606 return item;
607
608 if (listItem->section() && velocity > 0) {
609 if (itemTop + listItem->sectionSize() / 2 >= pos && itemTop - prevItemSize / 2 < pos)
610 snapItem = prevItem;
611 itemTop = listItem->itemPosition();
612 itemSize = listItem->itemSize();
613 }
614
615 // Middle of item and spacing (i.e. the middle of the distance between this item and the next
616 qreal halfwayToNextItem = itemTop + (itemSize+spacing) / 2;
617 qreal halfwayToPrevItem = itemTop - (prevItemSize+spacing) / 2;
618 if (halfwayToNextItem >= pos && halfwayToPrevItem < pos)
619 snapItem = item;
620
621 prevItemSize = listItem->itemSize();
622 prevItem = item;
623 }
624 return snapItem;
625}
626
628{
629 visiblePos = positionAt(newIndex);
630 visibleIndex = newIndex;
631}
632
634{
636 ::memset(sectionCache, 0, sizeof(QQuickItem*) * sectionCacheSize);
637}
638
639void QQuickListViewPrivate::clear(bool onDestruction)
640{
641 for (int i = 0; i < sectionCacheSize; ++i) {
642 delete sectionCache[i];
643 sectionCache[i] = nullptr;
644 }
645 visiblePos = 0;
647 currentSectionItem = nullptr;
649 nextSectionItem = nullptr;
651 QQuickItemViewPrivate::clear(onDestruction);
652}
653
655{
656 Q_Q(QQuickListView);
657
658 FxListItemSG *listItem = new FxListItemSG(item, q, false);
659 listItem->index = modelIndex;
660
661 // initialise attached properties
662 if (sectionCriteria) {
663 QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
664 QString section = sectionCriteria->sectionString(propValue);
665 QString prevSection;
667 if (modelIndex > 0) {
668 if (FxViewItem *item = itemBefore(modelIndex))
669 prevSection = item->attached->section();
670 else
671 prevSection = sectionAt(modelIndex-1);
672 }
673 if (modelIndex < model->count()-1) {
674 nextSection = sectionAt(modelIndex+1);
675 }
676 listItem->attached->setSections(prevSection, section, nextSection);
677 }
678
679 return listItem;
680}
681
683{
685
686 // need to track current items that are animating
687 item->trackGeometry(true);
688
690 if (QString::compare(item->attached->m_prevSection, item->attached->m_section, Qt::CaseInsensitive))
691 updateInlineSection(static_cast<FxListItemSG*>(item));
692 }
693}
694
696{
697 if (!item || !model)
699
701 QQuickListViewAttached *att = static_cast<QQuickListViewAttached*>(item->attached);
702
704 if (released && it && att && att->m_sectionItem) {
706
707 // We hold no more references to this item
708 int i = 0;
709 do {
710 if (!sectionCache[i]) {
712 sectionCache[i]->setVisible(false);
713 att->m_sectionItem = nullptr;
714 break;
715 }
716 ++i;
717 } while (i < sectionCacheSize);
718 delete att->m_sectionItem;
719 att->m_sectionItem = nullptr;
720 }
721
722 return released;
723}
724
725bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
726{
727 qreal itemEnd = visiblePos;
728 if (visibleItems.size()) {
730 itemEnd = (*(visibleItems.constEnd() - 1))->endPosition() + spacing;
731 }
732
733 int modelIndex = findLastVisibleIndex();
734 bool haveValidItems = modelIndex >= 0;
735 modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
736
737 if (haveValidItems && (bufferFrom > itemEnd+averageSize+spacing
738 || bufferTo < visiblePos - averageSize - spacing)) {
739 // We've jumped more than a page. Estimate which items are now
740 // visible and fill from there.
741 int count = (fillFrom - itemEnd) / (averageSize + spacing);
742 int newModelIdx = qBound(0, modelIndex + count, model->count());
743 count = newModelIdx - modelIndex;
744 if (count) {
746 modelIndex = newModelIdx;
747 visibleIndex = modelIndex;
748 visiblePos = itemEnd + count * (averageSize + spacing);
749 itemEnd = visiblePos;
750 }
751 }
752
754
755 bool changed = false;
756 FxListItemSG *item = nullptr;
757 qreal pos = itemEnd;
758 while (modelIndex < model->count() && pos <= fillTo) {
759 if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, incubationMode))))
760 break;
761 qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
762#if QT_CONFIG(quick_viewtransitions)
763 if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
764#endif
765 item->setPosition(pos, true);
766 if (item->item)
767 QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
768 pos += item->size() + spacing;
770 ++modelIndex;
771 changed = true;
772 }
773
774 if (doBuffer && requestedIndex != -1) // already waiting for an item
775 return changed;
776
777 while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
778 if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, incubationMode))))
779 break;
780 qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
781 --visibleIndex;
782 visiblePos -= item->size() + spacing;
783#if QT_CONFIG(quick_viewtransitions)
784 if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
785#endif
786 item->setPosition(visiblePos, true);
787 if (item->item)
788 QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
790 changed = true;
791 }
792
793 return changed;
794}
795
797{
798#if QT_CONFIG(quick_viewtransitions)
799 if (item->transitionScheduledOrRunning()) {
800 qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item);
801 item->releaseAfterTransition = true;
802 releasePendingTransition.append(item);
803 } else
804#endif
805 {
806 qCDebug(lcItemViewDelegateLifecycle) << "\treleasing stationary item" << item->index << (QObject *)(item->item);
808 }
809}
810
812{
813 FxViewItem *item = nullptr;
814 bool changed = false;
815
816 // Remove items from the start of the view.
817 // Zero-sized items shouldn't be removed unless a non-zero-sized item is also being
818 // removed, otherwise a zero-sized item is infinitely added and removed over and
819 // over by refill().
820 int index = 0;
821 while (visibleItems.size() > 1 && index < visibleItems.size()
822 && (item = visibleItems.at(index)) && item->endPosition() < bufferFrom) {
823 if (item->attached->delayRemove())
824 break;
825
826 if (item->size() > 0) {
827 qCDebug(lcItemViewDelegateLifecycle) << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
828 // remove this item and all zero-sized items before it
829 while (item) {
830 if (item->index != -1)
831 visibleIndex++;
834 if (index == 0)
835 break;
837 }
838 changed = true;
839 } else {
840 index++;
841 }
842 }
843
844 while (visibleItems.size() > 1 && (item = visibleItems.constLast()) && item->position() > bufferTo) {
845 if (item->attached->delayRemove())
846 break;
847 qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.size()-1 << item->position() << (QObject *)(item->item);
850 changed = true;
851 }
852
853 return changed;
854}
855
857{
858 if (visibleItems.size())
864 }
865 if (sectionCriteria)
868}
869
871{
872 if (!visibleItems.isEmpty()) {
875
876 FxListItemSG *firstItem = static_cast<FxListItemSG *>(visibleItems.constFirst());
877 bool fixedCurrent = currentItem && firstItem->item == currentItem->item;
878
879 /* Set position of first item in list view when populate transition is configured, as it doesn't set
880 while adding visible item (addVisibleItem()) to the view */
881 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true))
882 resetFirstItemPosition(isContentFlowReversed() ? -firstItem->position()-firstItem->size() : firstItem->position());
883
884 firstVisibleItemPosition = firstItem->position();
885 qreal sum = firstItem->size();
886 qreal pos = firstItem->position() + firstItem->size() + spacing;
887 firstItem->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
888
889 // setPosition will affect the position of the item, and its section, if it has one.
890 // This will prevent them from potentially overlapping.
891 if (firstItem->section())
892 firstItem->setPosition(firstItem->position());
893
894 for (int i=1; i < visibleItems.size(); ++i) {
895 FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
896 if (item->index >= fromModelIndex) {
897 item->setPosition(pos);
898 item->setVisible(item->endPosition() >= from && item->position() <= to);
899 }
900 pos += item->size() + spacing;
901 sum += item->size();
902 fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
903 }
905
906 // move current item if it is not a visible item.
907 if (currentIndex >= 0 && currentItem && !fixedCurrent)
909
912 }
913}
914
916{
917 static_cast<FxListItemSG *>(item)->setPosition(positionAt(index) + sizeBuffer);
918}
919
921{
922 Q_Q(QQuickListView);
923 qreal pos = position();
925 if (item->y() + item->height() > pos && item->y() < pos + q->height()) {
926 if (isBottomToTop())
927 item->setY(-positionAt(index)-item->height());
928 else
930 }
931 } else {
932 if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
933 if (isRightToLeft())
934 item->setX(-positionAt(index)-item->width());
935 else
937 }
938 }
939}
940
942{
944 item->setPosition(pos);
945}
946
948{
949 if (!visibleItems.size())
950 return;
951 qreal diff = forwards - backwards;
953}
954
956{
959}
960
962{
963 bool changed = false;
964 if (highlight) {
965 if (trackedItem == highlight.get())
966 trackedItem = nullptr;
967 highlight.reset();
968
969 highlightPosAnimator.reset();
972 highlightPosAnimator = nullptr;
973 highlightWidthAnimator = nullptr;
974 highlightHeightAnimator = nullptr;
975
976 changed = true;
977 }
978
979 if (onDestruction)
980 return;
981
982 Q_Q(QQuickListView);
983 if (currentItem) {
985 if (item) {
986 std::unique_ptr<FxListItemSG> newHighlight
987 = std::make_unique<FxListItemSG>(item, q, true);
988 newHighlight->trackGeometry(true);
989
990 if (autoHighlight) {
991 newHighlight->setSize(static_cast<FxListItemSG*>(currentItem)->itemSize());
992 newHighlight->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition());
993 }
994 const QLatin1String posProp(orient == QQuickListView::Vertical ? "y" : "x");
995 highlightPosAnimator = std::make_unique<QSmoothedAnimation>();
996 highlightPosAnimator->target = QQmlProperty(item, posProp);
999
1000 highlightWidthAnimator = std::make_unique<QSmoothedAnimation>();
1004
1005 highlightHeightAnimator = std::make_unique<QSmoothedAnimation>();
1009
1010 highlight = std::move(newHighlight);
1011 changed = true;
1012 }
1013 }
1014 if (changed)
1015 emit q->highlightItemChanged();
1016}
1017
1019{
1021
1022 if ((!currentItem && highlight) || (currentItem && !highlight))
1025 if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
1026 // auto-update highlight
1027 FxListItemSG *listItem = static_cast<FxListItemSG*>(currentItem);
1029 ? -listItem->itemPosition()-listItem->itemSize()
1030 : listItem->itemPosition();
1031 highlightWidthAnimator->to = listItem->item->width();
1032 highlightHeightAnimator->to = listItem->item->height();
1034 if (highlight->item->width() == 0)
1035 highlight->item->setWidth(currentItem->item->width());
1036 } else {
1037 if (highlight->item->height() == 0)
1038 highlight->item->setHeight(currentItem->item->height());
1039 }
1040
1041 highlightPosAnimator->restart();
1042 highlightWidthAnimator->restart();
1043 highlightHeightAnimator->restart();
1044 }
1046}
1047
1049{
1050 if (highlight && currentItem) {
1051 static_cast<FxListItemSG*>(highlight.get())->setPosition(
1052 static_cast<FxListItemSG*>(currentItem)->itemPosition());
1053 }
1054}
1055
1057{
1059 return false;
1060
1061 return (highlightPosAnimator && highlightPosAnimator->isRunning()) ||
1064}
1065
1066
1068{
1069 Q_Q(QQuickListView);
1070 QQuickItem *sectionItem = nullptr;
1071 int i = sectionCacheSize-1;
1072 while (i >= 0 && !sectionCache[i])
1073 --i;
1074 if (i >= 0) {
1075 sectionItem = sectionCache[i];
1076 sectionCache[i] = nullptr;
1077 sectionItem->setVisible(true);
1079 setSectionHelper(context, sectionItem, section);
1080 } else {
1081 QQmlComponent* delegate = sectionCriteria->delegate();
1082 const bool reuseExistingContext = delegate->isBound();
1083 auto delegatePriv = QQmlComponentPrivate::get(delegate);
1084 QQmlPropertyCache::ConstPtr rootPropertyCache;
1085
1086 QQmlContext *creationContext = sectionCriteria->delegate()->creationContext();
1087 auto baseContext = creationContext ? creationContext : qmlContext(q);
1088 // if we need to insert a context property, we need a separate context
1089 QQmlContext *context = reuseExistingContext ? baseContext : new QQmlContext(baseContext);
1090 QObject *nobj = delegate->beginCreate(context);
1091 if (nobj) {
1092 if (delegatePriv->hadTopLevelRequiredProperties()) {
1093 delegate->setInitialProperties(nobj, {{QLatin1String("section"), section}});
1094 } else if (!reuseExistingContext) {
1095 context->setContextProperty(QLatin1String("section"), section);
1096 }
1097 if (!reuseExistingContext)
1099 sectionItem = qobject_cast<QQuickItem *>(nobj);
1100 if (!sectionItem) {
1101 delete nobj;
1102 } else {
1103 if (qFuzzyIsNull(sectionItem->z()))
1104 sectionItem->setZ(2);
1105 QQml_setParent_noEvent(sectionItem, contentItem);
1106 sectionItem->setParentItem(contentItem);
1107 }
1108 // sections are not controlled by FxListItemSG, so apply attached properties here
1109 QQuickItemViewAttached *attached = static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(sectionItem));
1110 attached->setView(q);
1111 } else if (!reuseExistingContext) {
1112 delete context;
1113 }
1115 }
1116
1117 if (sectionItem)
1119
1120 return sectionItem;
1121}
1122
1124{
1125 if (!item)
1126 return;
1127 int i = 0;
1128
1130
1131 do {
1132 if (!sectionCache[i]) {
1133 sectionCache[i] = item;
1134 sectionCache[i]->setVisible(false);
1135 return;
1136 }
1137 ++i;
1138 } while (i < sectionCacheSize);
1139 delete item;
1140}
1141
1142
1144{
1145 for (FxViewItem *item : std::as_const(visibleItems)) {
1146 FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
1147 if (listItem->section()) {
1148 qreal pos = listItem->position();
1149 releaseSectionItem(listItem->section());
1150 listItem->setSection(nullptr);
1151 listItem->setPosition(pos);
1152 }
1153 }
1154 for (int i = 0; i < sectionCacheSize; ++i) {
1155 delete sectionCache[i];
1156 sectionCache[i] = nullptr;
1157 }
1158}
1159
1161{
1163 return;
1167 if (!listItem->section()) {
1168 qreal pos = listItem->position();
1169 listItem->setSection(getSectionItem(listItem->attached->m_section));
1170 listItem->setPosition(pos);
1171 } else {
1173 setSectionHelper(context, listItem->section(), listItem->attached->m_section);
1174 }
1175 } else if (listItem->section()) {
1176 qreal pos = listItem->position();
1177 releaseSectionItem(listItem->section());
1178 listItem->setSection(nullptr);
1179 listItem->setPosition(pos);
1180 }
1181}
1182
1184{
1187 return;
1188
1189 bool isFlowReversed = isContentFlowReversed();
1190 qreal viewPos = isFlowReversed ? -position()-size() : position();
1191 qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
1192 qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
1193
1194 QQuickItem *sectionItem = nullptr;
1195 QQuickItem *lastSectionItem = nullptr;
1196 int index = 0;
1197 while (index < visibleItems.size()) {
1198 if (QQuickItem *section = static_cast<FxListItemSG *>(visibleItems.at(index))->section()) {
1199 // Find the current section header and last visible section header
1200 // and hide them if they will overlap a static section header.
1201 qreal sectionPos = orient == QQuickListView::Vertical ? section->y() : section->x();
1202 qreal sectionSize = orient == QQuickListView::Vertical ? section->height() : section->width();
1203 bool visTop = true;
1205 visTop = isFlowReversed ? -sectionPos-sectionSize >= startPos : sectionPos >= startPos;
1206 bool visBot = true;
1208 visBot = isFlowReversed ? -sectionPos <= endPos : sectionPos + sectionSize < endPos;
1209 section->setVisible(visBot && visTop);
1210 if (visTop && !sectionItem)
1211 sectionItem = section;
1212 if (isFlowReversed) {
1213 if (-sectionPos <= endPos)
1214 lastSectionItem = section;
1215 } else {
1216 if (sectionPos + sectionSize < endPos)
1217 lastSectionItem = section;
1218 }
1219 }
1220 ++index;
1221 }
1222
1223 // Current section header
1225 if (!currentSectionItem) {
1230 }
1232 if (!currentSectionItem)
1233 return;
1234
1237
1238 currentSectionItem->setVisible(!atBeginning && (!header || hasStickyHeader() || header->endPosition() < viewPos));
1239 qreal pos = isFlowReversed ? position() + size() - sectionSize : startPos;
1240 if (header)
1241 pos = isFlowReversed ? qMin(-header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
1242 if (sectionItem) {
1243 qreal sectionPos = orient == QQuickListView::Vertical ? sectionItem->y() : sectionItem->x();
1244 pos = isFlowReversed ? qMax(pos, sectionPos + sectionSize) : qMin(pos, sectionPos - sectionSize);
1245 }
1246 if (footer)
1247 pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
1250 else
1252 } else if (currentSectionItem) {
1254 currentSectionItem = nullptr;
1255 }
1256
1257 // Next section footer
1259 if (!nextSectionItem) {
1264 }
1266 if (!nextSectionItem)
1267 return;
1268
1271 qreal pos = isFlowReversed ? position() : endPos - sectionSize;
1272 if (footer)
1273 pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
1274 if (lastSectionItem) {
1275 qreal sectionPos = orient == QQuickListView::Vertical ? lastSectionItem->y() : lastSectionItem->x();
1276 pos = isFlowReversed ? qMin(pos, sectionPos - sectionSize) : qMax(pos, sectionPos + sectionSize);
1277 }
1278 if (header)
1279 pos = isFlowReversed ? qMin(-header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
1282 else
1284 } else if (nextSectionItem) {
1286 nextSectionItem = nullptr;
1287 }
1288}
1289
1291{
1292 Q_Q(QQuickListView);
1293 if (!q->isComponentComplete())
1294 return;
1295
1297
1299 QString prevSection;
1300 if (visibleIndex > 0)
1301 prevSection = sectionAt(visibleIndex-1);
1302 QQuickListViewAttached *prevAtt = nullptr;
1303 int prevIdx = -1;
1304 int idx = -1;
1305 for (FxViewItem *item : std::as_const(visibleItems)) {
1306 QQuickListViewAttached *attached = static_cast<QQuickListViewAttached*>(item->attached);
1307 attached->setPrevSection(prevSection);
1308 if (item->index != -1) {
1309 QString propValue = model->stringValue(item->index, sectionCriteria->property());
1310 attached->setSection(sectionCriteria->sectionString(propValue));
1311 idx = item->index;
1312 }
1313 updateInlineSection(static_cast<FxListItemSG*>(item));
1314 if (prevAtt)
1315 prevAtt->setNextSection(sectionAt(prevIdx+1));
1316 prevSection = attached->section();
1317 prevAtt = attached;
1318 prevIdx = item->index;
1319 }
1320 if (prevAtt) {
1321 if (idx > 0 && idx < model->count()-1)
1322 prevAtt->setNextSection(sectionAt(idx+1));
1323 else
1324 prevAtt->setNextSection(QString());
1325 }
1326 }
1327
1329}
1330
1332{
1333 Q_Q(QQuickListView);
1335 if (!currentSection.isEmpty()) {
1337 emit q->currentSectionChanged();
1338 }
1339 return;
1340 }
1342 qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
1343 qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
1344 int index = 0;
1345 int modelIndex = visibleIndex;
1346 while (index < visibleItems.size()) {
1348 if (item->endPosition() > startPos)
1349 break;
1350 if (item->index != -1)
1351 modelIndex = item->index;
1352 ++index;
1353 }
1354
1355 QString newSection = currentSection;
1356 if (index < visibleItems.size())
1357 newSection = visibleItems.at(index)->attached->section();
1358 else
1359 newSection = (*visibleItems.constBegin())->attached->section();
1360 if (newSection != currentSection) {
1361 currentSection = newSection;
1363 emit q->currentSectionChanged();
1364 }
1365
1367 // Don't want to scan for next section on every movement, so remember
1368 // the last section in the visible area and only scan for the next
1369 // section when that changes. Clearing lastVisibleSection will also
1370 // force searching.
1371 QString lastSection = currentSection;
1372 qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
1373 if (nextSectionItem && !inlineSections)
1375 while (index < visibleItems.size()) {
1376 FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(index));
1377 if (listItem->itemPosition() >= endPos)
1378 break;
1379 if (listItem->index != -1)
1380 modelIndex = listItem->index;
1381 lastSection = listItem->attached->section();
1382 ++index;
1383 }
1384
1385 if (lastVisibleSection != lastSection) {
1386 nextSection = QString();
1387 lastVisibleSection = lastSection;
1388 for (int i = modelIndex; i < itemCount; ++i) {
1389 QString section = sectionAt(i);
1390 if (section != lastSection) {
1391 nextSection = section;
1393 break;
1394 }
1395 }
1396 }
1397 }
1398}
1399
1401{
1403
1404 if (currentItem) {
1405 FxListItemSG *listItem = static_cast<FxListItemSG *>(currentItem);
1406
1407 // don't reposition the item if it is already in the visibleItems list
1408 FxViewItem *actualItem = visibleItem(currentIndex);
1409 if (!actualItem) {
1410 if (currentIndex == visibleIndex - 1 && visibleItems.size()) {
1411 // We can calculate exact postion in this case
1413 } else {
1414 // Create current item now and position as best we can.
1415 // Its position will be corrected when it becomes visible.
1417 }
1418 }
1419
1420 if (visibleItems.isEmpty())
1421 averageSize = listItem->size();
1422 }
1423}
1424
1426{
1427 if (!visibleItems.size())
1428 return;
1429 qreal sum = 0.0;
1430 for (FxViewItem *item : std::as_const(visibleItems))
1431 sum += item->size();
1433}
1434
1436{
1437 return header ? header->size() : 0.0;
1438}
1439
1441{
1442 return footer ? footer->size() : 0.0;
1443}
1444
1446{
1447 return index == 0;
1448}
1449
1451{
1452 return model && index == model->count()-1;
1453}
1454
1456{
1457 Q_Q(QQuickListView);
1458 bool created = false;
1459 if (!footer) {
1461 if (!item)
1462 return;
1463 footer = new FxListItemSG(item, q, true);
1464 footer->trackGeometry(true);
1465 created = true;
1466 }
1467
1468 FxListItemSG *listItem = static_cast<FxListItemSG*>(footer);
1471 } else if (visibleItems.size()) {
1473 qreal viewPos = isContentFlowReversed() ? -position() : position() + size();
1474 // using qBound() would throw an assert here, because max < min is a valid case
1475 // here, if the list's delegates do not fill the whole view
1476 qreal clampedPos = qMax(originPosition() - footerSize() + size(), qMin(listItem->position(), lastPosition()));
1477 listItem->setPosition(qBound(viewPos - footerSize(), clampedPos, viewPos));
1478 } else {
1479 qreal endPos = lastPosition();
1480 if (findLastVisibleIndex() == model->count()-1) {
1481 listItem->setPosition(endPos);
1482 } else {
1483 qreal visiblePos = position() + q->height();
1484 if (endPos <= visiblePos || listItem->position() < endPos)
1485 listItem->setPosition(endPos);
1486 }
1487 }
1488 } else {
1489 listItem->setPosition(visiblePos);
1490 }
1491
1492 if (created)
1493 emit q->footerItemChanged();
1494}
1495
1497{
1500}
1501
1503{
1504 FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
1505 const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
1507 int fixupDura = timeline.duration();
1508 if (fixupDura < 0)
1509 fixupDura = fixupDuration/2;
1510 const int t = timeline.time();
1511
1512 const qreal progress = qreal(t)/fixupDura;
1514 const qreal headerPosition = fixupHeaderPosition * (1 - progress) + ultimateHeaderPosition * progress;
1515 const qreal viewPos = isContentFlowReversed() ? -position() - size() : position();
1516 const qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size());
1517 listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos));
1518 }
1519}
1520
1522{
1523 Q_Q(QQuickListView);
1524 bool created = false;
1525 if (!header) {
1527 if (!item)
1528 return;
1529 header = new FxListItemSG(item, q, true);
1530 header->trackGeometry(true);
1531 created = true;
1532 }
1533
1534 FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
1536 listItem->setPosition(isContentFlowReversed() ? -position() - size() : position());
1537 } else if (visibleItems.size()) {
1538 const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
1540 qreal headerPosition = listItem->position();
1541 const qreal viewPos = isContentFlowReversed() ? -position() - size() : position();
1542 // Make sure the header is not shown if we absolutely do not have any plans to show it
1543 if (fixingUp && !headerNeedsSeparateFixup)
1544 headerPosition = viewPos - headerSize();
1545 // using qBound() would throw an assert here, because max < min is a valid case
1546 // here, if the list's delegates do not fill the whole view
1547 qreal clampedPos = qMax(originPosition() - headerSize(), qMin(headerPosition, lastPosition() - size()));
1548 listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos));
1549 } else {
1550 qreal startPos = originPosition();
1551 if (visibleIndex == 0) {
1552 listItem->setPosition(startPos - headerSize());
1553 } else {
1554 if (position() <= startPos || listItem->position() > startPos - headerSize())
1555 listItem->setPosition(startPos - headerSize());
1556 }
1557 }
1558 } else {
1559 listItem->setPosition(-headerSize());
1560 }
1561
1562 if (created)
1563 emit q->headerItemChanged();
1564}
1565
1567{
1569}
1570
1572{
1574}
1575
1577{
1578 QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
1579 qmlAttachedPropertiesObject<QQuickListView>(item));
1580 if (attached) // can be null for default components (see createComponentItem)
1581 attached->setView(const_cast<QQuickListView*>(q_func()));
1582}
1583
1585 const QRectF &oldGeometry)
1586{
1587 Q_Q(QQuickListView);
1588
1590 if (!q->isComponentComplete())
1591 return;
1592
1593 if (currentItem && currentItem->item == item) {
1594 const bool contentFlowReversed = isContentFlowReversed();
1595 const qreal pos = position();
1596 const qreal sz = size();
1597 const qreal from = contentFlowReversed ? -pos - displayMarginBeginning - sz : pos - displayMarginBeginning;
1598 const qreal to = contentFlowReversed ? -pos + displayMarginEnd : pos + sz + displayMarginEnd;
1600 }
1601
1602 if (item != contentItem && (!highlight || item != highlight->item)) {
1603 if ((orient == QQuickListView::Vertical && change.heightChange())
1604 || (orient == QQuickListView::Horizontal && change.widthChange())) {
1605
1606 // if visibleItems.first() has resized, adjust its pos since it is used to
1607 // position all subsequent items
1609 FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.constFirst());
1610#if QT_CONFIG(quick_viewtransitions)
1611 if (listItem->transitionScheduledOrRunning())
1612 return;
1613#endif
1615 const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height();
1616 const qreal heightDiff = item->height() - oldGeometry.height();
1617 if (verticalLayoutDirection == QQuickListView::TopToBottom && oldItemEndPosition < q->contentY())
1618 listItem->setPosition(listItem->position() - heightDiff, true);
1619 else if (verticalLayoutDirection == QQuickListView::BottomToTop && oldItemEndPosition > q->contentY())
1620 listItem->setPosition(listItem->position() + heightDiff, true);
1621 } else {
1622 const qreal oldItemEndPosition = q->effectiveLayoutDirection() == Qt::RightToLeft ? -oldGeometry.x() : oldGeometry.x() + oldGeometry.width();
1623 const qreal widthDiff = item->width() - oldGeometry.width();
1624 if (q->effectiveLayoutDirection() == Qt::LeftToRight && oldItemEndPosition < q->contentX())
1625 listItem->setPosition(listItem->position() - widthDiff, true);
1626 else if (q->effectiveLayoutDirection() == Qt::RightToLeft && oldItemEndPosition > q->contentX())
1627 listItem->setPosition(listItem->position() + widthDiff, true);
1628 }
1629 }
1631 }
1632 }
1633}
1634
1636{
1638 fixupY();
1639 else
1640 fixupX();
1641}
1642
1644{
1648 return;
1649 } else if (orient == QQuickListView::Vertical && &data == &hData) {
1652 return;
1653 }
1654
1655 // update footer if all visible items have been removed
1656 if (visibleItems.size() == 0)
1657 updateFooter();
1658
1659 correctFlick = false;
1662
1663 qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
1664
1666 qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
1668 // if we've been dragged < averageSize/2 then bias towards the next item
1669 qreal dist = data.move.value() - data.pressPos;
1670 qreal bias = 0;
1671 if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2)
1672 bias = averageSize/2;
1673 else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2)
1674 bias = -averageSize/2;
1676 bias = -bias;
1677 tempPosition -= bias;
1678 }
1679
1680 qreal snapOffset = 0;
1681 qreal overlayHeaderOffset = 0;
1682 bool isHeaderWithinBounds = false;
1683 if (header) {
1684 qreal visiblePartOfHeader = header->position() + header->size() - tempPosition;
1685 isHeaderWithinBounds = visiblePartOfHeader > 0;
1686 switch (headerPositioning) {
1688 snapOffset = header->size();
1689 overlayHeaderOffset = header->size();
1690 break;
1692 if (isHeaderWithinBounds && tempPosition < originPosition())
1693 // For the inline header, we want to snap to the first item
1694 // if we're more than halfway down the inline header.
1695 // So if we look for an item halfway down of the header
1696 snapOffset = header->size() / 2;
1697 break;
1699 desiredHeaderVisible = visiblePartOfHeader > header->size()/2;
1700 if (qFuzzyCompare(header->position(), tempPosition)) {
1701 // header was pulled down; make sure it remains visible and snap items to bottom of header
1702 snapOffset = header->size();
1703 } else if (desiredHeaderVisible) {
1704 // More than 50% of the header is shown. Show it fully.
1705 // Scroll the view so the next item snaps to the header.
1706 snapOffset = header->size();
1707 overlayHeaderOffset = header->size();
1708 }
1709 break;
1710 }
1711 }
1712 FxViewItem *topItem = snapItemAt(tempPosition + snapOffset + highlightRangeStart);
1713 if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) {
1714 // StrictlyEnforceRange always keeps an item in range
1716 topItem = currentItem;
1717 }
1718 FxViewItem *bottomItem = snapItemAt(tempPosition + snapOffset + highlightRangeEnd);
1719 if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) {
1720 // StrictlyEnforceRange always keeps an item in range
1722 bottomItem = currentItem;
1723 }
1724 qreal pos = 0;
1725 bool isInBounds = -position() > maxExtent && -position() <= minExtent;
1726
1727 if (header && !topItem && isInBounds) {
1728 // We are trying to pull back further than needed
1729 switch (headerPositioning) {
1731 pos = startPosition() - overlayHeaderOffset;
1732 break;
1735 break;
1738 break;
1739 }
1740 } else if (topItem && (isInBounds || strictHighlightRange)) {
1741 if (topItem->index == 0 && header && !hasStickyHeader() && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) {
1743 } else {
1745 // We pulled down the header. If it isn't pulled all way down, we need to snap
1746 // the header.
1747 if (qFuzzyCompare(tempPosition, header->position())) {
1748 // It is pulled all way down. Scroll-snap the content, but not the header.
1750 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + snapOffset;
1751 else
1752 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - snapOffset;
1753 } else {
1754 // Header is not pulled all way down, make it completely visible or hide it.
1755 // Depends on how much of the header is visible.
1757 // More than half of the header is visible - show it.
1758 // Scroll so that the topItem is aligned to a fully visible header
1760 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + headerSize();
1761 else
1762 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - headerSize();
1763 } else {
1764 // Less than half is visible - hide the header. Scroll so
1765 // that the topItem is aligned to the top of the view
1767 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size();
1768 else
1769 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart;
1770 }
1771 }
1772
1773 headerNeedsSeparateFixup = isHeaderWithinBounds || desiredHeaderVisible;
1775 // We need to animate the header independently if it starts visible or should end as visible,
1776 // since the header should not necessarily follow the content.
1777 // Store the desired viewport position.
1778 // Also store the header position so we know where to animate the header from (fixupHeaderPosition).
1779 // We deduce the desired header position from the desiredViewportPosition variable.
1782
1783 FxListItemSG *headerItem = static_cast<FxListItemSG*>(header);
1784 fixupHeaderPosition = headerItem->position();
1785
1786 // follow the same fixup timeline
1789 }
1790 } else if (isContentFlowReversed()) {
1791 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + overlayHeaderOffset;
1792 } else {
1793 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - overlayHeaderOffset;
1794 }
1795 }
1796 } else if (bottomItem && isInBounds) {
1798 pos = -static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size() + overlayHeaderOffset;
1799 else
1800 pos = static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd - overlayHeaderOffset;
1801 } else {
1803 return;
1804 }
1806
1807 qreal dist = qAbs(data.move + pos);
1808 if (dist >= 0) {
1809 // Even if dist == 0 we still start the timeline, because we use the same timeline for
1810 // moving the header. And we might need to move the header while the content does not
1811 // need moving
1812 timeline.reset(data.move);
1813 if (fixupMode != Immediate) {
1815 data.fixingUp = true;
1816 } else {
1817 timeline.set(data.move, -pos);
1818 }
1819 vTime = timeline.time();
1820 }
1821 } else if (currentItem && strictHighlightRange && moveReason != QQuickListViewPrivate::SetIndex) {
1823 qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
1824 if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd)
1825 viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd;
1826 if (viewPos > pos - highlightRangeStart)
1827 viewPos = pos - highlightRangeStart;
1829 viewPos = -viewPos-size();
1830
1831 timeline.reset(data.move);
1832 if (viewPos != position()) {
1833 if (fixupMode != Immediate) {
1834 if (fixupMode == ExtentChanged && data.fixingUp)
1836 else
1838 data.fixingUp = true;
1839 } else {
1840 timeline.set(data.move, -viewPos);
1841 }
1842 }
1843 vTime = timeline.time();
1844 } else {
1846 }
1847 data.inOvershoot = false;
1848 fixupMode = Normal;
1849}
1850
1851bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
1852 QQuickTimeLineCallback::Callback fixupCallback, QEvent::Type eventType, qreal velocity)
1853{
1854 data.fixingUp = false;
1855 moveReason = Mouse;
1857 correctFlick = true;
1858 return QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, eventType, velocity);
1859 }
1860 qreal maxDistance = 0;
1861 const qreal dataValue =
1862 isContentFlowReversed() ? -data.move.value() + size() : data.move.value();
1863
1864 // -ve velocity means list is moving up/left
1865 if (velocity > 0) {
1866 if (data.move.value() < minExtent) {
1868 // averageSize/2 + 1 - next item
1869 qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
1871 bias = -bias;
1872 data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
1873 maxDistance = qAbs(data.flickTarget - data.move.value());
1874 velocity = maxVelocity;
1875 } else {
1876 maxDistance = qAbs(minExtent - data.move.value());
1877 }
1878 }
1880 data.flickTarget = minExtent;
1881 } else {
1882 if (data.move.value() > maxExtent) {
1884 // averageSize/2 + 1 - next item
1885 qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
1887 bias = -bias;
1888 data.flickTarget =
1890 maxDistance = qAbs(data.flickTarget - data.move.value());
1891 velocity = -maxVelocity;
1892 } else {
1893 maxDistance = qAbs(maxExtent - data.move.value());
1894 }
1895 }
1897 data.flickTarget = maxExtent;
1898 }
1900 if (maxDistance > 0 || overShoot) {
1901 // These modes require the list to stop exactly on an item boundary.
1902 // The initial flick will estimate the boundary to stop on.
1903 // Since list items can have variable sizes, the boundary will be
1904 // reevaluated and adjusted as we approach the boundary.
1905 qreal v = velocity;
1906 if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1907 if (v < 0)
1908 v = -maxVelocity;
1909 else
1910 v = maxVelocity;
1911 }
1912 if (!hData.flicking && !vData.flicking) {
1913 // the initial flick - estimate boundary
1914 qreal accel = eventType == QEvent::Wheel ? wheelDeceleration : deceleration;
1915 qreal v2 = v * v;
1916 overshootDist = 0.0;
1917 // + averageSize/4 to encourage moving at least one item in the flick direction
1918 qreal dist = v2 / (accel * 2.0) + averageSize/4;
1919 if (maxDistance > 0)
1920 dist = qMin(dist, maxDistance);
1921 if (v > 0)
1922 dist = -dist;
1923 if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QQuickListView::SnapOneItem) {
1925 qreal distTemp = isContentFlowReversed() ? -dist : dist;
1926 data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + distTemp) + highlightRangeStart;
1927 }
1928 data.flickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
1929 if (overShoot) {
1930 if (data.flickTarget > minExtent) {
1932 data.flickTarget += overshootDist;
1933 } else if (data.flickTarget < maxExtent) {
1935 data.flickTarget -= overshootDist;
1936 }
1937 }
1938 qreal adjDist = -data.flickTarget + data.move.value();
1939 if (qAbs(adjDist) > qAbs(dist)) {
1940 // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
1941 qreal adjv2 = accel * 2.0f * qAbs(adjDist);
1942 if (adjv2 > v2) {
1943 v2 = adjv2;
1944 v = qSqrt(v2);
1945 if (dist > 0)
1946 v = -v;
1947 }
1948 }
1949 dist = adjDist;
1950 accel = v2 / (2.0f * qAbs(dist));
1951 } else if (overShoot) {
1952 data.flickTarget = data.move.value() - dist;
1953 if (data.flickTarget > minExtent) {
1955 data.flickTarget += overshootDist;
1956 } else if (data.flickTarget < maxExtent) {
1958 data.flickTarget -= overshootDist;
1959 }
1960 }
1961 timeline.reset(data.move);
1962 timeline.accel(data.move, v, accel, maxDistance + overshootDist);
1963 timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
1964 correctFlick = true;
1965 return true;
1966 } else {
1967 // reevaluate the target boundary.
1968 qreal newtarget = data.flickTarget;
1970 qreal tempFlickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
1971 newtarget = -snapPosAt(-(tempFlickTarget - highlightRangeStart)) + highlightRangeStart;
1972 newtarget = isContentFlowReversed() ? -newtarget+size() : newtarget;
1973 }
1974 if (velocity < 0 && newtarget <= maxExtent)
1975 newtarget = maxExtent - overshootDist;
1976 else if (velocity > 0 && newtarget >= minExtent)
1977 newtarget = minExtent + overshootDist;
1978 if (newtarget == data.flickTarget) { // boundary unchanged - nothing to do
1979 if (qAbs(velocity) < _q_MinimumFlickVelocity)
1980 correctFlick = false;
1981 return false;
1982 }
1983 data.flickTarget = newtarget;
1984 qreal dist = -newtarget + data.move.value();
1985 if ((v < 0 && dist < 0) || (v > 0 && dist > 0)) {
1986 correctFlick = false;
1987 timeline.reset(data.move);
1989 return false;
1990 }
1991 timeline.reset(data.move);
1992 timeline.accelDistance(data.move, v, -dist);
1993 timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
1994 return false;
1995 }
1996 } else {
1997 correctFlick = false;
1998 timeline.reset(data.move);
2000 return false;
2001 }
2002}
2003
2005{
2006 if (!QQmlContextData::get(context)->isInternal() && context->contextProperty(QLatin1String("section")).isValid())
2007 context->setContextProperty(QLatin1String("section"), section);
2008 else
2009 sectionItem->setProperty("section", section);
2010}
2011
2013{
2014 QObject *attachedObject = qmlAttachedPropertiesObject<QQuickListView>(object);
2015 return static_cast<QQuickItemViewAttached *>(attachedObject);
2016}
2017
2018//----------------------------------------------------------------------------
2019
2242{
2243}
2244
2246{
2247}
2248
2488//###Possibly rename these properties, since they are very useful even without a highlight?
2518{
2519 Q_D(QQuickListView);
2520 if (d->autoHighlight != autoHighlight) {
2521 if (!autoHighlight) {
2522 if (d->highlightPosAnimator)
2523 d->highlightPosAnimator->stop();
2524 if (d->highlightWidthAnimator)
2525 d->highlightWidthAnimator->stop();
2526 if (d->highlightHeightAnimator)
2527 d->highlightHeightAnimator->stop();
2528 }
2530 }
2531}
2532
2541{
2542 Q_D(const QQuickListView);
2543 return d->spacing;
2544}
2545
2547{
2548 Q_D(QQuickListView);
2549 if (spacing != d->spacing) {
2550 d->spacing = spacing;
2551 d->forceLayoutPolish();
2553 }
2554}
2555
2572{
2573 Q_D(const QQuickListView);
2574 return d->orient;
2575}
2576
2578{
2579 Q_D(QQuickListView);
2580 if (d->orient != orientation) {
2581 d->orient = orientation;
2582 if (d->orient == Vertical) {
2583 if (d->flickableDirection == HorizontalFlick) {
2585 if (isComponentComplete())
2586 setContentWidth(-1);
2587 }
2588 setContentX(0);
2589 } else {
2590 if (d->flickableDirection == VerticalFlick) {
2592 if (isComponentComplete())
2593 setContentHeight(-1);
2594 }
2595 setContentY(0);
2596 }
2597 d->regenerate(true);
2599 }
2600}
2601
2799{
2800 Q_D(QQuickListView);
2801 if (!d->sectionCriteria)
2802 d->sectionCriteria = new QQuickViewSection(this);
2803 return d->sectionCriteria;
2804}
2805
2811{
2812 Q_D(const QQuickListView);
2813 return d->currentSection;
2814}
2815
2853{
2854 Q_D(const QQuickListView);
2855 return d->highlightMoveVelocity;
2856}
2857
2859{
2860 Q_D(QQuickListView);
2861 if (d->highlightMoveVelocity != speed) {
2862 d->highlightMoveVelocity = speed;
2863 if (d->highlightPosAnimator)
2864 d->highlightPosAnimator->velocity = d->highlightMoveVelocity;
2866 }
2867}
2868
2870{
2871 Q_D(QQuickListView);
2872 if (d->highlightMoveDuration != duration) {
2873 if (d->highlightPosAnimator)
2874 d->highlightPosAnimator->userDuration = duration;
2876 }
2877}
2878
2880{
2881 Q_D(const QQuickListView);
2882 return d->highlightResizeVelocity;
2883}
2884
2886{
2887 Q_D(QQuickListView);
2888 if (d->highlightResizeVelocity != speed) {
2889 d->highlightResizeVelocity = speed;
2890 if (d->highlightWidthAnimator)
2891 d->highlightWidthAnimator->velocity = d->highlightResizeVelocity;
2892 if (d->highlightHeightAnimator)
2893 d->highlightHeightAnimator->velocity = d->highlightResizeVelocity;
2895 }
2896}
2897
2899{
2900 Q_D(const QQuickListView);
2901 return d->highlightResizeDuration;
2902}
2903
2905{
2906 Q_D(QQuickListView);
2907 if (d->highlightResizeDuration != duration) {
2908 d->highlightResizeDuration = duration;
2909 if (d->highlightWidthAnimator)
2910 d->highlightWidthAnimator->userDuration = d->highlightResizeDuration;
2911 if (d->highlightHeightAnimator)
2912 d->highlightHeightAnimator->userDuration = d->highlightResizeDuration;
2914 }
2915}
2916
2939{
2940 Q_D(const QQuickListView);
2941 return d->snapMode;
2942}
2943
2945{
2946 Q_D(QQuickListView);
2947 if (d->snapMode != mode) {
2948 d->snapMode = mode;
2950 d->fixupPosition();
2951 }
2952}
2953
2954
3027{
3028 Q_D(const QQuickListView);
3029 return d->headerPositioning;
3030}
3031
3033{
3034 Q_D(QQuickListView);
3035 if (d->headerPositioning != positioning) {
3036 d->applyPendingChanges();
3037 d->headerPositioning = positioning;
3038 if (isComponentComplete()) {
3039 d->updateHeader();
3040 d->updateViewport();
3041 d->fixupPosition();
3042 }
3043 emit headerPositioningChanged();
3044 }
3045}
3046
3074{
3075 Q_D(const QQuickListView);
3076 return d->footerPositioning;
3077}
3078
3080{
3081 Q_D(QQuickListView);
3082 if (d->footerPositioning != positioning) {
3083 d->applyPendingChanges();
3084 d->footerPositioning = positioning;
3085 if (isComponentComplete()) {
3086 d->updateFooter();
3087 d->updateViewport();
3088 d->fixupPosition();
3089 }
3090 emit footerPositioningChanged();
3091 }
3092}
3093
3396void QQuickListView::viewportMoved(Qt::Orientations orient)
3397{
3398 Q_D(QQuickListView);
3400
3401 if (!d->itemCount) {
3402 if (d->hasStickyHeader())
3403 d->updateHeader();
3404 if (d->hasStickyFooter())
3405 d->updateFooter();
3406 return;
3407 }
3408
3409 // Recursion can occur due to refill changing the content size.
3410 if (d->inViewportMoved)
3411 return;
3412 d->inViewportMoved = true;
3413
3414 if (yflick()) {
3415 if (d->isBottomToTop())
3416 d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
3417 else
3418 d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
3419 } else {
3420 if (d->isRightToLeft())
3421 d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
3422 else
3423 d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
3424 }
3425
3426 d->refillOrLayout();
3427
3428 // Set visibility of items to eliminate cost of items outside the visible area.
3429 qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
3430 qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
3431 for (FxViewItem *item : std::as_const(d->visibleItems)) {
3432 if (item->item)
3433 QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
3434 }
3435 if (d->currentItem)
3436 QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to);
3437
3438 if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
3439 d->moveReason = QQuickListViewPrivate::Mouse;
3440 if (d->moveReason != QQuickListViewPrivate::SetIndex) {
3441 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
3442 // reposition highlight
3443 qreal pos = d->highlight->position();
3444 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
3445 if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
3446 pos = viewPos + d->highlightRangeEnd - d->highlight->size();
3447 if (pos < viewPos + d->highlightRangeStart)
3448 pos = viewPos + d->highlightRangeStart;
3449 if (pos != d->highlight->position()) {
3450 d->highlightPosAnimator->stop();
3451 static_cast<FxListItemSG*>(d->highlight.get())->setPosition(pos);
3452 } else {
3453 d->updateHighlight();
3454 }
3455
3456 // update current index
3457 if (FxViewItem *snapItem = d->snapItemAt(d->highlight->position())) {
3458 if (snapItem->index >= 0 && snapItem->index != d->currentIndex)
3459 d->updateCurrent(snapItem->index);
3460 }
3461 }
3462 }
3463
3464 if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) {
3465 d->inFlickCorrection = true;
3466 // Near an end and it seems that the extent has changed?
3467 // Recalculate the flick so that we don't end up in an odd position.
3468 if (yflick() && !d->vData.inOvershoot) {
3469 if (d->vData.velocity > 0) {
3470 const qreal minY = minYExtent();
3471 if ((minY - d->vData.move.value() < height()/2 || d->vData.flickTarget - d->vData.move.value() < height()/2)
3472 && minY != d->vData.flickTarget)
3473 d->flickY(QEvent::TouchUpdate, -d->vData.smoothVelocity.value());
3474 } else if (d->vData.velocity < 0) {
3475 const qreal maxY = maxYExtent();
3476 if ((d->vData.move.value() - maxY < height()/2 || d->vData.move.value() - d->vData.flickTarget < height()/2)
3477 && maxY != d->vData.flickTarget)
3478 d->flickY(QEvent::TouchUpdate, -d->vData.smoothVelocity.value());
3479 }
3480 }
3481
3482 if (xflick() && !d->hData.inOvershoot) {
3483 if (d->hData.velocity > 0) {
3484 const qreal minX = minXExtent();
3485 if ((minX - d->hData.move.value() < width()/2 || d->hData.flickTarget - d->hData.move.value() < width()/2)
3486 && minX != d->hData.flickTarget)
3487 d->flickX(QEvent::TouchUpdate, -d->hData.smoothVelocity.value());
3488 } else if (d->hData.velocity < 0) {
3489 const qreal maxX = maxXExtent();
3490 if ((d->hData.move.value() - maxX < width()/2 || d->hData.move.value() - d->hData.flickTarget < width()/2)
3491 && maxX != d->hData.flickTarget)
3492 d->flickX(QEvent::TouchUpdate, -d->hData.smoothVelocity.value());
3493 }
3494 }
3495 d->inFlickCorrection = false;
3496 }
3497 if (d->hasStickyHeader())
3498 d->updateHeader();
3499 if (d->hasStickyFooter())
3500 d->updateFooter();
3501 if (d->sectionCriteria) {
3502 d->updateCurrentSection();
3503 d->updateStickySections();
3504 }
3505 d->inViewportMoved = false;
3506}
3507
3509{
3510 Q_D(QQuickListView);
3511 if (d->model && d->model->count() && ((d->interactive && !d->explicitKeyNavigationEnabled)
3512 || (d->explicitKeyNavigationEnabled && d->keyNavigationEnabled))) {
3513 if ((d->orient == QQuickListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Left)
3514 || (d->orient == QQuickListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right)
3515 || (d->orient == QQuickListView::Vertical && !d->isBottomToTop() && event->key() == Qt::Key_Up)
3516 || (d->orient == QQuickListView::Vertical && d->isBottomToTop() && event->key() == Qt::Key_Down)) {
3517 if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
3519 event->accept();
3520 return;
3521 } else if (d->wrap) {
3522 event->accept();
3523 return;
3524 }
3525 } else if ((d->orient == QQuickListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Right)
3526 || (d->orient == QQuickListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left)
3527 || (d->orient == QQuickListView::Vertical && !d->isBottomToTop() && event->key() == Qt::Key_Down)
3528 || (d->orient == QQuickListView::Vertical && d->isBottomToTop() && event->key() == Qt::Key_Up)) {
3529 if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
3531 event->accept();
3532 return;
3533 } else if (d->wrap) {
3534 event->accept();
3535 return;
3536 }
3537 }
3538 }
3539 event->ignore();
3541}
3542
3543void QQuickListView::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
3544{
3545 Q_D(QQuickListView);
3546
3547 if (d->model) {
3548 // When the view changes size, we force the pool to
3549 // shrink by releasing all pooled items.
3550 d->model->drainReusableItemsPool(0);
3551 }
3552
3553 if (d->isRightToLeft()) {
3554 // maintain position relative to the right edge
3555 qreal dx = newGeometry.width() - oldGeometry.width();
3556 setContentX(contentX() - dx);
3557 } else if (d->isBottomToTop()) {
3558 // maintain position relative to the bottom edge
3559 qreal dy = newGeometry.height() - oldGeometry.height();
3560 setContentY(contentY() - dy);
3561 }
3562 QQuickItemView::geometryChange(newGeometry, oldGeometry);
3563}
3564
3566{
3568
3569 // setting the view from the FxViewItem wrapper is too late if the delegate
3570 // needs access to the view in Component.onCompleted
3572 if (item) {
3573 QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
3574 qmlAttachedPropertiesObject<QQuickListView>(item));
3575 if (attached)
3576 attached->setView(this);
3577 }
3578}
3579
3581{
3582 Q_D(const QQuickListView);
3583 if (d->layoutOrientation() == Qt::Horizontal && d->flickableDirection != HorizontalFlick)
3586}
3587
3589{
3590 Q_D(const QQuickListView);
3591 if (d->layoutOrientation() == Qt::Vertical && d->flickableDirection != VerticalFlick)
3594}
3595
3606{
3607 Q_D(QQuickListView);
3608 int count = d->model ? d->model->count() : 0;
3609 if (count && (currentIndex() < count - 1 || d->wrap)) {
3610 d->moveReason = QQuickListViewPrivate::SetIndex;
3611 int index = currentIndex()+1;
3612 setCurrentIndex((index >= 0 && index < count) ? index : 0);
3613 }
3614}
3615
3626{
3627 Q_D(QQuickListView);
3628 int count = d->model ? d->model->count() : 0;
3629 if (count && (currentIndex() > 0 || d->wrap)) {
3630 d->moveReason = QQuickListViewPrivate::SetIndex;
3631 int index = currentIndex()-1;
3632 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
3633 }
3634}
3635
3637{
3638 Q_Q(QQuickListView);
3639 if (q->isComponentComplete() && model) {
3640 QList<QByteArray> roles;
3642 roles << sectionCriteria->property().toUtf8();
3643 model->setWatchedRoles(roles);
3645 if (itemCount)
3647 }
3648}
3649
3651{
3652 Q_Q(QQuickListView);
3653#if QT_CONFIG(quick_viewtransitions)
3654 Q_UNUSED(movingIntoView)
3655#endif
3656 int modelIndex = change.index;
3657 int count = change.count;
3658
3659 if (q->size().isEmpty() && visibleItems.isEmpty())
3660 return false;
3661
3662 qreal tempPos = isContentFlowReversed() ? -position()-size() : position();
3663 int index = visibleItems.size() ? mapFromModel(modelIndex) : 0;
3664 qreal lastVisiblePos = buffer + displayMarginEnd + tempPos + size();
3665
3666 if (index < 0) {
3667 int i = visibleItems.size() - 1;
3668 while (i > 0 && visibleItems.at(i)->index == -1)
3669 --i;
3670 if (i == 0 && visibleItems.constFirst()->index == -1) {
3671 // there are no visible items except items marked for removal
3673 } else if (visibleItems.at(i)->index + 1 == modelIndex
3674 && visibleItems.at(i)->endPosition() <= lastVisiblePos) {
3675 // Special case of appending an item to the model.
3677 } else {
3678 if (modelIndex < visibleIndex) {
3679 // Insert before visible items
3681 for (FxViewItem *item : std::as_const(visibleItems)) {
3682 if (item->index != -1 && item->index >= modelIndex)
3683 item->index += count;
3684 }
3685 }
3686 return true;
3687 }
3688 }
3689
3690 // index can be the next item past the end of the visible items list (i.e. appended)
3691 qreal pos = 0;
3692 if (visibleItems.size()) {
3695 }
3696
3697 // Update the indexes of the following visible items.
3698 for (FxViewItem *item : std::as_const(visibleItems)) {
3699 if (item->index != -1 && item->index >= modelIndex) {
3700 item->index += count;
3701#if QT_CONFIG(quick_viewtransitions)
3702 if (change.isMove())
3703 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
3704 else
3705 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false);
3706#endif
3707 }
3708 }
3709
3710 bool visibleAffected = false;
3711 if (insertResult->visiblePos.isValid() && pos < insertResult->visiblePos) {
3712 // Insert items before the visible item.
3713 int insertionIdx = index;
3714 qreal from = tempPos - displayMarginBeginning - buffer;
3715
3716 if (insertionIdx < visibleIndex) {
3717 if (pos >= from) {
3718 // items won't be visible, just note the size for repositioning
3720 }
3721 } else {
3722 MutableModelIterator it(model, modelIndex + count - 1, modelIndex -1);
3723 for (; it.hasNext() && pos >= from; it.next()) {
3724 // item is before first visible e.g. in cache buffer
3725 FxViewItem *item = nullptr;
3726 if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(it.index))))
3727 item->index = it.index;
3728 if (!item)
3730 if (!item)
3731 return false;
3732 if (it.removedAtIndex)
3733 continue;
3734
3735 visibleAffected = true;
3736 visibleItems.insert(insertionIdx, item);
3737 if (insertionIdx == 0)
3738 insertResult->changedFirstItem = true;
3739 if (!change.isMove()) {
3740 addedItems->append(item);
3741#if QT_CONFIG(quick_viewtransitions)
3742 if (transitioner)
3743 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
3744 else
3745#endif
3746 static_cast<FxListItemSG *>(item)->setPosition(pos, true);
3747 }
3748 insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
3749 pos -= item->size() + spacing;
3750 index++;
3751 }
3752 }
3753
3754 int firstOkIdx = -1;
3755 for (int i = 0; i <= insertionIdx && i < visibleItems.size() - 1; i++) {
3756 if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
3757 firstOkIdx = i + 1;
3758 break;
3759 }
3760 }
3761 for (int i = 0; i < firstOkIdx; i++) {
3762 FxViewItem *nvItem = visibleItems.takeFirst();
3763 addedItems->removeOne(nvItem);
3764 removeItem(nvItem);
3765 }
3766
3767 } else {
3768 MutableModelIterator it(model, modelIndex, modelIndex + count);
3769 for (; it.hasNext() && pos <= lastVisiblePos; it.next()) {
3770 visibleAffected = true;
3771 FxViewItem *item = nullptr;
3772 if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(it.index))))
3773 item->index = it.index;
3774#if QT_CONFIG(quick_viewtransitions)
3775 bool newItem = !item;
3776#endif
3777 it.removedAtIndex = false;
3778 if (!item)
3780 if (!item)
3781 return false;
3782 if (it.removedAtIndex) {
3784 continue;
3785 }
3786
3788 if (index == 0)
3789 insertResult->changedFirstItem = true;
3790 if (change.isMove()) {
3791 // we know this is a move target, since move displaced items that are
3792 // shuffled into view due to a move would be added in refill()
3793#if QT_CONFIG(quick_viewtransitions)
3794 if (newItem && transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true))
3795 movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
3796#endif
3797 } else {
3798 addedItems->append(item);
3799#if QT_CONFIG(quick_viewtransitions)
3800 if (transitioner)
3801 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
3802 else
3803#endif
3804 static_cast<FxListItemSG *>(item)->setPosition(pos, true);
3805 }
3806 insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
3807 pos += item->size() + spacing;
3808 ++index;
3809 }
3810 it.disconnect();
3811
3812 if (0 < index && index < visibleItems.size()) {
3813 FxViewItem *prevItem = visibleItems.at(index - 1);
3815 if (prevItem->index != item->index - 1) {
3816 int i = index;
3817#if QT_CONFIG(quick_viewtransitions)
3818 qreal prevPos = prevItem->position();
3819#endif
3820 while (i < visibleItems.size()) {
3821 FxListItemSG *nvItem = static_cast<FxListItemSG *>(visibleItems.takeLast());
3822 insertResult->sizeChangesAfterVisiblePos -= nvItem->size() + spacing;
3823 addedItems->removeOne(nvItem);
3824#if QT_CONFIG(quick_viewtransitions)
3825 if (nvItem->transitionScheduledOrRunning())
3826 nvItem->setPosition(prevPos + (nvItem->index - prevItem->index) * averageSize);
3827#endif
3828 removeItem(nvItem);
3829 }
3830 }
3831 }
3832 }
3833
3835
3836 return visibleAffected;
3837}
3838
3839#if QT_CONFIG(quick_viewtransitions)
3840void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult)
3841{
3842 Q_UNUSED(insertionResult);
3843
3844 if (!transitioner)
3845 return;
3846
3847 int markerItemIndex = -1;
3848 for (int i=0; i<visibleItems.size(); i++) {
3849 if (visibleItems.at(i)->index == afterModelIndex) {
3850 markerItemIndex = i;
3851 break;
3852 }
3853 }
3854 if (markerItemIndex < 0)
3855 return;
3856
3857 const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
3858 qreal sizeRemoved = -removalResult.sizeChangesAfterVisiblePos
3859 - (removalResult.countChangeAfterVisibleItems * (averageSize + spacing));
3860
3861 for (int i=markerItemIndex+1; i<visibleItems.size(); i++) {
3862 FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(i));
3863 if (listItem->position() >= viewEndPos)
3864 break;
3865 if (!listItem->transitionScheduledOrRunning()) {
3866 qreal pos = listItem->position();
3867 listItem->setPosition(pos - sizeRemoved);
3868 listItem->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
3869 listItem->setPosition(pos);
3870 }
3871 }
3872}
3873#endif
3874
3984{
3985 return new QQuickListViewAttached(obj);
3986}
3987
3992{
3993 Q_Q(const QQuickListView);
3994 bool ret = true;
3995
3996 QPointF pos = event->points().first().position();
3997 if (!pos.isNull()) {
3998 if (auto header = q->headerItem()) {
3999 if (q->headerPositioning() != QQuickListView::InlineHeader &&
4000 header->contains(q->mapToItem(header, pos)))
4001 ret = false;
4002 }
4003 if (auto footer = q->footerItem()) {
4004 if (q->footerPositioning() != QQuickListView::InlineFooter &&
4005 footer->contains(q->mapToItem(footer, pos)))
4006 ret = false;
4007 }
4008 }
4009
4010 switch (event->type()) {
4013 break;
4014 case QEvent::MouseMove:
4016 break;
4017 default:
4018 break;
4019 }
4020
4021 qCDebug(lcEvents) << q << (ret ? "WANTS" : "DOESN'T want") << event;
4022 return ret;
4023}
4024
4026
4027#include "moc_qquicklistview_p.cpp"
DarwinBluetooth::DeviceInquiryDelegate * m_delegate
bool contains(qreal x, qreal y) const override
FxListItemSG(QQuickItem *i, QQuickListView *v, bool own)
qreal itemPosition() const
QQuickItem * section() const
qreal position() const override
qreal endPosition() const override
void setSize(qreal size)
qreal size() const override
qreal sectionSize() const override
void setSection(QQuickItem *s)
void setPosition(qreal pos, bool immediate=false)
qreal itemSize() const
QQuickListView * view
QQuickItemViewAttached * attached
MutableModelIterator(QQmlInstanceModel *model, int iBegin, int iEnd)
\inmodule QtCore
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ MouseMove
Definition qcoreevent.h:63
@ MouseButtonPress
Definition qcoreevent.h:60
@ TouchUpdate
Definition qcoreevent.h:242
void setX(qreal x)
qreal y() const
This convenience function is equivalent to calling pos().y().
qreal x() const
This convenience function is equivalent to calling pos().x().
void setVisible(bool visible)
If visible is true, the item is made visible.
void setY(qreal y)
The QKeyEvent class describes a key event.
Definition qevent.h:423
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
void removeAt(qsizetype i)
Definition qlist.h:573
const T & constLast() const noexcept
Definition qlist.h:633
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:471
bool removeOne(const AT &t)
Definition qlist.h:581
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
value_type takeFirst()
Definition qlist.h:549
const_iterator constBegin() const noexcept
Definition qlist.h:615
value_type takeLast()
Definition qlist.h:550
void prepend(rvalue_ref t)
Definition qlist.h:456
const T & constFirst() const noexcept
Definition qlist.h:630
void removeLast() noexcept
Definition qlist.h:808
void append(parameter_type t)
Definition qlist.h:441
const_iterator constEnd() const noexcept
Definition qlist.h:616
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
T take(const Key &key)
Removes the item with the key from the hash and returns the value associated with it.
Definition qhash.h:1541
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
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
\inmodule QtCore\reentrant
Definition qpoint.h:214
A base class for pointer events.
Definition qevent.h:73
\inmodule QtCore
Definition qpointer.h:18
The QQmlChangeSet class stores an ordered list of notifications about changes to a linear data set.
const QVector< Change > & removes() const
const QVector< Change > & inserts() const
static QQmlComponentPrivate * get(QQmlComponent *c)
The QQmlComponent class encapsulates a QML component definition.
bool isBound() const
Returns true if the component was created in a QML files that specifies {pragma ComponentBehavior: Bo...
virtual QObject * beginCreate(QQmlContext *)
Create an object instance from this component, within the specified context.
virtual void completeCreate()
This method provides advanced control over component instance creation.
QQmlContext * creationContext() const
Returns the QQmlContext the component was created in.
void setInitialProperties(QObject *component, const QVariantMap &properties)
Set top-level properties of the component.
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
QQmlContext * parentContext() const
Return the context's parent QQmlContext, or \nullptr if this context has no parent or if the parent h...
static QQmlContext * contextForObject(const QObject *)
Returns the QQmlContext for the object, or nullptr if no context has been set.
IncubationMode
Specifies the mode the incubator operates in.
virtual void setWatchedRoles(const QList< QByteArray > &roles)=0
void modelUpdated(const QQmlChangeSet &changeSet, bool reset)
QString stringValue(int index, const QString &role)
The QQmlProperty class abstracts accessing properties on objects created from QML.
virtual bool flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QQuickTimeLineCallback::Callback fixupCallback, QEvent::Type eventType, qreal velocity)
qreal overShootDistance(qreal velocity) const
virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent)
QQuickFlickable::FlickableDirection flickableDirection
QQuickFlickable::BoundsBehavior boundsBehavior
void setContentWidth(qreal)
virtual void viewportMoved(Qt::Orientations orient)
void setFlickableDirection(FlickableDirection)
virtual qreal maxXExtent() const
virtual qreal maxYExtent() const
void setContentHeight(qreal)
void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types)
void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types)
static QQuickItemPrivate * get(QQuickItem *item)
void setSections(const QString &prev, const QString &sect, const QString &next)
void setView(QQuickItemView *view)
void setSection(const QString &sect)
void setPrevSection(const QString &sect)
void setNextSection(const QString &sect)
QMultiHash< QQmlChangeSet::MoveKey, FxViewItem * > removedItems
QPointer< QQuickItem > item
virtual qreal position() const =0
void setVisible(bool visible)
virtual qreal endPosition() const =0
void moveTo(const QPointF &pos, bool immediate)
virtual qreal size() const =0
virtual bool contains(qreal x, qreal y) const =0
int findLastVisibleIndex(int defaultValue=-1) const
virtual void initializeCurrentItem()
FxViewItem * visibleItem(int modelIndex) const
virtual void clear(bool onDestruction=false)
QQuickItem * createHighlightItem() const
QPointer< QQmlInstanceModel > model
QList< FxViewItem * > visibleItems
virtual void initializeViewItem(FxViewItem *)
virtual void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
QQmlComponent * footerComponent
QQuickItemViewChangeSet currentChanges
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &) override
QQuickItemView::VerticalLayoutDirection verticalLayoutDirection
int mapFromModel(int modelIndex) const
QQuickItem * createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault=false) const
void releaseVisibleItems(QQmlInstanceModel::ReusableFlag reusableFlag)
FxViewItem * createItem(int modelIndex, QQmlIncubator::IncubationMode incubationMode=QQmlIncubator::AsynchronousIfNested)
QQmlComponent * headerComponent
virtual bool releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag)
QQmlInstanceModel::ReusableFlag reusableFlag
std::unique_ptr< FxViewItem > highlight
virtual void setHighlightFollowsCurrentItem(bool)
qreal maxYExtent() const override
qreal maxXExtent() const override
qreal minYExtent() const override
void setContentX(qreal pos) override
Qt::LayoutDirection effectiveLayoutDirection
void setContentY(qreal pos) override
virtual void initItem(int index, QObject *item)
virtual void setHighlightMoveDuration(int)
void setCurrentIndex(int idx)
VerticalLayoutDirection verticalLayoutDirection
qreal minXExtent() const override
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
virtual void keyPressEvent(QKeyEvent *event)
This event handler can be reimplemented in a subclass to receive key press events for an item.
qreal x
\qmlproperty real QtQuick::Item::x \qmlproperty real QtQuick::Item::y \qmlproperty real QtQuick::Item...
Definition qquickitem.h:73
void setParentItem(QQuickItem *parent)
qreal z
\qmlproperty real QtQuick::Item::z
Definition qquickitem.h:75
qreal y
Defines the item's y position relative to its parent.
Definition qquickitem.h:74
void setHeight(qreal)
qreal width
This property holds the width of this item.
Definition qquickitem.h:76
void setVisible(bool)
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
qreal height
This property holds the height of this item.
Definition qquickitem.h:77
void setZ(qreal)
void setWidth(qreal)
void setX(qreal)
void setY(qreal)
QPointer< QQuickItem > m_sectionItem
void releaseSectionItem(QQuickItem *item)
void createHighlight(bool onDestruction=false) override
void visibleItemsChanged() override
bool hasStickyHeader() const override
static void setSectionHelper(QQmlContext *context, QQuickItem *sectionItem, const QString &section)
FxViewItem * snapItemAt(qreal pos)
QQuickListView::Orientation orient
void updateInlineSection(FxListItemSG *)
void updateSections() override
qreal originPosition() const override
QQuickListView::FooterPositioning footerPositioning
void fixupPosition() override
QString sectionAt(int modelIndex)
void updateSectionCriteria() override
qreal snapPosAt(qreal pos)
void initializeComponentItem(QQuickItem *item) const override
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) override
void updateHeader() override
void layoutVisibleItems(int fromModelIndex=0) override
static const int sectionCacheSize
qreal endPositionAt(int index) const override
void updateHighlight() override
void setPosition(qreal pos) override
qreal lastPosition() const override
bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) override
void adjustFirstItem(qreal forwards, qreal backwards, int) override
QQuickItem * currentSectionItem
void repositionPackageItemAt(QQuickItem *item, int index) override
void fixup(AxisData &data, qreal minExtent, qreal maxExtent) override
bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList< FxViewItem * > *addedItems, QList< MovedItem > *movingIntoView) override
void changedVisibleIndex(int newIndex) override
QQuickViewSection * sectionCriteria
bool releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag) override
bool showFooterForIndex(int index) const override
FxViewItem * newViewItem(int index, QQuickItem *item) override
void resetHighlightPosition() override
qreal footerSize() const override
bool wantsPointerEvent(const QPointerEvent *event) override
Qt::Orientation layoutOrientation() const override
void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) override
bool showHeaderForIndex(int index) const override
void initializeCurrentItem() override
std::unique_ptr< QSmoothedAnimation > highlightHeightAnimator
QQuickListView::HeaderPositioning headerPositioning
void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult) override
void initializeViewItem(FxViewItem *item) override
bool hasStickyFooter() const override
qreal positionAt(int index) const override
bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QQuickTimeLineCallback::Callback fixupCallback, QEvent::Type eventType, qreal velocity) override
std::unique_ptr< QSmoothedAnimation > highlightWidthAnimator
void updateFooter() override
FxViewItem * itemBefore(int modelIndex) const
QQuickItem * sectionCache[sectionCacheSize]
QQuickItemViewAttached * getAttachedObject(const QObject *object) const override
bool movingFromHighlight() override
void resetFirstItemPosition(qreal pos=0.0) override
bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) override
QQuickItem * getSectionItem(const QString &section)
void removeItem(FxViewItem *item)
bool isContentFlowReversed() const override
QQuickListView::SnapMode snapMode
qreal headerSize() const override
std::unique_ptr< QSmoothedAnimation > highlightPosAnimator
void clear(bool onDestruction) override
void setOrientation(Orientation)
QQuickListView(QQuickItem *parent=nullptr)
\qmltype ListView \instantiates QQuickListView \inqmlmodule QtQuick\inherits Flickable
void spacingChanged()
void viewportMoved(Qt::Orientations orient) override
\qmlproperty Transition QtQuick::ListView::populate
void highlightMoveVelocityChanged()
void setHighlightMoveDuration(int) override
void highlightResizeDurationChanged()
void orientationChanged()
qreal highlightResizeVelocity
void keyPressEvent(QKeyEvent *) override
This event handler can be reimplemented in a subclass to receive key press events for an item.
FINALFooterPositioning footerPositioning
void setFooterPositioning(FooterPositioning positioning)
void setHighlightResizeDuration(int)
void setSnapMode(SnapMode mode)
void setSpacing(qreal spacing)
qreal maxYExtent() const override
void highlightResizeVelocityChanged()
qreal maxXExtent() const override
void incrementCurrentIndex()
\qmlmethod QtQuick::ListView::incrementCurrentIndex()
void setHighlightResizeVelocity(qreal)
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void setHighlightFollowsCurrentItem(bool) override
\qmlattachedproperty bool QtQuick::ListView::isCurrentItem \readonly
HeaderPositioning headerPositioning
void decrementCurrentIndex()
\qmlmethod QtQuick::ListView::decrementCurrentIndex()
void snapModeChanged()
void setHeaderPositioning(HeaderPositioning positioning)
static QQuickListViewAttached * qmlAttachedProperties(QObject *)
\qmlmethod QtQuick::ListView::positionViewAtIndex(int index, PositionMode mode)
void setHighlightMoveVelocity(qreal)
QQuickViewSection * sectionCriteria()
\qmlproperty enumeration QtQuick::ListView::layoutDirection This property holds the layout direction ...
Orientation orientation
void reset(QQuickTimeLineValue &)
Cancel (but don't complete) all scheduled actions for timeLineValue.
int accel(QQuickTimeLineValue &, qreal velocity, qreal accel)
Decelerate timeLineValue from the starting velocity to zero at the given acceleration rate.
void callback(const QQuickTimeLineCallback &)
Execute the event.
int accelDistance(QQuickTimeLineValue &, qreal velocity, qreal distance)
Decelerate timeLineValue from the starting velocity to zero over the given distance.
void set(QQuickTimeLineValue &, qreal)
Set the value of timeLineValue.
void move(QQuickTimeLineValue &, qreal destination, int time=500)
Linearly change the timeLineValue from its current value to the given destination value over time mil...
void updated()
Emitted each time the timeline modifies QQuickTimeLineValues.
int duration() const override
void setDelegate(QQmlComponent *delegate)
QQuickViewSection(QQuickListView *parent=nullptr)
void labelPositioningChanged()
void setProperty(const QString &)
SectionCriteria criteria
QString sectionString(const QString &value)
QQmlComponent * delegate
void setCriteria(SectionCriteria)
void setLabelPositioning(int pos)
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:658
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:655
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
QString section(QChar sep, qsizetype start, qsizetype end=-1, SectionFlags flags=SectionDefault) const
This function returns a section of the string.
Definition qstring.h:1139
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
QByteArray toUtf8() const &
Definition qstring.h:563
b clear()
qreal spacing
cache insert(employee->id(), employee)
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ LeftToRight
@ RightToLeft
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
@ Key_Right
Definition qnamespace.h:674
@ Key_Left
Definition qnamespace.h:672
@ Key_Up
Definition qnamespace.h:673
@ Key_Down
Definition qnamespace.h:675
@ CaseInsensitive
static void * context
static QDBusError::ErrorType get(const char *name)
static const qint64 headerSize
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:303
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:243
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
return ret
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
n void setPosition(void) \n\
GLint GLfloat GLfloat GLfloat v2
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLint GLsizei GLsizei height
GLfloat GLfloat GLfloat GLfloat GLfloat maxY
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum GLenum GLsizei count
GLfloat minY
GLenum GLuint buffer
GLint GLsizei width
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint y
GLfloat GLfloat GLfloat GLfloat maxX
struct _cl_event * event
GLhandleARB obj
[2]
GLfloat bias
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLdouble s
[6]
Definition qopenglext.h:235
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
QObject * qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc func, bool create)
Definition qqml.cpp:110
void QQml_setParent_noEvent(QObject *object, QObject *parent)
Makes the object a child of parent.
QQuickItem * qmlobject_cast< QQuickItem * >(QObject *object)
static QQuickAttachedPropertyPropagator * attachedObject(const QMetaObject *type, QObject *object, bool create=false)
const qreal _q_MinimumFlickVelocity
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:483
#define QML_FLICK_SNAPONETHRESHOLD
static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, const QPointF &point)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:92
const char property[13]
Definition qwizard.cpp:101
QSqlQueryModel * model
[16]
std::uniform_real_distribution dist(1, 2.5)
[2]
QObject::connect nullptr
QGraphicsItem * item
MoveKey moveKey(int index) const
QQmlNullableValue< qreal > visiblePos
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent