Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
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:
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 }
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
293 void setPosition(qreal pos, bool immediate = false, bool resetInactiveAxis = true) {
294 // position the section immediately even if there is a transition
295 if (section()) {
298 section()->setY(-section()->height()-pos);
299 else
300 section()->setY(pos);
301 } else {
303 section()->setX(-section()->width()-pos);
304 else
305 section()->setX(pos);
306 }
307 }
308 moveTo(pointForPosition(pos, resetInactiveAxis), immediate);
309 }
310
314 else
316 }
317 bool contains(qreal x, qreal y) const override {
318 return (x >= itemX() && x < itemX() + itemWidth() &&
319 y >= itemY() && y < itemY() + itemHeight());
320 }
321
323
324private:
325 QPointF pointForPosition(qreal pos, bool resetInactiveAxis) const {
328 if (section())
329 pos += section()->height();
330 return QPointF(resetInactiveAxis ? 0 : itemX(), -itemHeight() - pos);
331 } else {
332 if (section())
333 pos += section()->height();
334 return QPointF(resetInactiveAxis ? 0 : itemX(), pos);
335 }
336 } else {
338 if (section())
339 pos += section()->width();
340 return QPointF(-itemWidth() - pos, resetInactiveAxis ? 0 : itemY());
341 } else {
342 if (section())
343 pos += section()->width();
344 return QPointF(pos, resetInactiveAxis ? 0 : itemY());
345 }
346 }
347 }
348};
349
373public:
376 , backwards(iEnd < iBegin)
377 {
379 [&] (const QQmlChangeSet &changeSet, bool /*reset*/)
380 {
381 for (const QQmlChangeSet::Change &rem : changeSet.removes()) {
382 idxEnd -= rem.count;
383 if (rem.start() <= index) {
384 index -= rem.count;
385 if (index < rem.start() + rem.count)
386 removedAtIndex = true; // model index was removed
387 }
388 }
389 for (const QQmlChangeSet::Change &ins : changeSet.inserts()) {
390 idxEnd += ins.count;
391 if (ins.start() <= index)
392 index += ins.count;
393 }
394 }
395 );
396 index = iBegin;
397 idxEnd = iEnd;
398 }
399
400 bool hasNext() const {
401 return backwards ? index > idxEnd : index < idxEnd;
402 }
403
404 void next() { index += (backwards ? -1 : +1); }
405
407 {
408 disconnect();
409 }
410
412 {
413 if (conn) {
415 conn = QMetaObject::Connection(); // set to nullptr
416 }
417 }
418 int index = 0;
420 unsigned removedAtIndex : 1;
421 unsigned backwards : 1;
422private:
424};
425
426
427//----------------------------------------------------------------------------
428
433
438
440{
441 Q_Q(const QQuickListView);
442 return orient == QQuickListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
443}
444
449
450// Returns the item before modelIndex, if created.
451// May return an item marked for removal.
453{
454 if (modelIndex < visibleIndex)
455 return nullptr;
456 int idx = 1;
457 int lastIndex = -1;
458 while (idx < visibleItems.size()) {
460 if (item->index != -1)
461 lastIndex = item->index;
462 if (item->index == modelIndex)
463 return visibleItems.at(idx-1);
464 ++idx;
465 }
466 if (lastIndex == modelIndex-1)
467 return visibleItems.constLast();
468 return nullptr;
469}
470
472{
473 Q_Q(QQuickListView);
475 if (isBottomToTop())
476 q->QQuickFlickable::setContentY(-pos-size());
477 else
478 q->QQuickFlickable::setContentY(pos);
479 } else {
480 if (isRightToLeft())
481 q->QQuickFlickable::setContentX(-pos-size());
482 else
483 q->QQuickFlickable::setContentX(pos);
484 }
485}
486
488{
489 qreal pos = 0;
490 if (!visibleItems.isEmpty()) {
492 if (visibleIndex > 0)
494 }
495 return pos;
496}
497
499{
500 qreal pos = 0;
501 if (!visibleItems.isEmpty()) {
502 int invisibleCount = INT_MIN;
503 int delayRemovedCount = 0;
504 for (int i = visibleItems.size()-1; i >= 0; --i) {
506 if (item->index != -1) {
507 // Find the invisible count after the last visible item with known index
508 invisibleCount = model->count() - (item->index + 1 + delayRemovedCount);
509 break;
510 } else if (item->attached->delayRemove()) {
511 ++delayRemovedCount;
512 }
513 }
514 if (invisibleCount == INT_MIN) {
515 // All visible items are in delayRemove state
516 invisibleCount = model->count();
517 }
518 pos = (*(visibleItems.constEnd() - 1))->endPosition();
519 if (invisibleCount > 0)
520 pos += invisibleCount * (averageSize + spacing);
521 } else if (model && model->count()) {
522 pos = (model->count() * averageSize + (model->count()-1) * spacing);
523 }
524 return pos;
525}
526
528{
529 if (FxViewItem *item = visibleItem(modelIndex)) {
530 return item->position();
531 }
532 if (!visibleItems.isEmpty()) {
533 if (modelIndex < visibleIndex) {
534 int count = visibleIndex - modelIndex;
535 qreal cs = 0;
536 if (modelIndex == currentIndex && currentItem) {
537 cs = currentItem->size() + spacing;
538 --count;
539 }
540 return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
541 } else {
542 int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
543 return (*(visibleItems.constEnd() - 1))->endPosition() + spacing + count * (averageSize + spacing);
544 }
545 }
546 return 0;
547}
548
550{
551 if (FxViewItem *item = visibleItem(modelIndex))
552 return item->endPosition();
553 if (!visibleItems.isEmpty()) {
554 if (modelIndex < visibleIndex) {
555 int count = visibleIndex - modelIndex;
556 return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing;
557 } else {
558 int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
559 return (*(visibleItems.constEnd() - 1))->endPosition() + count * (averageSize + spacing);
560 }
561 }
562 return 0;
563}
564
566{
567 if (FxViewItem *item = visibleItem(modelIndex))
568 return item->attached->section();
569
570 QString section;
571 if (sectionCriteria && modelIndex >= 0 && modelIndex < itemCount) {
572 QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
573 section = sectionCriteria->sectionString(propValue);
574 }
575
576 return section;
577}
578
580{
581 if (FxListItemSG *snapItem = static_cast<FxListItemSG*>(snapItemAt(pos)))
582 return snapItem->itemPosition();
583 if (visibleItems.size()) {
584 qreal firstPos = (*visibleItems.constBegin())->position();
585 qreal endPos = (*(visibleItems.constEnd() - 1))->position();
586 if (pos < firstPos) {
587 return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
588 } else if (pos > endPos)
589 return endPos + qRound((pos - endPos) / averageSize) * averageSize;
590 }
592}
593
595{
597 FxViewItem *snapItem = nullptr;
598 FxViewItem *prevItem = nullptr;
599 qreal prevItemSize = 0;
600 for (FxViewItem *item : std::as_const(visibleItems)) {
601 if (item->index == -1)
602 continue;
603
604 const FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
605 qreal itemTop = listItem->position();
606 qreal itemSize = listItem->size();
607 if (highlight && itemTop >= pos && listItem->endPosition() <= pos + highlight->size())
608 return item;
609
610 if (listItem->section() && velocity > 0) {
611 if (itemTop + listItem->sectionSize() / 2 >= pos && itemTop - prevItemSize / 2 < pos)
612 snapItem = prevItem;
613 itemTop = listItem->itemPosition();
614 itemSize = listItem->itemSize();
615 }
616
617 // Middle of item and spacing (i.e. the middle of the distance between this item and the next
618 qreal halfwayToNextItem = itemTop + (itemSize+spacing) / 2;
619 qreal halfwayToPrevItem = itemTop - (prevItemSize+spacing) / 2;
620 if (halfwayToNextItem >= pos && halfwayToPrevItem < pos)
621 snapItem = item;
622
623 prevItemSize = listItem->itemSize();
624 prevItem = item;
625 }
626 return snapItem;
627}
628
630{
631 visiblePos = positionAt(newIndex);
632 visibleIndex = newIndex;
633}
634
640
641void QQuickListViewPrivate::clear(bool onDestruction)
642{
643 for (int i = 0; i < sectionCacheSize; ++i) {
644 delete sectionCache[i];
645 sectionCache[i] = nullptr;
646 }
647 visiblePos = 0;
649 currentSectionItem = nullptr;
651 nextSectionItem = nullptr;
653 QQuickItemViewPrivate::clear(onDestruction);
654}
655
657{
658 Q_Q(QQuickListView);
659
660 FxListItemSG *listItem = new FxListItemSG(item, q, false);
661 listItem->index = modelIndex;
662
663 // initialise attached properties
664 if (sectionCriteria) {
665 QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
666 QString section = sectionCriteria->sectionString(propValue);
667 QString prevSection;
669 if (modelIndex > 0) {
670 if (FxViewItem *item = itemBefore(modelIndex))
671 prevSection = item->attached->section();
672 else
673 prevSection = sectionAt(modelIndex-1);
674 }
675 if (modelIndex < model->count()-1) {
676 nextSection = sectionAt(modelIndex+1);
677 }
678 listItem->attached->setSections(prevSection, section, nextSection);
679 }
680
681 return listItem;
682}
683
685{
687
688 // need to track current items that are animating
689 item->trackGeometry(true);
690
692 if (QString::compare(item->attached->m_prevSection, item->attached->m_section, Qt::CaseInsensitive))
693 updateInlineSection(static_cast<FxListItemSG*>(item));
694 }
695}
696
698{
699 if (!item || !model)
701
702 QPointer<QQuickItem> it = item->item;
703 QQuickListViewAttached *att = static_cast<QQuickListViewAttached*>(item->attached);
704
706 if (released && it && att && att->m_sectionItem) {
707 QQuickItemPrivate::get(att->m_sectionItem)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
708
709 // We hold no more references to this item
710 int i = 0;
711 do {
712 if (!sectionCache[i]) {
714 sectionCache[i]->setVisible(false);
715 att->m_sectionItem = nullptr;
716 break;
717 }
718 ++i;
719 } while (i < sectionCacheSize);
720 delete att->m_sectionItem;
721 att->m_sectionItem = nullptr;
722 }
723
724 return released;
725}
726
727bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
728{
729 qreal itemEnd = visiblePos;
730 if (visibleItems.size()) {
732 itemEnd = (*(visibleItems.constEnd() - 1))->endPosition() + spacing;
733 }
734
735 int modelIndex = findLastVisibleIndex();
736 bool haveValidItems = modelIndex >= 0;
737 modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
738
739 if (haveValidItems && (bufferFrom > itemEnd+averageSize+spacing
740 || bufferTo < visiblePos - averageSize - spacing)) {
741 // We've jumped more than a page. Estimate which items are now
742 // visible and fill from there.
743 int count = (fillFrom - itemEnd) / (averageSize + spacing);
744 int newModelIdx = qBound(0, modelIndex + count, model->count());
745 count = newModelIdx - modelIndex;
746 if (count) {
748 modelIndex = newModelIdx;
749 visibleIndex = modelIndex;
750 visiblePos = itemEnd + count * (averageSize + spacing);
751 itemEnd = visiblePos;
752 }
753 }
754
756
757 bool changed = false;
758 FxListItemSG *item = nullptr;
759 qreal pos = itemEnd;
760 while (modelIndex < model->count() && pos <= fillTo) {
761 if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, incubationMode))))
762 break;
763 qCDebug(lcItemViewDelegateLifecycle) << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
764#if QT_CONFIG(quick_viewtransitions)
765 if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
766#endif
767 item->setPosition(pos, true);
768 if (item->item)
769 QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
770 pos += item->size() + spacing;
772 ++modelIndex;
773 changed = true;
774 }
775
776 if (doBuffer && requestedIndex != -1) // already waiting for an item
777 return changed;
778
779 while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
780 if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, incubationMode))))
781 break;
782 qCDebug(lcItemViewDelegateLifecycle) << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer << "item" << (QObject *)(item->item);
783 --visibleIndex;
784 visiblePos -= item->size() + spacing;
785#if QT_CONFIG(quick_viewtransitions)
786 if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
787#endif
788 item->setPosition(visiblePos, true);
789 if (item->item)
790 QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
792 changed = true;
793 }
794
795 return changed;
796}
797
799{
800#if QT_CONFIG(quick_viewtransitions)
801 if (item->transitionScheduledOrRunning()) {
802 qCDebug(lcItemViewDelegateLifecycle) << "\tnot releasing animating item" << item->index << (QObject *)(item->item);
803 item->releaseAfterTransition = true;
804 releasePendingTransition.append(item);
805 } else
806#endif
807 {
808 qCDebug(lcItemViewDelegateLifecycle) << "\treleasing stationary item" << item->index << (QObject *)(item->item);
810 }
811}
812
814{
815 FxViewItem *item = nullptr;
816 bool changed = false;
817
818 // Remove items from the start of the view.
819 // Zero-sized items shouldn't be removed unless a non-zero-sized item is also being
820 // removed, otherwise a zero-sized item is infinitely added and removed over and
821 // over by refill().
822 int index = 0;
823 while (visibleItems.size() > 1 && index < visibleItems.size()
824 && (item = visibleItems.at(index)) && item->endPosition() < bufferFrom) {
825 if (item->attached->delayRemove())
826 break;
827
828 if (item->size() > 0) {
829 qCDebug(lcItemViewDelegateLifecycle) << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
830 // remove this item and all zero-sized items before it
831 while (item) {
832 if (item->index != -1)
833 visibleIndex++;
836 if (index == 0)
837 break;
839 }
840 changed = true;
841 } else {
842 index++;
843 }
844 }
845
846 while (visibleItems.size() > 1 && (item = visibleItems.constLast()) && item->position() > bufferTo) {
847 if (item->attached->delayRemove())
848 break;
849 qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.size()-1 << item->position() << (QObject *)(item->item);
852 changed = true;
853 }
854
855 return changed;
856}
857
871
873{
874 if (!visibleItems.isEmpty()) {
877
878 FxListItemSG *firstItem = static_cast<FxListItemSG *>(visibleItems.constFirst());
879 bool fixedCurrent = currentItem && firstItem->item == currentItem->item;
880
881#if QT_CONFIG(quick_viewtransitions)
882 /* Set position of first item in list view when populate transition is configured, as it doesn't set
883 while adding visible item (addVisibleItem()) to the view */
884 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true))
885 resetFirstItemPosition(isContentFlowReversed() ? -firstItem->position()-firstItem->size() : firstItem->position());
886#endif
887
888 firstVisibleItemPosition = firstItem->position();
889 qreal sum = firstItem->size();
890 qreal pos = firstItem->position() + firstItem->size() + spacing;
891 firstItem->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
892
893 // setPosition will affect the position of the item, and its section, if it has one.
894 // This will prevent them from potentially overlapping.
895 if (firstItem->section())
896 firstItem->setPosition(firstItem->position());
897
898 for (int i=1; i < visibleItems.size(); ++i) {
899 FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
900 if (item->index >= fromModelIndex) {
901 item->setPosition(pos);
902 item->setVisible(item->endPosition() >= from && item->position() <= to);
903 }
904 pos += item->size() + spacing;
905 sum += item->size();
906 fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
907 }
909
910 // move current item if it is not a visible item.
911 if (currentIndex >= 0 && currentItem && !fixedCurrent)
913
916 }
917}
918
920{
921 static_cast<FxListItemSG *>(item)->setPosition(positionAt(index) + sizeBuffer);
922}
923
925{
926 Q_Q(QQuickListView);
927 qreal pos = position();
929 if (item->y() + item->height() > pos && item->y() < pos + q->height()) {
930 if (isBottomToTop())
931 item->setY(-positionAt(index)-item->height());
932 else
934 }
935 } else {
936 if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
937 if (isRightToLeft())
938 item->setX(-positionAt(index)-item->width());
939 else
941 }
942 }
943}
944
950
952{
953 if (!visibleItems.size())
954 return;
955 qreal diff = forwards - backwards;
957}
958
964
966{
967 bool changed = false;
968 if (highlight) {
969 if (trackedItem == highlight.get())
970 trackedItem = nullptr;
971 highlight.reset();
972
973 highlightPosAnimator.reset();
976 highlightPosAnimator = nullptr;
977 highlightWidthAnimator = nullptr;
978 highlightHeightAnimator = nullptr;
979
980 changed = true;
981 }
982
983 if (onDestruction)
984 return;
985
986 Q_Q(QQuickListView);
987 if (currentItem) {
989 if (item) {
990 std::unique_ptr<FxListItemSG> newHighlight
991 = std::make_unique<FxListItemSG>(item, q, true);
992 newHighlight->trackGeometry(true);
993
994 if (autoHighlight) {
995 newHighlight->setSize(static_cast<FxListItemSG*>(currentItem)->itemSize());
996 newHighlight->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition());
997 }
998 const QLatin1String posProp(orient == QQuickListView::Vertical ? "y" : "x");
999 highlightPosAnimator = std::make_unique<QSmoothedAnimation>();
1000 highlightPosAnimator->target = QQmlProperty(item, posProp);
1003
1004 highlightWidthAnimator = std::make_unique<QSmoothedAnimation>();
1008
1009 highlightHeightAnimator = std::make_unique<QSmoothedAnimation>();
1013
1014 highlight = std::move(newHighlight);
1015 changed = true;
1016 }
1017 }
1018 if (changed)
1019 emit q->highlightItemChanged();
1020}
1021
1023{
1025
1026 if ((!currentItem && highlight) || (currentItem && !highlight))
1029 if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
1030 // auto-update highlight
1031 FxListItemSG *listItem = static_cast<FxListItemSG*>(currentItem);
1033 ? -listItem->itemPosition()-listItem->itemSize()
1034 : listItem->itemPosition();
1035 highlightWidthAnimator->to = listItem->item->width();
1036 highlightHeightAnimator->to = listItem->item->height();
1038 if (highlight->item->width() == 0)
1039 highlight->item->setWidth(currentItem->item->width());
1040 } else {
1041 if (highlight->item->height() == 0)
1042 highlight->item->setHeight(currentItem->item->height());
1043 }
1044
1045 highlightPosAnimator->restart();
1046 highlightWidthAnimator->restart();
1047 highlightHeightAnimator->restart();
1048 }
1050}
1051
1053{
1054 if (highlight && currentItem) {
1055 static_cast<FxListItemSG*>(highlight.get())->setPosition(
1056 static_cast<FxListItemSG*>(currentItem)->itemPosition());
1057 }
1058}
1059
1069
1070
1072{
1073 Q_Q(QQuickListView);
1074 QQuickItem *sectionItem = nullptr;
1075 int i = sectionCacheSize-1;
1076 while (i >= 0 && !sectionCache[i])
1077 --i;
1078 if (i >= 0) {
1079 sectionItem = sectionCache[i];
1080 sectionCache[i] = nullptr;
1081 sectionItem->setVisible(true);
1082 QQmlContext *context = QQmlEngine::contextForObject(sectionItem)->parentContext();
1083 setSectionHelper(context, sectionItem, section);
1084 } else {
1085 QQmlComponent* delegate = sectionCriteria->delegate();
1086 const bool reuseExistingContext = delegate->isBound();
1087 auto delegatePriv = QQmlComponentPrivate::get(delegate);
1088 QQmlPropertyCache::ConstPtr rootPropertyCache;
1089
1090 QQmlContext *creationContext = sectionCriteria->delegate()->creationContext();
1091 auto baseContext = creationContext ? creationContext : qmlContext(q);
1092 // if we need to insert a context property, we need a separate context
1093 QQmlContext *context = reuseExistingContext ? baseContext : new QQmlContext(baseContext);
1094 QObject *nobj = delegate->beginCreate(context);
1095 if (nobj) {
1096 if (delegatePriv->hadTopLevelRequiredProperties()) {
1097 delegate->setInitialProperties(nobj, {{QLatin1String("section"), section}});
1098 } else if (!reuseExistingContext) {
1099 context->setContextProperty(QLatin1String("section"), section);
1100 }
1101 if (!reuseExistingContext)
1103 sectionItem = qobject_cast<QQuickItem *>(nobj);
1104 if (!sectionItem) {
1105 delete nobj;
1106 } else {
1107 if (qFuzzyIsNull(sectionItem->z()))
1108 sectionItem->setZ(2);
1109 QQml_setParent_noEvent(sectionItem, contentItem);
1110 sectionItem->setParentItem(contentItem);
1111 }
1112 // sections are not controlled by FxListItemSG, so apply attached properties here
1113 QQuickItemViewAttached *attached = static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(sectionItem));
1114 attached->setView(q);
1115 } else if (!reuseExistingContext) {
1116 delete context;
1117 }
1119 }
1120
1121 if (sectionItem)
1122 QQuickItemPrivate::get(sectionItem)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
1123
1124 return sectionItem;
1125}
1126
1128{
1129 if (!item)
1130 return;
1131 int i = 0;
1132
1133 QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
1134
1135 do {
1136 if (!sectionCache[i]) {
1137 sectionCache[i] = item;
1138 sectionCache[i]->setVisible(false);
1139 return;
1140 }
1141 ++i;
1142 } while (i < sectionCacheSize);
1143 delete item;
1144}
1145
1146
1148{
1149 for (FxViewItem *item : std::as_const(visibleItems)) {
1150 FxListItemSG *listItem = static_cast<FxListItemSG *>(item);
1151 if (listItem->section()) {
1152 qreal pos = listItem->position();
1153 releaseSectionItem(listItem->section());
1154 listItem->setSection(nullptr);
1155 listItem->setPosition(pos);
1156 }
1157 }
1158 for (int i = 0; i < sectionCacheSize; ++i) {
1159 delete sectionCache[i];
1160 sectionCache[i] = nullptr;
1161 }
1162}
1163
1165{
1167 return;
1168 if (QString::compare(listItem->attached->m_prevSection, listItem->attached->m_section, Qt::CaseInsensitive)
1170 || (listItem->index == 0 && sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart))) {
1171 if (!listItem->section()) {
1172 qreal pos = listItem->position();
1173 listItem->setSection(getSectionItem(listItem->attached->m_section));
1174 listItem->setPosition(pos);
1175 } else {
1176 QQmlContext *context = QQmlEngine::contextForObject(listItem->section())->parentContext();
1177 setSectionHelper(context, listItem->section(), listItem->attached->m_section);
1178 }
1179 } else if (listItem->section()) {
1180 qreal pos = listItem->position();
1181 releaseSectionItem(listItem->section());
1182 listItem->setSection(nullptr);
1183 listItem->setPosition(pos);
1184 }
1185}
1186
1188{
1191 return;
1192
1193 bool isFlowReversed = isContentFlowReversed();
1194 qreal viewPos = isFlowReversed ? -position()-size() : position();
1195 qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
1196 qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
1197
1198 QQuickItem *sectionItem = nullptr;
1199 QQuickItem *lastSectionItem = nullptr;
1200 int index = 0;
1201 while (index < visibleItems.size()) {
1202 if (QQuickItem *section = static_cast<FxListItemSG *>(visibleItems.at(index))->section()) {
1203 // Find the current section header and last visible section header
1204 // and hide them if they will overlap a static section header.
1205 qreal sectionPos = orient == QQuickListView::Vertical ? section->y() : section->x();
1206 qreal sectionSize = orient == QQuickListView::Vertical ? section->height() : section->width();
1207 bool visTop = true;
1209 visTop = isFlowReversed ? -sectionPos-sectionSize >= startPos : sectionPos >= startPos;
1210 bool visBot = true;
1212 visBot = isFlowReversed ? -sectionPos <= endPos : sectionPos + sectionSize < endPos;
1213 section->setVisible(visBot && visTop);
1214 if (visTop && !sectionItem)
1215 sectionItem = section;
1216 if (isFlowReversed) {
1217 if (-sectionPos <= endPos)
1218 lastSectionItem = section;
1219 } else {
1220 if (sectionPos + sectionSize < endPos)
1221 lastSectionItem = section;
1222 }
1223 }
1224 ++index;
1225 }
1226
1227 // Current section header
1229 if (!currentSectionItem) {
1234 }
1236 if (!currentSectionItem)
1237 return;
1238
1241
1242 currentSectionItem->setVisible(!atBeginning && (!header || hasStickyHeader() || header->endPosition() < viewPos));
1243 qreal pos = isFlowReversed ? position() + size() - sectionSize : startPos;
1244 if (header)
1245 pos = isFlowReversed ? qMin(-header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
1246 if (sectionItem) {
1247 qreal sectionPos = orient == QQuickListView::Vertical ? sectionItem->y() : sectionItem->x();
1248 pos = isFlowReversed ? qMax(pos, sectionPos + sectionSize) : qMin(pos, sectionPos - sectionSize);
1249 }
1250 if (footer)
1251 pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
1254 else
1256 } else if (currentSectionItem) {
1258 currentSectionItem = nullptr;
1259 }
1260
1261 // Next section footer
1263 if (!nextSectionItem) {
1268 }
1270 if (!nextSectionItem)
1271 return;
1272
1275 qreal pos = isFlowReversed ? position() : endPos - sectionSize;
1276 if (footer)
1277 pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
1278 if (lastSectionItem) {
1279 qreal sectionPos = orient == QQuickListView::Vertical ? lastSectionItem->y() : lastSectionItem->x();
1280 pos = isFlowReversed ? qMin(pos, sectionPos - sectionSize) : qMax(pos, sectionPos + sectionSize);
1281 }
1282 if (header)
1283 pos = isFlowReversed ? qMin(-header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
1286 else
1288 } else if (nextSectionItem) {
1290 nextSectionItem = nullptr;
1291 }
1292}
1293
1295{
1296 Q_Q(QQuickListView);
1297 if (!q->isComponentComplete())
1298 return;
1299
1301
1303 QString prevSection;
1304 if (visibleIndex > 0)
1305 prevSection = sectionAt(visibleIndex-1);
1306 QQuickListViewAttached *prevAtt = nullptr;
1307 int prevIdx = -1;
1308 int idx = -1;
1309 for (FxViewItem *item : std::as_const(visibleItems)) {
1310 QQuickListViewAttached *attached = static_cast<QQuickListViewAttached*>(item->attached);
1311 attached->setPrevSection(prevSection);
1312 if (item->index != -1) {
1313 QString propValue = model->stringValue(item->index, sectionCriteria->property());
1314 attached->setSection(sectionCriteria->sectionString(propValue));
1315 idx = item->index;
1316 }
1317 updateInlineSection(static_cast<FxListItemSG*>(item));
1318 if (prevAtt)
1319 prevAtt->setNextSection(sectionAt(prevIdx+1));
1320 prevSection = attached->section();
1321 prevAtt = attached;
1322 prevIdx = item->index;
1323 }
1324 if (prevAtt) {
1325 if (idx > 0 && idx < model->count()-1)
1326 prevAtt->setNextSection(sectionAt(idx+1));
1327 else
1328 prevAtt->setNextSection(QString());
1329 }
1330 }
1331
1333}
1334
1336{
1337 Q_Q(QQuickListView);
1339 if (!currentSection.isEmpty()) {
1341 emit q->currentSectionChanged();
1342 }
1343 return;
1344 }
1346 qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
1347 qreal startPos = hasStickyHeader() ? header->endPosition() : viewPos;
1348 int index = 0;
1349 int modelIndex = visibleIndex;
1350 while (index < visibleItems.size()) {
1352 if (item->endPosition() > startPos)
1353 break;
1354 if (item->index != -1)
1355 modelIndex = item->index;
1356 ++index;
1357 }
1358
1359 QString newSection = currentSection;
1360 if (index < visibleItems.size())
1361 newSection = visibleItems.at(index)->attached->section();
1362 else
1363 newSection = (*visibleItems.constBegin())->attached->section();
1364 if (newSection != currentSection) {
1365 currentSection = newSection;
1367 emit q->currentSectionChanged();
1368 }
1369
1371 // Don't want to scan for next section on every movement, so remember
1372 // the last section in the visible area and only scan for the next
1373 // section when that changes. Clearing lastVisibleSection will also
1374 // force searching.
1375 QString lastSection = currentSection;
1376 qreal endPos = hasStickyFooter() ? footer->position() : viewPos + size();
1377 if (nextSectionItem && !inlineSections)
1379 while (index < visibleItems.size()) {
1380 FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(index));
1381 if (listItem->itemPosition() >= endPos)
1382 break;
1383 if (listItem->index != -1)
1384 modelIndex = listItem->index;
1385 lastSection = listItem->attached->section();
1386 ++index;
1387 }
1388
1389 if (lastVisibleSection != lastSection) {
1390 nextSection = QString();
1391 lastVisibleSection = lastSection;
1392 for (int i = modelIndex; i < itemCount; ++i) {
1393 QString section = sectionAt(i);
1394 if (section != lastSection) {
1395 nextSection = section;
1397 break;
1398 }
1399 }
1400 }
1401 }
1402}
1403
1405{
1407
1408 if (currentItem) {
1409 FxListItemSG *listItem = static_cast<FxListItemSG *>(currentItem);
1410
1411 // don't reposition the item if it is already in the visibleItems list
1412 FxViewItem *actualItem = visibleItem(currentIndex);
1413 if (!actualItem) {
1414 if (currentIndex == visibleIndex - 1 && visibleItems.size()) {
1415 // We can calculate exact postion in this case
1416 listItem->setPosition(visibleItems.constFirst()->position() - currentItem->size() - spacing);
1417 } else {
1418 // Create current item now and position as best we can.
1419 // Its position will be corrected when it becomes visible.
1420 listItem->setPosition(positionAt(currentIndex));
1421 }
1422 }
1423
1424 if (visibleItems.isEmpty())
1425 averageSize = listItem->size();
1426 }
1427}
1428
1430{
1431 if (!visibleItems.size())
1432 return;
1433 qreal sum = 0.0;
1434 for (FxViewItem *item : std::as_const(visibleItems))
1435 sum += item->size();
1437}
1438
1440{
1441 return header ? header->size() : 0.0;
1442}
1443
1445{
1446 return footer ? footer->size() : 0.0;
1447}
1448
1450{
1451 return index == 0;
1452}
1453
1455{
1456 return model && index == model->count()-1;
1457}
1458
1460{
1461 Q_Q(QQuickListView);
1462 bool created = false;
1463 if (!footer) {
1465 if (!item)
1466 return;
1467 footer = new FxListItemSG(item, q, true);
1468 footer->trackGeometry(true);
1469 created = true;
1470 }
1471
1472 FxListItemSG *listItem = static_cast<FxListItemSG*>(footer);
1474 listItem->setPosition(isContentFlowReversed() ? -position() - footerSize() : position() + size() - footerSize(), false, false);
1475 } else if (visibleItems.size()) {
1477 qreal viewPos = isContentFlowReversed() ? -position() : position() + size();
1478 // using qBound() would throw an assert here, because max < min is a valid case
1479 // here, if the list's delegates do not fill the whole view
1480 qreal clampedPos = qMax(originPosition() - footerSize() + size(), qMin(listItem->position(), lastPosition()));
1481 listItem->setPosition(qBound(viewPos - footerSize(), clampedPos, viewPos), false, false);
1482 } else {
1483 qreal endPos = lastPosition();
1484 if (findLastVisibleIndex() == model->count()-1) {
1485 listItem->setPosition(endPos, false, false);
1486 } else {
1487 qreal visiblePos = position() + q->height();
1488 if (endPos <= visiblePos || listItem->position() < endPos)
1489 listItem->setPosition(endPos, false, false);
1490 }
1491 }
1492 } else {
1493 listItem->setPosition(visiblePos, false, false);
1494 }
1495
1496 if (created)
1497 emit q->footerItemChanged();
1498}
1499
1505
1507{
1508 FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
1509 const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
1511 int fixupDura = timeline.duration();
1512 if (fixupDura < 0)
1513 fixupDura = fixupDuration/2;
1514 const int t = timeline.time();
1515
1516 const qreal progress = qreal(t)/fixupDura;
1518 const qreal headerPosition = fixupHeaderPosition * (1 - progress) + ultimateHeaderPosition * progress;
1519 const qreal viewPos = isContentFlowReversed() ? -position() - size() : position();
1520 const qreal clampedPos = qBound(originPosition() - headerSize(), headerPosition, lastPosition() - size());
1521 listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos));
1522 }
1523}
1524
1526{
1527 Q_Q(QQuickListView);
1528 bool created = false;
1529 if (!header) {
1531 if (!item)
1532 return;
1533 header = new FxListItemSG(item, q, true);
1534 header->trackGeometry(true);
1535 created = true;
1536 }
1537
1538 FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
1540 listItem->setPosition(isContentFlowReversed() ? -position() - size() : position(), false, false);
1541 } else if (visibleItems.size()) {
1542 const bool fixingUp = (orient == QQuickListView::Vertical ? vData : hData).fixingUp;
1544 qreal headerPosition = listItem->position();
1545 const qreal viewPos = isContentFlowReversed() ? -position() - size() : position();
1546 // Make sure the header is not shown if we absolutely do not have any plans to show it
1547 if (fixingUp && !headerNeedsSeparateFixup)
1548 headerPosition = viewPos - headerSize();
1549 // using qBound() would throw an assert here, because max < min is a valid case
1550 // here, if the list's delegates do not fill the whole view
1551 qreal clampedPos = qMax(originPosition() - headerSize(), qMin(headerPosition, lastPosition() - size()));
1552 listItem->setPosition(qBound(viewPos - headerSize(), clampedPos, viewPos), false, false);
1553 } else {
1554 qreal startPos = originPosition();
1555 if (visibleIndex == 0) {
1556 listItem->setPosition(startPos - headerSize(), false, false);
1557 } else {
1558 if (position() <= startPos || listItem->position() > startPos - headerSize())
1559 listItem->setPosition(startPos - headerSize(), false, false);
1560 }
1561 }
1562 } else {
1563 listItem->setPosition(-headerSize(), false, false);
1564 }
1565
1566 if (created)
1567 emit q->headerItemChanged();
1568}
1569
1574
1579
1581{
1582 QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
1583 qmlAttachedPropertiesObject<QQuickListView>(item));
1584 if (attached) // can be null for default components (see createComponentItem)
1585 attached->setView(const_cast<QQuickListView*>(q_func()));
1586}
1587
1589 const QRectF &oldGeometry)
1590{
1591 Q_Q(QQuickListView);
1592
1594 if (!q->isComponentComplete())
1595 return;
1596
1597 if (currentItem && currentItem->item == item) {
1598 const bool contentFlowReversed = isContentFlowReversed();
1599 const qreal pos = position();
1600 const qreal sz = size();
1601 const qreal from = contentFlowReversed ? -pos - displayMarginBeginning - sz : pos - displayMarginBeginning;
1602 const qreal to = contentFlowReversed ? -pos + displayMarginEnd : pos + sz + displayMarginEnd;
1604 }
1605
1606 if (item != contentItem && (!highlight || item != highlight->item)) {
1607 if ((orient == QQuickListView::Vertical && change.heightChange())
1608 || (orient == QQuickListView::Horizontal && change.widthChange())) {
1609
1610 // if visibleItems.first() has resized, adjust its pos since it is used to
1611 // position all subsequent items
1613 FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.constFirst());
1614#if QT_CONFIG(quick_viewtransitions)
1615 if (listItem->transitionScheduledOrRunning())
1616 return;
1617#endif
1619 const qreal oldItemEndPosition = verticalLayoutDirection == QQuickItemView::BottomToTop ? -oldGeometry.y() : oldGeometry.y() + oldGeometry.height();
1620 const qreal heightDiff = item->height() - oldGeometry.height();
1621 if (verticalLayoutDirection == QQuickListView::TopToBottom && oldItemEndPosition < q->contentY())
1622 listItem->setPosition(listItem->position() - heightDiff, true);
1623 else if (verticalLayoutDirection == QQuickListView::BottomToTop && oldItemEndPosition > q->contentY())
1624 listItem->setPosition(listItem->position() + heightDiff, true);
1625 } else {
1626 const qreal oldItemEndPosition = q->effectiveLayoutDirection() == Qt::RightToLeft ? -oldGeometry.x() : oldGeometry.x() + oldGeometry.width();
1627 const qreal widthDiff = item->width() - oldGeometry.width();
1628 if (q->effectiveLayoutDirection() == Qt::LeftToRight && oldItemEndPosition < q->contentX())
1629 listItem->setPosition(listItem->position() - widthDiff, true);
1630 else if (q->effectiveLayoutDirection() == Qt::RightToLeft && oldItemEndPosition > q->contentX())
1631 listItem->setPosition(listItem->position() + widthDiff, true);
1632 }
1633 }
1635 }
1636 }
1637}
1638
1640{
1642 fixupY();
1643 else
1644 fixupX();
1645}
1646
1648{
1652 return;
1653 } else if (orient == QQuickListView::Vertical && &data == &hData) {
1656 return;
1657 }
1658
1659 // update footer if all visible items have been removed
1660 if (visibleItems.size() == 0)
1661 updateFooter();
1662
1663 correctFlick = false;
1666
1667 qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
1668
1670 qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
1672 // if we've been dragged < averageSize/2 then bias towards the next item
1673 qreal dist = data.move.value() - data.pressPos;
1674 qreal bias = 0;
1675 if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2)
1676 bias = averageSize/2;
1677 else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2)
1678 bias = -averageSize/2;
1680 bias = -bias;
1681 tempPosition -= bias;
1682 }
1683
1684 qreal snapOffset = 0;
1685 qreal overlayHeaderOffset = 0;
1686 bool isHeaderWithinBounds = false;
1687 if (header) {
1688 qreal visiblePartOfHeader = header->position() + header->size() - tempPosition;
1689 isHeaderWithinBounds = visiblePartOfHeader > 0;
1690 switch (headerPositioning) {
1692 snapOffset = header->size();
1693 overlayHeaderOffset = header->size();
1694 break;
1696 if (isHeaderWithinBounds && tempPosition < originPosition())
1697 // For the inline header, we want to snap to the first item
1698 // if we're more than halfway down the inline header.
1699 // So if we look for an item halfway down of the header
1700 snapOffset = header->size() / 2;
1701 break;
1703 desiredHeaderVisible = visiblePartOfHeader > header->size()/2;
1704 if (qFuzzyCompare(header->position(), tempPosition)) {
1705 // header was pulled down; make sure it remains visible and snap items to bottom of header
1706 snapOffset = header->size();
1707 } else if (desiredHeaderVisible) {
1708 // More than 50% of the header is shown. Show it fully.
1709 // Scroll the view so the next item snaps to the header.
1710 snapOffset = header->size();
1711 overlayHeaderOffset = header->size();
1712 }
1713 break;
1714 }
1715 }
1716 FxViewItem *topItem = snapItemAt(tempPosition + snapOffset + highlightRangeStart);
1717 if (strictHighlightRange && currentItem && (!topItem || (topItem->index != currentIndex && fixupMode == Immediate))) {
1718 // StrictlyEnforceRange always keeps an item in range
1720 topItem = currentItem;
1721 }
1722 FxViewItem *bottomItem = snapItemAt(tempPosition + snapOffset + highlightRangeEnd);
1723 if (strictHighlightRange && currentItem && (!bottomItem || (bottomItem->index != currentIndex && fixupMode == Immediate))) {
1724 // StrictlyEnforceRange always keeps an item in range
1726 bottomItem = currentItem;
1727 }
1728 qreal pos = 0;
1729 bool isInBounds = -position() > maxExtent && -position() <= minExtent;
1730
1731 if (header && !topItem && isInBounds) {
1732 // We are trying to pull back further than needed
1733 switch (headerPositioning) {
1735 pos = startPosition() - overlayHeaderOffset;
1736 break;
1739 break;
1742 break;
1743 }
1744 } else if (topItem && (isInBounds || strictHighlightRange)) {
1745 if (topItem->index == 0 && header && !hasStickyHeader() && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) {
1747 } else {
1749 // We pulled down the header. If it isn't pulled all way down, we need to snap
1750 // the header.
1751 if (qFuzzyCompare(tempPosition, header->position())) {
1752 // It is pulled all way down. Scroll-snap the content, but not the header.
1754 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + snapOffset;
1755 else
1756 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - snapOffset;
1757 } else {
1758 // Header is not pulled all way down, make it completely visible or hide it.
1759 // Depends on how much of the header is visible.
1761 // More than half of the header is visible - show it.
1762 // Scroll so that the topItem is aligned to a fully visible header
1764 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + headerSize();
1765 else
1766 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - headerSize();
1767 } else {
1768 // Less than half is visible - hide the header. Scroll so
1769 // that the topItem is aligned to the top of the view
1771 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size();
1772 else
1773 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart;
1774 }
1775 }
1776
1777 headerNeedsSeparateFixup = isHeaderWithinBounds || desiredHeaderVisible;
1779 // We need to animate the header independently if it starts visible or should end as visible,
1780 // since the header should not necessarily follow the content.
1781 // Store the desired viewport position.
1782 // Also store the header position so we know where to animate the header from (fixupHeaderPosition).
1783 // We deduce the desired header position from the desiredViewportPosition variable.
1786
1787 FxListItemSG *headerItem = static_cast<FxListItemSG*>(header);
1788 fixupHeaderPosition = headerItem->position();
1789
1790 // follow the same fixup timeline
1793 }
1794 } else if (isContentFlowReversed()) {
1795 pos = -static_cast<FxListItemSG*>(topItem)->itemPosition() + highlightRangeStart - size() + overlayHeaderOffset;
1796 } else {
1797 pos = static_cast<FxListItemSG*>(topItem)->itemPosition() - highlightRangeStart - overlayHeaderOffset;
1798 }
1799 }
1800 } else if (bottomItem && isInBounds) {
1802 pos = -static_cast<FxListItemSG*>(bottomItem)->itemPosition() + highlightRangeEnd - size() + overlayHeaderOffset;
1803 else
1804 pos = static_cast<FxListItemSG*>(bottomItem)->itemPosition() - highlightRangeEnd - overlayHeaderOffset;
1805 } else {
1807 return;
1808 }
1810
1811 qreal dist = qAbs(data.move + pos);
1812 if (dist >= 0) {
1813 // Even if dist == 0 we still start the timeline, because we use the same timeline for
1814 // moving the header. And we might need to move the header while the content does not
1815 // need moving
1816 timeline.reset(data.move);
1817 if (fixupMode != Immediate) {
1819 data.fixingUp = true;
1820 } else {
1821 timeline.set(data.move, -pos);
1822 }
1823 vTime = timeline.time();
1824 }
1825 } else if (currentItem && strictHighlightRange && moveReason != QQuickListViewPrivate::SetIndex) {
1827 qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
1828 if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd)
1829 viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd;
1830 if (viewPos > pos - highlightRangeStart)
1831 viewPos = pos - highlightRangeStart;
1833 viewPos = -viewPos-size();
1834
1835 timeline.reset(data.move);
1836 if (viewPos != position()) {
1837 if (fixupMode != Immediate) {
1838 if (fixupMode == ExtentChanged && data.fixingUp)
1840 else
1842 data.fixingUp = true;
1843 } else {
1844 timeline.set(data.move, -viewPos);
1845 }
1846 }
1847 vTime = timeline.time();
1848 } else {
1850 }
1851 data.inOvershoot = false;
1852 fixupMode = Normal;
1853}
1854
1855bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
1856 QQuickTimeLineCallback::Callback fixupCallback, QEvent::Type eventType, qreal velocity)
1857{
1858 data.fixingUp = false;
1859 moveReason = Mouse;
1861 correctFlick = true;
1862 return QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, eventType, velocity);
1863 }
1864 qreal maxDistance = 0;
1865 const qreal dataValue =
1866 isContentFlowReversed() ? -data.move.value() + size() : data.move.value();
1867
1868 // -ve velocity means list is moving up/left
1869 if (velocity > 0) {
1870 if (data.move.value() < minExtent) {
1872 // averageSize/2 + 1 - next item
1873 qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
1875 bias = -bias;
1876 data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
1877 maxDistance = qAbs(data.flickTarget - data.move.value());
1878 velocity = maxVelocity;
1879 } else {
1880 maxDistance = qAbs(minExtent - data.move.value());
1881 }
1882 }
1884 data.flickTarget = minExtent;
1885 } else {
1886 if (data.move.value() > maxExtent) {
1888 // averageSize/2 + 1 - next item
1889 qreal bias = averageSize / 2 + 1 - (pressed ? data.pressPos : 0);
1891 bias = -bias;
1892 data.flickTarget =
1894 maxDistance = qAbs(data.flickTarget - data.move.value());
1895 velocity = -maxVelocity;
1896 } else {
1897 maxDistance = qAbs(maxExtent - data.move.value());
1898 }
1899 }
1901 data.flickTarget = maxExtent;
1902 }
1904 if (maxDistance > 0 || overShoot) {
1905 // These modes require the list to stop exactly on an item boundary.
1906 // The initial flick will estimate the boundary to stop on.
1907 // Since list items can have variable sizes, the boundary will be
1908 // reevaluated and adjusted as we approach the boundary.
1909 qreal v = velocity;
1910 if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1911 if (v < 0)
1912 v = -maxVelocity;
1913 else
1914 v = maxVelocity;
1915 }
1916 if (!hData.flicking && !vData.flicking) {
1917 // the initial flick - estimate boundary
1918 qreal accel = eventType == QEvent::Wheel ? wheelDeceleration : deceleration;
1919 qreal v2 = v * v;
1920 overshootDist = 0.0;
1921 // + averageSize/4 to encourage moving at least one item in the flick direction
1922 qreal dist = v2 / (accel * 2.0) + averageSize/4;
1923 if (maxDistance > 0)
1924 dist = qMin(dist, maxDistance);
1925 if (v > 0)
1926 dist = -dist;
1927 if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QQuickListView::SnapOneItem) {
1929 qreal distTemp = isContentFlowReversed() ? -dist : dist;
1930 data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + distTemp) + highlightRangeStart;
1931 }
1932 data.flickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
1933 if (overShoot) {
1934 if (data.flickTarget > minExtent) {
1936 data.flickTarget += overshootDist;
1937 } else if (data.flickTarget < maxExtent) {
1939 data.flickTarget -= overshootDist;
1940 }
1941 }
1942 qreal adjDist = -data.flickTarget + data.move.value();
1943 if (qAbs(adjDist) > qAbs(dist)) {
1944 // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
1945 qreal adjv2 = accel * 2.0f * qAbs(adjDist);
1946 if (adjv2 > v2) {
1947 v2 = adjv2;
1948 v = qSqrt(v2);
1949 if (dist > 0)
1950 v = -v;
1951 }
1952 }
1953 dist = adjDist;
1954 accel = v2 / (2.0f * qAbs(dist));
1955 } else if (overShoot) {
1956 data.flickTarget = data.move.value() - dist;
1957 if (data.flickTarget > minExtent) {
1959 data.flickTarget += overshootDist;
1960 } else if (data.flickTarget < maxExtent) {
1962 data.flickTarget -= overshootDist;
1963 }
1964 }
1965 timeline.reset(data.move);
1966 timeline.accel(data.move, v, accel, maxDistance + overshootDist);
1967 timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
1968 correctFlick = true;
1969 return true;
1970 } else {
1971 // reevaluate the target boundary.
1972 qreal newtarget = data.flickTarget;
1974 qreal tempFlickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
1975 newtarget = -snapPosAt(-(tempFlickTarget - highlightRangeStart)) + highlightRangeStart;
1976 newtarget = isContentFlowReversed() ? -newtarget+size() : newtarget;
1977 }
1978 if (velocity < 0 && newtarget <= maxExtent)
1979 newtarget = maxExtent - overshootDist;
1980 else if (velocity > 0 && newtarget >= minExtent)
1981 newtarget = minExtent + overshootDist;
1982 if (newtarget == data.flickTarget) { // boundary unchanged - nothing to do
1983 if (qAbs(velocity) < _q_MinimumFlickVelocity)
1984 correctFlick = false;
1985 return false;
1986 }
1987 data.flickTarget = newtarget;
1988 qreal dist = -newtarget + data.move.value();
1989 if ((v < 0 && dist < 0) || (v > 0 && dist > 0)) {
1990 correctFlick = false;
1991 timeline.reset(data.move);
1993 return false;
1994 }
1995 timeline.reset(data.move);
1996 timeline.accelDistance(data.move, v, -dist);
1997 timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
1998 return false;
1999 }
2000 } else {
2001 correctFlick = false;
2002 timeline.reset(data.move);
2004 return false;
2005 }
2006}
2007
2009{
2010 if (!QQmlContextData::get(context)->isInternal() && context->contextProperty(QLatin1String("section")).isValid())
2011 context->setContextProperty(QLatin1String("section"), section);
2012 else
2013 sectionItem->setProperty("section", section);
2014}
2015
2017{
2018 QObject *attachedObject = qmlAttachedPropertiesObject<QQuickListView>(object);
2019 return static_cast<QQuickItemViewAttached *>(attachedObject);
2020}
2021
2022//----------------------------------------------------------------------------
2023
2252
2256
2496//###Possibly rename these properties, since they are very useful even without a highlight?
2526{
2527 Q_D(QQuickListView);
2528 if (d->autoHighlight != autoHighlight) {
2529 if (!autoHighlight) {
2530 if (d->highlightPosAnimator)
2531 d->highlightPosAnimator->stop();
2532 if (d->highlightWidthAnimator)
2533 d->highlightWidthAnimator->stop();
2534 if (d->highlightHeightAnimator)
2535 d->highlightHeightAnimator->stop();
2536 }
2538 }
2539}
2540
2549{
2550 Q_D(const QQuickListView);
2551 return d->spacing;
2552}
2553
2555{
2556 Q_D(QQuickListView);
2557 if (spacing != d->spacing) {
2558 d->spacing = spacing;
2559 d->forceLayoutPolish();
2561 }
2562}
2563
2580{
2581 Q_D(const QQuickListView);
2582 return d->orient;
2583}
2584
2586{
2587 Q_D(QQuickListView);
2588 if (d->orient != orientation) {
2589 d->orient = orientation;
2590 if (d->orient == Vertical) {
2591 if (d->flickableDirection == HorizontalFlick) {
2593 if (isComponentComplete())
2594 setContentWidth(-1);
2595 }
2596 setContentX(0);
2597 } else {
2598 if (d->flickableDirection == VerticalFlick) {
2600 if (isComponentComplete())
2601 setContentHeight(-1);
2602 }
2603 setContentY(0);
2604 }
2605 d->regenerate(true);
2607 }
2608}
2609
2807{
2808 Q_D(QQuickListView);
2809 if (!d->sectionCriteria)
2810 d->sectionCriteria = new QQuickViewSection(this);
2811 return d->sectionCriteria;
2812}
2813
2819{
2820 Q_D(const QQuickListView);
2821 return d->currentSection;
2822}
2823
2861{
2862 Q_D(const QQuickListView);
2863 return d->highlightMoveVelocity;
2864}
2865
2867{
2868 Q_D(QQuickListView);
2869 if (d->highlightMoveVelocity != speed) {
2870 d->highlightMoveVelocity = speed;
2871 if (d->highlightPosAnimator)
2872 d->highlightPosAnimator->velocity = d->highlightMoveVelocity;
2874 }
2875}
2876
2878{
2879 Q_D(QQuickListView);
2880 if (d->highlightMoveDuration != duration) {
2881 if (d->highlightPosAnimator)
2882 d->highlightPosAnimator->userDuration = duration;
2884 }
2885}
2886
2888{
2889 Q_D(const QQuickListView);
2890 return d->highlightResizeVelocity;
2891}
2892
2894{
2895 Q_D(QQuickListView);
2896 if (d->highlightResizeVelocity != speed) {
2897 d->highlightResizeVelocity = speed;
2898 if (d->highlightWidthAnimator)
2899 d->highlightWidthAnimator->velocity = d->highlightResizeVelocity;
2900 if (d->highlightHeightAnimator)
2901 d->highlightHeightAnimator->velocity = d->highlightResizeVelocity;
2903 }
2904}
2905
2907{
2908 Q_D(const QQuickListView);
2909 return d->highlightResizeDuration;
2910}
2911
2913{
2914 Q_D(QQuickListView);
2915 if (d->highlightResizeDuration != duration) {
2916 d->highlightResizeDuration = duration;
2917 if (d->highlightWidthAnimator)
2918 d->highlightWidthAnimator->userDuration = d->highlightResizeDuration;
2919 if (d->highlightHeightAnimator)
2920 d->highlightHeightAnimator->userDuration = d->highlightResizeDuration;
2922 }
2923}
2924
2947{
2948 Q_D(const QQuickListView);
2949 return d->snapMode;
2950}
2951
2953{
2954 Q_D(QQuickListView);
2955 if (d->snapMode != mode) {
2956 d->snapMode = mode;
2958 d->fixupPosition();
2959 }
2960}
2961
2962
3035{
3036 Q_D(const QQuickListView);
3037 return d->headerPositioning;
3038}
3039
3041{
3042 Q_D(QQuickListView);
3043 if (d->headerPositioning != positioning) {
3044 d->applyPendingChanges();
3045 d->headerPositioning = positioning;
3046 if (isComponentComplete()) {
3047 d->updateHeader();
3048 d->updateViewport();
3049 d->fixupPosition();
3050 }
3051 emit headerPositioningChanged();
3052 }
3053}
3054
3082{
3083 Q_D(const QQuickListView);
3084 return d->footerPositioning;
3085}
3086
3088{
3089 Q_D(QQuickListView);
3090 if (d->footerPositioning != positioning) {
3091 d->applyPendingChanges();
3092 d->footerPositioning = positioning;
3093 if (isComponentComplete()) {
3094 d->updateFooter();
3095 d->updateViewport();
3096 d->fixupPosition();
3097 }
3098 emit footerPositioningChanged();
3099 }
3100}
3101
3404void QQuickListView::viewportMoved(Qt::Orientations orient)
3405{
3406 Q_D(QQuickListView);
3408
3409 if (!d->itemCount) {
3410 if (d->hasStickyHeader())
3411 d->updateHeader();
3412 if (d->hasStickyFooter())
3413 d->updateFooter();
3414 return;
3415 }
3416
3417 // Recursion can occur due to refill changing the content size.
3418 if (d->inViewportMoved)
3419 return;
3420 d->inViewportMoved = true;
3421
3422 if (yflick()) {
3423 if (d->isBottomToTop())
3424 d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
3425 else
3426 d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
3427 } else {
3428 if (d->isRightToLeft())
3429 d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
3430 else
3431 d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
3432 }
3433
3434 d->refillOrLayout();
3435
3436 // Set visibility of items to eliminate cost of items outside the visible area.
3437 qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
3438 qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
3439 for (FxViewItem *item : std::as_const(d->visibleItems)) {
3440 if (item->item)
3441 QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
3442 }
3443 if (d->currentItem)
3444 QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to);
3445
3446 if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
3447 d->moveReason = QQuickListViewPrivate::Mouse;
3448 if (d->moveReason != QQuickListViewPrivate::SetIndex) {
3449 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
3450 // reposition highlight
3451 qreal pos = d->highlight->position();
3452 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
3453 if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
3454 pos = viewPos + d->highlightRangeEnd - d->highlight->size();
3455 if (pos < viewPos + d->highlightRangeStart)
3456 pos = viewPos + d->highlightRangeStart;
3457 if (pos != d->highlight->position()) {
3458 d->highlightPosAnimator->stop();
3459 static_cast<FxListItemSG*>(d->highlight.get())->setPosition(pos);
3460 } else {
3461 d->updateHighlight();
3462 }
3463
3464 // update current index
3465 if (FxViewItem *snapItem = d->snapItemAt(d->highlight->position())) {
3466 if (snapItem->index >= 0 && snapItem->index != d->currentIndex)
3467 d->updateCurrent(snapItem->index);
3468 }
3469 }
3470 }
3471
3472 if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) {
3473 d->inFlickCorrection = true;
3474 // Near an end and it seems that the extent has changed?
3475 // Recalculate the flick so that we don't end up in an odd position.
3476 if (yflick() && !d->vData.inOvershoot) {
3477 if (d->vData.velocity > 0) {
3478 const qreal minY = minYExtent();
3479 if ((minY - d->vData.move.value() < height()/2 || d->vData.flickTarget - d->vData.move.value() < height()/2)
3480 && minY != d->vData.flickTarget)
3481 d->flickY(QEvent::TouchUpdate, -d->vData.smoothVelocity.value());
3482 } else if (d->vData.velocity < 0) {
3483 const qreal maxY = maxYExtent();
3484 if ((d->vData.move.value() - maxY < height()/2 || d->vData.move.value() - d->vData.flickTarget < height()/2)
3485 && maxY != d->vData.flickTarget)
3486 d->flickY(QEvent::TouchUpdate, -d->vData.smoothVelocity.value());
3487 }
3488 }
3489
3490 if (xflick() && !d->hData.inOvershoot) {
3491 if (d->hData.velocity > 0) {
3492 const qreal minX = minXExtent();
3493 if ((minX - d->hData.move.value() < width()/2 || d->hData.flickTarget - d->hData.move.value() < width()/2)
3494 && minX != d->hData.flickTarget)
3495 d->flickX(QEvent::TouchUpdate, -d->hData.smoothVelocity.value());
3496 } else if (d->hData.velocity < 0) {
3497 const qreal maxX = maxXExtent();
3498 if ((d->hData.move.value() - maxX < width()/2 || d->hData.move.value() - d->hData.flickTarget < width()/2)
3499 && maxX != d->hData.flickTarget)
3500 d->flickX(QEvent::TouchUpdate, -d->hData.smoothVelocity.value());
3501 }
3502 }
3503 d->inFlickCorrection = false;
3504 }
3505 if (d->hasStickyHeader())
3506 d->updateHeader();
3507 if (d->hasStickyFooter())
3508 d->updateFooter();
3509 if (d->sectionCriteria) {
3510 d->updateCurrentSection();
3511 d->updateStickySections();
3512 }
3513 d->inViewportMoved = false;
3514}
3515
3517{
3518 Q_D(QQuickListView);
3519 if (d->model && d->model->count() && ((d->interactive && !d->explicitKeyNavigationEnabled)
3520 || (d->explicitKeyNavigationEnabled && d->keyNavigationEnabled))) {
3521 if ((d->orient == QQuickListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Left)
3522 || (d->orient == QQuickListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right)
3523 || (d->orient == QQuickListView::Vertical && !d->isBottomToTop() && event->key() == Qt::Key_Up)
3524 || (d->orient == QQuickListView::Vertical && d->isBottomToTop() && event->key() == Qt::Key_Down)) {
3525 if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
3527 event->accept();
3528 return;
3529 } else if (d->wrap) {
3530 event->accept();
3531 return;
3532 }
3533 } else if ((d->orient == QQuickListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Right)
3534 || (d->orient == QQuickListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left)
3535 || (d->orient == QQuickListView::Vertical && !d->isBottomToTop() && event->key() == Qt::Key_Down)
3536 || (d->orient == QQuickListView::Vertical && d->isBottomToTop() && event->key() == Qt::Key_Up)) {
3537 if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
3539 event->accept();
3540 return;
3541 } else if (d->wrap) {
3542 event->accept();
3543 return;
3544 }
3545 }
3546 }
3547 event->ignore();
3549}
3550
3551void QQuickListView::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
3552{
3553 Q_D(QQuickListView);
3554
3555 if (d->model) {
3556 // When the view changes size, we force the pool to
3557 // shrink by releasing all pooled items.
3558 d->model->drainReusableItemsPool(0);
3559 }
3560
3561 if (d->isRightToLeft()) {
3562 // maintain position relative to the right edge
3563 qreal dx = newGeometry.width() - oldGeometry.width();
3564 setContentX(contentX() - dx);
3565 } else if (d->isBottomToTop()) {
3566 // maintain position relative to the bottom edge
3567 qreal dy = newGeometry.height() - oldGeometry.height();
3568 setContentY(contentY() - dy);
3569 }
3570 QQuickItemView::geometryChange(newGeometry, oldGeometry);
3571}
3572
3574{
3576
3577 // setting the view from the FxViewItem wrapper is too late if the delegate
3578 // needs access to the view in Component.onCompleted
3580 if (item) {
3581 QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
3582 qmlAttachedPropertiesObject<QQuickListView>(item));
3583 if (attached)
3584 attached->setView(this);
3585 }
3586}
3587
3589{
3590 Q_D(const QQuickListView);
3591 if (d->layoutOrientation() == Qt::Horizontal && d->flickableDirection != HorizontalFlick)
3594}
3595
3597{
3598 Q_D(const QQuickListView);
3599 if (d->layoutOrientation() == Qt::Vertical && d->flickableDirection != VerticalFlick)
3602}
3603
3614{
3615 Q_D(QQuickListView);
3616 int count = d->model ? d->model->count() : 0;
3617 if (count && (currentIndex() < count - 1 || d->wrap)) {
3618 d->moveReason = QQuickListViewPrivate::SetIndex;
3619 int index = currentIndex()+1;
3620 setCurrentIndex((index >= 0 && index < count) ? index : 0);
3621 }
3622}
3623
3634{
3635 Q_D(QQuickListView);
3636 int count = d->model ? d->model->count() : 0;
3637 if (count && (currentIndex() > 0 || d->wrap)) {
3638 d->moveReason = QQuickListViewPrivate::SetIndex;
3639 int index = currentIndex()-1;
3640 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
3641 }
3642}
3643
3645{
3646 Q_Q(QQuickListView);
3647 if (q->isComponentComplete() && model) {
3648 QList<QByteArray> roles;
3650 roles << sectionCriteria->property().toUtf8();
3651 model->setWatchedRoles(roles);
3653 if (itemCount)
3655 }
3656}
3657
3658bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView)
3659{
3660 Q_Q(QQuickListView);
3661#if QT_CONFIG(quick_viewtransitions)
3662 Q_UNUSED(movingIntoView)
3663#endif
3664 int modelIndex = change.index;
3665 int count = change.count;
3666
3667 if (q->size().isEmpty() && visibleItems.isEmpty())
3668 return false;
3669
3670 qreal tempPos = isContentFlowReversed() ? -position()-size() : position();
3671 int index = visibleItems.size() ? mapFromModel(modelIndex) : 0;
3672 qreal lastVisiblePos = buffer + displayMarginEnd + tempPos + size();
3673
3674 if (index < 0) {
3675 int i = visibleItems.size() - 1;
3676 while (i > 0 && visibleItems.at(i)->index == -1)
3677 --i;
3678 if (i == 0 && visibleItems.constFirst()->index == -1) {
3679 // there are no visible items except items marked for removal
3681 } else if (visibleItems.at(i)->index + 1 == modelIndex
3682 && visibleItems.at(i)->endPosition() <= lastVisiblePos) {
3683 // Special case of appending an item to the model.
3685 } else {
3686 if (modelIndex < visibleIndex) {
3687 // Insert before visible items
3689 for (FxViewItem *item : std::as_const(visibleItems)) {
3690 if (item->index != -1 && item->index >= modelIndex)
3691 item->index += count;
3692 }
3693 }
3694 return true;
3695 }
3696 }
3697
3698 // index can be the next item past the end of the visible items list (i.e. appended)
3699 qreal pos = 0;
3700 if (visibleItems.size()) {
3703 }
3704
3705 // Update the indexes of the following visible items.
3706 for (FxViewItem *item : std::as_const(visibleItems)) {
3707 if (item->index != -1 && item->index >= modelIndex) {
3708 item->index += count;
3709#if QT_CONFIG(quick_viewtransitions)
3710 if (change.isMove())
3711 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
3712 else
3713 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false);
3714#endif
3715 }
3716 }
3717
3718 bool visibleAffected = false;
3719 if (insertResult->visiblePos.isValid() && pos < insertResult->visiblePos) {
3720 // Insert items before the visible item.
3721 int insertionIdx = index;
3722 qreal from = tempPos - displayMarginBeginning - buffer;
3723
3724 if (insertionIdx < visibleIndex) {
3725 if (pos >= from) {
3726 // items won't be visible, just note the size for repositioning
3727 insertResult->sizeChangesBeforeVisiblePos += count * (averageSize + spacing);
3728 }
3729 } else {
3730 MutableModelIterator it(model, modelIndex + count - 1, modelIndex -1);
3731 for (; it.hasNext() && pos >= from; it.next()) {
3732 // item is before first visible e.g. in cache buffer
3733 FxViewItem *item = nullptr;
3734 if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(it.index))))
3735 item->index = it.index;
3736 if (!item)
3738 if (!item)
3739 return false;
3740 if (it.removedAtIndex)
3741 continue;
3742
3743 visibleAffected = true;
3744 visibleItems.insert(insertionIdx, item);
3745 if (insertionIdx == 0)
3746 insertResult->changedFirstItem = true;
3747 if (!change.isMove()) {
3748 addedItems->append(item);
3749#if QT_CONFIG(quick_viewtransitions)
3750 if (transitioner)
3751 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
3752 else
3753#endif
3754 static_cast<FxListItemSG *>(item)->setPosition(pos, true);
3755 }
3756 insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
3757 pos -= item->size() + spacing;
3758 index++;
3759 }
3760 }
3761
3762 int firstOkIdx = -1;
3763 for (int i = 0; i <= insertionIdx && i < visibleItems.size() - 1; i++) {
3764 if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
3765 firstOkIdx = i + 1;
3766 break;
3767 }
3768 }
3769 for (int i = 0; i < firstOkIdx; i++) {
3770 FxViewItem *nvItem = visibleItems.takeFirst();
3771 addedItems->removeOne(nvItem);
3772 removeItem(nvItem);
3773 }
3774
3775 } else {
3776 MutableModelIterator it(model, modelIndex, modelIndex + count);
3777 for (; it.hasNext() && pos <= lastVisiblePos; it.next()) {
3778 visibleAffected = true;
3779 FxViewItem *item = nullptr;
3780 if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(it.index))))
3781 item->index = it.index;
3782#if QT_CONFIG(quick_viewtransitions)
3783 bool newItem = !item;
3784#endif
3785 it.removedAtIndex = false;
3786 if (!item)
3788 if (!item)
3789 return false;
3790 if (it.removedAtIndex) {
3792 continue;
3793 }
3794
3796 if (index == 0)
3797 insertResult->changedFirstItem = true;
3798 if (change.isMove()) {
3799 // we know this is a move target, since move displaced items that are
3800 // shuffled into view due to a move would be added in refill()
3801#if QT_CONFIG(quick_viewtransitions)
3802 if (newItem && transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true))
3803 movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
3804#endif
3805 } else {
3806 addedItems->append(item);
3807#if QT_CONFIG(quick_viewtransitions)
3808 if (transitioner)
3809 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
3810 else
3811#endif
3812 static_cast<FxListItemSG *>(item)->setPosition(pos, true);
3813 }
3814 insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
3815 pos += item->size() + spacing;
3816 ++index;
3817 }
3818 it.disconnect();
3819
3820 if (0 < index && index < visibleItems.size()) {
3821 FxViewItem *prevItem = visibleItems.at(index - 1);
3823 if (prevItem->index != item->index - 1) {
3824 int i = index;
3825#if QT_CONFIG(quick_viewtransitions)
3826 qreal prevPos = prevItem->position();
3827#endif
3828 while (i < visibleItems.size()) {
3829 FxListItemSG *nvItem = static_cast<FxListItemSG *>(visibleItems.takeLast());
3830 insertResult->sizeChangesAfterVisiblePos -= nvItem->size() + spacing;
3831 addedItems->removeOne(nvItem);
3832#if QT_CONFIG(quick_viewtransitions)
3833 if (nvItem->transitionScheduledOrRunning())
3834 nvItem->setPosition(prevPos + (nvItem->index - prevItem->index) * averageSize);
3835#endif
3836 removeItem(nvItem);
3837 }
3838 }
3839 }
3840 }
3841
3843
3844 return visibleAffected;
3845}
3846
3847#if QT_CONFIG(quick_viewtransitions)
3848void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult)
3849{
3850 Q_UNUSED(insertionResult);
3851
3852 if (!transitioner)
3853 return;
3854
3855 int markerItemIndex = -1;
3856 for (int i=0; i<visibleItems.size(); i++) {
3857 if (visibleItems.at(i)->index == afterModelIndex) {
3858 markerItemIndex = i;
3859 break;
3860 }
3861 }
3862 if (markerItemIndex < 0)
3863 return;
3864
3865 const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
3866 qreal sizeRemoved = -removalResult.sizeChangesAfterVisiblePos
3867 - (removalResult.countChangeAfterVisibleItems * (averageSize + spacing));
3868
3869 for (int i=markerItemIndex+1; i<visibleItems.size(); i++) {
3870 FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(i));
3871 if (listItem->position() >= viewEndPos)
3872 break;
3873 if (!listItem->transitionScheduledOrRunning()) {
3874 qreal pos = listItem->position();
3875 listItem->setPosition(pos - sizeRemoved);
3876 listItem->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
3877 listItem->setPosition(pos);
3878 }
3879 }
3880}
3881#endif
3882
3995
4000{
4001 Q_Q(const QQuickListView);
4002 bool ret = true;
4003
4004 QPointF pos = event->points().first().position();
4005 if (!pos.isNull()) {
4006 if (auto header = q->headerItem()) {
4007 if (q->headerPositioning() != QQuickListView::InlineHeader &&
4008 header->contains(q->mapToItem(header, pos)))
4009 ret = false;
4010 }
4011 if (auto footer = q->footerItem()) {
4012 if (q->footerPositioning() != QQuickListView::InlineFooter &&
4013 footer->contains(q->mapToItem(footer, pos)))
4014 ret = false;
4015 }
4016 }
4017
4018 switch (event->type()) {
4021 break;
4022 case QEvent::MouseMove:
4024 break;
4025 default:
4026 break;
4027 }
4028
4029 qCDebug(lcEvents) << q << (ret ? "WANTS" : "DOESN'T want") << event;
4030 return ret;
4031}
4032
4034
4035#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, bool resetInactiveAxis=true)
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:424
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
void removeAt(qsizetype i)
Definition qlist.h:590
const T & constLast() const noexcept
Definition qlist.h:650
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
value_type takeFirst()
Definition qlist.h:566
const_iterator constBegin() const noexcept
Definition qlist.h:632
value_type takeLast()
Definition qlist.h:567
void prepend(rvalue_ref t)
Definition qlist.h:473
const T & constFirst() const noexcept
Definition qlist.h:647
void removeLast() noexcept
Definition qlist.h:815
void append(parameter_type t)
Definition qlist.h:458
const_iterator constEnd() const noexcept
Definition qlist.h:633
\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:1626
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:299
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:328
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
\inmodule QtCore\reentrant
Definition qpoint.h:217
A base class for pointer events.
Definition qevent.h:73
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
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)
static QQuickItemPrivate * get(QQuickItem *item)
void setView(QQuickItemView *view)
void setSection(const QString &sect)
void setPrevSection(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:63
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:72
qreal y
Defines the item's y position relative to its parent.
Definition qquickitem.h:73
void setHeight(qreal)
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
void setVisible(bool)
bool isComponentComplete() const
Returns true if construction of the QML component is complete; otherwise returns false.
QPointF position() const
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
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()
FooterPositioning footerPositioning
qreal highlightResizeVelocity
void initItem(int index, QObject *item) override
void keyPressEvent(QKeyEvent *) override
This event handler can be reimplemented in a subclass to receive key press events for an item.
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:484
constexpr qreal y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:672
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:732
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:729
constexpr qreal x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:669
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
QString section(QChar sep, qsizetype start, qsizetype end=-1, SectionFlags flags=SectionDefault) const
This function returns a section of the string.
Definition qstring.h:1284
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
QByteArray toUtf8() const &
Definition qstring.h:634
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:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ Key_Right
Definition qnamespace.h:679
@ Key_Left
Definition qnamespace.h:677
@ Key_Up
Definition qnamespace.h:678
@ Key_Down
Definition qnamespace.h:680
@ 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:333
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:289
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLint GLsizei width
GLint y
GLfloat GLfloat GLfloat GLfloat maxX
struct _cl_event * event
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat bias
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
QObject * qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc func, bool create)
Definition qqml.cpp:114
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:492
#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:187
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