6#include <QtQml/qqmlcomponent.h>
8#include <QtQuick/private/qquicktransition_p.h>
9#include <QtQml/QQmlInfo>
10#include "qplatformdefs.h"
14Q_LOGGING_CATEGORY(lcItemViewDelegateLifecycle,
"qt.quick.itemview.lifecycle")
15Q_STATIC_LOGGING_CATEGORY(lcCount,
"qt.quick.itemview.count")
18#ifndef QML_VIEW_DEFAULTCACHEBUFFER
19#define QML_VIEW_DEFAULTCACHEBUFFER 320
22FxViewItem::FxViewItem(QQuickItem *i, QQuickItemView *v,
bool own, QQuickItemViewAttached *attached)
23 : QQuickItemViewFxItem(i, own, QQuickItemViewPrivate::get(v))
29QQuickItemViewChangeSet::QQuickItemViewChangeSet()
35bool QQuickItemViewChangeSet::hasPendingChanges()
const
37 return !pendingChanges.isEmpty();
40void QQuickItemViewChangeSet::applyChanges(
const QQmlChangeSet &changeSet)
42 pendingChanges.apply(changeSet);
47 for (
const QQmlChangeSet::Change &r : changeSet.removes()) {
49 if (moveId == -1 && newCurrentIndex >= r.index + r.count) {
50 newCurrentIndex -= r.count;
51 currentChanged =
true;
52 }
else if (moveId == -1 && newCurrentIndex >= r.index && newCurrentIndex < r.index + r.count) {
56 moveOffset = newCurrentIndex - r.index;
58 currentRemoved =
true;
61 newCurrentIndex = qMin(r.index, itemCount - 1);
63 currentChanged =
true;
66 for (
const QQmlChangeSet::Change &i : changeSet.inserts()) {
68 if (itemCount && newCurrentIndex >= i.index) {
69 newCurrentIndex += i.count;
70 currentChanged =
true;
71 }
else if (newCurrentIndex < 0) {
73 currentChanged =
true;
74 }
else if (newCurrentIndex == 0 && !itemCount) {
76 currentChanged =
true;
78 }
else if (moveId == i.moveId) {
79 newCurrentIndex = i.index + moveOffset;
85void QQuickItemViewChangeSet::applyBufferedChanges(
const QQuickItemViewChangeSet &other)
87 if (!other.hasPendingChanges())
90 pendingChanges.apply(other.pendingChanges);
91 itemCount = other.itemCount;
92 newCurrentIndex = other.newCurrentIndex;
93 currentChanged = other.currentChanged;
94 currentRemoved = other.currentRemoved;
97void QQuickItemViewChangeSet::prepare(
int currentIndex,
int count)
104 newCurrentIndex = currentIndex;
107void QQuickItemViewChangeSet::reset()
110 newCurrentIndex = -1;
111 pendingChanges.clear();
112 removedItems.clear();
114 currentChanged =
false;
115 currentRemoved =
false;
120QQuickItemView::QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent)
121 : QQuickFlickable(dd, parent)
127QQuickItemView::~QQuickItemView()
134 QQmlDelegateModelPointer model(d->model);
135 d->disconnectModel(
this, &model);
142QQuickItem *QQuickItemView::currentItem()
const
144 Q_D(
const QQuickItemView);
145 return d->currentItem ? d->currentItem->item :
nullptr;
148QVariant QQuickItemView::model()
const
150 Q_D(
const QQuickItemView);
152 return static_cast<QQmlDelegateModel *>(d->model.data())->model();
154 return QVariant::fromValue(d->model.data());
158void QQuickItemView::setModel(
const QVariant &m)
162 if (model.userType() == qMetaTypeId<QJSValue>())
163 model = model.value<QJSValue>().toVariant();
165 QQmlDelegateModelPointer oldModel(d->model);
167 if (oldModel.delegateModel()->model() == model)
169 }
else if (QVariant::fromValue(d->model) == model) {
173 d->disconnectModel(
this, &oldModel);
177 d->setPosition(d->contentStartOffset());
179 QObject *object = qvariant_cast<QObject *>(model);
181 QQmlDelegateModelPointer newModel(qobject_cast<QQmlInstanceModel *>(object));
183 if (d->explicitDelegate) {
184 QQmlComponent *delegate =
nullptr;
185 if (QQmlDelegateModel *old = oldModel.delegateModel())
186 delegate = old->delegate();
188 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
189 delegateModel->setDelegate(delegate);
190 }
else if (delegate) {
191 qmlWarning(
this) <<
"Cannot retain explicitly set delegate on non-DelegateModel";
192 d->explicitDelegate =
false;
196 if (d->explicitDelegateModelAccess) {
197 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
198 if (QQmlDelegateModel *old = oldModel.delegateModel())
199 access = old->delegateModelAccess();
201 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
202 delegateModel->setDelegateModelAccess(access);
203 }
else if (access != QQmlDelegateModel::Qt5ReadWrite) {
204 qmlWarning(
this) <<
"Cannot retain explicitly set delegate model access "
205 "on non-DelegateModel";
206 d->explicitDelegateModelAccess =
false;
211 delete oldModel.instanceModel();
214 d->model = newModel.instanceModel();
215 }
else if (d->ownModel) {
217 Q_ASSERT(oldModel.delegateModel());
219 d->model = newModel.instanceModel();
220 newModel.delegateModel()->setModel(model);
222 newModel = QQmlDelegateModel::createForView(
this, d);
223 if (d->explicitDelegate) {
224 QQmlComponent *delegate =
nullptr;
225 if (QQmlDelegateModel *old = oldModel.delegateModel())
226 delegate = old->delegate();
227 newModel.delegateModel()->setDelegate(delegate);
230 if (d->explicitDelegateModelAccess) {
231 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
232 if (QQmlDelegateModel *old = oldModel.delegateModel())
233 access = old->delegateModelAccess();
234 newModel.delegateModel()->setDelegateModelAccess(access);
237 newModel.delegateModel()->setModel(model);
240 d->connectModel(
this, &newModel);
242 d->moveReason = QQuickItemViewPrivate::Other;
245QQmlComponent *QQuickItemView::delegate()
const
247 Q_D(
const QQuickItemView);
249 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
250 return dataModel->delegate();
256void QQuickItemView::setDelegate(QQmlComponent *delegate)
259 const auto setExplicitDelegate = [&](QQmlDelegateModel *delegateModel) {
260 int oldCount = delegateModel->count();
261 delegateModel->setDelegate(delegate);
262 if (oldCount != delegateModel->count())
263 d->emitCountChanged();
264 d->explicitDelegate =
true;
265 d->delegateValidated =
false;
271 d->explicitDelegate =
true;
275 setExplicitDelegate(QQmlDelegateModel::createForView(
this, d));
279 emit delegateChanged();
283 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
285 d->explicitDelegate =
false;
286 setExplicitDelegate(delegateModel);
291 qmlWarning(
this) <<
"Cannot set a delegate on an explicitly provided non-DelegateModel";
293 d->explicitDelegate =
true;
297int QQuickItemView::count()
const
299 Q_D(
const QQuickItemView);
302 return d->model->count();
305int QQuickItemView::currentIndex()
const
307 Q_D(
const QQuickItemView);
308 return d->currentIndex;
311void QQuickItemView::setCurrentIndex(
int index)
316 d->currentIndexCleared = (index == -1);
318 d->applyPendingChanges();
319 if (index == d->currentIndex)
321 if (isComponentComplete() && d->isValid()) {
322 d->moveReason = QQuickItemViewPrivate::SetIndex;
323 d->updateCurrent(index);
324 }
else if (d->currentIndex != index) {
325 d->currentIndex = index;
326 emit currentIndexChanged();
331bool QQuickItemView::isWrapEnabled()
const
333 Q_D(
const QQuickItemView);
337void QQuickItemView::setWrapEnabled(
bool wrap)
343 emit keyNavigationWrapsChanged();
346bool QQuickItemView::isKeyNavigationEnabled()
const
348 Q_D(
const QQuickItemView);
349 return d->explicitKeyNavigationEnabled ? d->keyNavigationEnabled : d->interactive;
352void QQuickItemView::setKeyNavigationEnabled(
bool keyNavigationEnabled)
356 const bool wasImplicit = !d->explicitKeyNavigationEnabled;
358 QObject::disconnect(
this, &QQuickFlickable::interactiveChanged,
this, &QQuickItemView::keyNavigationEnabledChanged);
360 d->explicitKeyNavigationEnabled =
true;
363 if (d->keyNavigationEnabled != keyNavigationEnabled || wasImplicit) {
364 d->keyNavigationEnabled = keyNavigationEnabled;
365 emit keyNavigationEnabledChanged();
369int QQuickItemView::cacheBuffer()
const
371 Q_D(
const QQuickItemView);
375void QQuickItemView::setCacheBuffer(
int b)
379 qmlWarning(
this) <<
"Cannot set a negative cache buffer";
383 if (d->buffer != b) {
385 if (isComponentComplete()) {
386 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
389 emit cacheBufferChanged();
393int QQuickItemView::displayMarginBeginning()
const
395 Q_D(
const QQuickItemView);
396 return d->displayMarginBeginning;
399void QQuickItemView::setDisplayMarginBeginning(
int margin)
402 if (d->displayMarginBeginning != margin) {
403 d->displayMarginBeginning = margin;
404 if (isComponentComplete()) {
405 d->forceLayoutPolish();
407 emit displayMarginBeginningChanged();
411int QQuickItemView::displayMarginEnd()
const
413 Q_D(
const QQuickItemView);
414 return d->displayMarginEnd;
417void QQuickItemView::setDisplayMarginEnd(
int margin)
420 if (d->displayMarginEnd != margin) {
421 d->displayMarginEnd = margin;
422 if (isComponentComplete()) {
423 d->forceLayoutPolish();
425 emit displayMarginEndChanged();
429Qt::LayoutDirection QQuickItemView::layoutDirection()
const
431 Q_D(
const QQuickItemView);
432 return d->layoutDirection;
435void QQuickItemView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
438 if (d->layoutDirection != layoutDirection) {
439 d->layoutDirection = layoutDirection;
441 emit layoutDirectionChanged();
442 emit effectiveLayoutDirectionChanged();
446Qt::LayoutDirection QQuickItemView::effectiveLayoutDirection()
const
448 Q_D(
const QQuickItemView);
449 if (d->effectiveLayoutMirror)
450 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
452 return d->layoutDirection;
455QQuickItemView::VerticalLayoutDirection QQuickItemView::verticalLayoutDirection()
const
457 Q_D(
const QQuickItemView);
458 return d->verticalLayoutDirection;
461void QQuickItemView::setVerticalLayoutDirection(VerticalLayoutDirection layoutDirection)
464 if (d->verticalLayoutDirection != layoutDirection) {
465 d->verticalLayoutDirection = layoutDirection;
467 emit verticalLayoutDirectionChanged();
471QQmlComponent *QQuickItemView::header()
const
473 Q_D(
const QQuickItemView);
474 return d->headerComponent;
477QQuickItem *QQuickItemView::headerItem()
const
479 Q_D(
const QQuickItemView);
480 return d->header ? d->header->item :
nullptr;
483void QQuickItemView::setHeader(QQmlComponent *headerComponent)
486 if (d->headerComponent != headerComponent) {
487 d->applyPendingChanges();
490 d->headerComponent = headerComponent;
492 d->markExtentsDirty();
494 if (isComponentComplete()) {
500 emit headerItemChanged();
502 emit headerChanged();
506QQmlComponent *QQuickItemView::footer()
const
508 Q_D(
const QQuickItemView);
509 return d->footerComponent;
512QQuickItem *QQuickItemView::footerItem()
const
514 Q_D(
const QQuickItemView);
515 return d->footer ? d->footer->item :
nullptr;
518void QQuickItemView::setFooter(QQmlComponent *footerComponent)
521 if (d->footerComponent != footerComponent) {
522 d->applyPendingChanges();
525 d->footerComponent = footerComponent;
527 if (isComponentComplete()) {
532 emit footerItemChanged();
534 emit footerChanged();
538QQmlComponent *QQuickItemView::highlight()
const
540 Q_D(
const QQuickItemView);
541 return d->highlightComponent;
544void QQuickItemView::setHighlight(QQmlComponent *highlightComponent)
547 if (highlightComponent != d->highlightComponent) {
548 d->applyPendingChanges();
549 d->highlightComponent = highlightComponent;
550 d->createHighlight();
552 d->updateHighlight();
553 emit highlightChanged();
557QQuickItem *QQuickItemView::highlightItem()
const
559 Q_D(
const QQuickItemView);
560 return d->highlight ? d->highlight->item :
nullptr;
563bool QQuickItemView::highlightFollowsCurrentItem()
const
565 Q_D(
const QQuickItemView);
566 return d->autoHighlight;
569void QQuickItemView::setHighlightFollowsCurrentItem(
bool autoHighlight)
572 if (d->autoHighlight != autoHighlight) {
573 d->autoHighlight = autoHighlight;
575 d->updateHighlight();
576 emit highlightFollowsCurrentItemChanged();
580QQuickItemView::HighlightRangeMode QQuickItemView::highlightRangeMode()
const
582 Q_D(
const QQuickItemView);
583 return static_cast<QQuickItemView::HighlightRangeMode>(d->highlightRange);
586void QQuickItemView::setHighlightRangeMode(HighlightRangeMode mode)
589 if (d->highlightRange == mode)
591 d->highlightRange = mode;
592 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
593 if (isComponentComplete()) {
595 d->moveReason = QQuickItemViewPrivate::Other;
598 emit highlightRangeModeChanged();
602qreal QQuickItemView::preferredHighlightBegin()
const
604 Q_D(
const QQuickItemView);
605 return d->highlightRangeStart;
608void QQuickItemView::setPreferredHighlightBegin(qreal start)
611 d->highlightRangeStartValid =
true;
612 if (d->highlightRangeStart == start)
614 d->highlightRangeStart = start;
615 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
616 if (isComponentComplete()) {
618 if (!isMoving() && !isFlicking()) {
619 d->moveReason = QQuickItemViewPrivate::Other;
623 emit preferredHighlightBeginChanged();
626void QQuickItemView::resetPreferredHighlightBegin()
629 d->highlightRangeStartValid =
false;
630 if (d->highlightRangeStart == 0)
632 d->highlightRangeStart = 0;
633 if (isComponentComplete()) {
635 if (!isMoving() && !isFlicking()) {
636 d->moveReason = QQuickItemViewPrivate::Other;
640 emit preferredHighlightBeginChanged();
643qreal QQuickItemView::preferredHighlightEnd()
const
645 Q_D(
const QQuickItemView);
646 return d->highlightRangeEnd;
649void QQuickItemView::setPreferredHighlightEnd(qreal end)
652 d->highlightRangeEndValid =
true;
653 if (d->highlightRangeEnd == end)
655 d->highlightRangeEnd = end;
656 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
657 if (isComponentComplete()) {
659 if (!isMoving() && !isFlicking()) {
660 d->moveReason = QQuickItemViewPrivate::Other;
664 emit preferredHighlightEndChanged();
667void QQuickItemView::resetPreferredHighlightEnd()
670 d->highlightRangeEndValid =
false;
671 if (d->highlightRangeEnd == 0)
673 d->highlightRangeEnd = 0;
674 if (isComponentComplete()) {
676 if (!isMoving() && !isFlicking()) {
677 d->moveReason = QQuickItemViewPrivate::Other;
681 emit preferredHighlightEndChanged();
684int QQuickItemView::highlightMoveDuration()
const
686 Q_D(
const QQuickItemView);
687 return d->highlightMoveDuration;
690void QQuickItemView::setHighlightMoveDuration(
int duration)
693 if (d->highlightMoveDuration != duration) {
694 d->highlightMoveDuration = duration;
695 emit highlightMoveDurationChanged();
699bool QQuickItemView::reuseItems()
const
701 return bool(d_func()->reusableFlag == QQmlDelegateModel::Reusable);
704void QQuickItemView::setReuseItems(
bool reuse)
707 if (reuseItems() == reuse)
710 d->reusableFlag = reuse ? QQmlDelegateModel::Reusable : QQmlDelegateModel::NotReusable;
712 if (!reuse && d->model) {
715 d->model->drainReusableItemsPool(0);
718 emit reuseItemsChanged();
721#if QT_CONFIG(quick_viewtransitions)
722QQuickTransition *QQuickItemView::populateTransition()
const
724 Q_D(
const QQuickItemView);
725 return d->transitioner ? d->transitioner->populateTransition :
nullptr;
728void QQuickItemView::setPopulateTransition(QQuickTransition *transition)
731 d->createTransitioner();
732 if (d->transitioner->populateTransition != transition) {
733 d->transitioner->populateTransition = transition;
734 emit populateTransitionChanged();
738QQuickTransition *QQuickItemView::addTransition()
const
740 Q_D(
const QQuickItemView);
741 return d->transitioner ? d->transitioner->addTransition :
nullptr;
744void QQuickItemView::setAddTransition(QQuickTransition *transition)
747 d->createTransitioner();
748 if (d->transitioner->addTransition != transition) {
749 d->transitioner->addTransition = transition;
750 emit addTransitionChanged();
754QQuickTransition *QQuickItemView::addDisplacedTransition()
const
756 Q_D(
const QQuickItemView);
757 return d->transitioner ? d->transitioner->addDisplacedTransition :
nullptr;
760void QQuickItemView::setAddDisplacedTransition(QQuickTransition *transition)
763 d->createTransitioner();
764 if (d->transitioner->addDisplacedTransition != transition) {
765 d->transitioner->addDisplacedTransition = transition;
766 emit addDisplacedTransitionChanged();
770QQuickTransition *QQuickItemView::moveTransition()
const
772 Q_D(
const QQuickItemView);
773 return d->transitioner ? d->transitioner->moveTransition :
nullptr;
776void QQuickItemView::setMoveTransition(QQuickTransition *transition)
779 d->createTransitioner();
780 if (d->transitioner->moveTransition != transition) {
781 d->transitioner->moveTransition = transition;
782 emit moveTransitionChanged();
786QQuickTransition *QQuickItemView::moveDisplacedTransition()
const
788 Q_D(
const QQuickItemView);
789 return d->transitioner ? d->transitioner->moveDisplacedTransition :
nullptr;
792void QQuickItemView::setMoveDisplacedTransition(QQuickTransition *transition)
795 d->createTransitioner();
796 if (d->transitioner->moveDisplacedTransition != transition) {
797 d->transitioner->moveDisplacedTransition = transition;
798 emit moveDisplacedTransitionChanged();
802QQuickTransition *QQuickItemView::removeTransition()
const
804 Q_D(
const QQuickItemView);
805 return d->transitioner ? d->transitioner->removeTransition :
nullptr;
808void QQuickItemView::setRemoveTransition(QQuickTransition *transition)
811 d->createTransitioner();
812 if (d->transitioner->removeTransition != transition) {
813 d->transitioner->removeTransition = transition;
814 emit removeTransitionChanged();
818QQuickTransition *QQuickItemView::removeDisplacedTransition()
const
820 Q_D(
const QQuickItemView);
821 return d->transitioner ? d->transitioner->removeDisplacedTransition :
nullptr;
824void QQuickItemView::setRemoveDisplacedTransition(QQuickTransition *transition)
827 d->createTransitioner();
828 if (d->transitioner->removeDisplacedTransition != transition) {
829 d->transitioner->removeDisplacedTransition = transition;
830 emit removeDisplacedTransitionChanged();
834QQuickTransition *QQuickItemView::displacedTransition()
const
836 Q_D(
const QQuickItemView);
837 return d->transitioner ? d->transitioner->displacedTransition :
nullptr;
840void QQuickItemView::setDisplacedTransition(QQuickTransition *transition)
843 d->createTransitioner();
844 if (d->transitioner->displacedTransition != transition) {
845 d->transitioner->displacedTransition = transition;
846 emit displacedTransitionChanged();
851void QQuickItemViewPrivate::positionViewAtIndex(
int index,
int mode)
855 if (mode < QQuickItemView::Beginning || mode > QQuickItemView::SnapPosition)
860 applyPendingChanges();
861 const int modelCount = model->count();
862 int idx = qMax(qMin(index, modelCount - 1), 0);
864 const auto viewSize = size();
865 qreal pos = isContentFlowReversed() ? -position() - viewSize : position();
866 FxViewItem *item = visibleItem(idx);
867 qreal maxExtent = calculatedMaxExtent();
872 qreal itemPos = (mode == QQuickItemView::Beginning && idx == 0)
873 ? contentStartOffset()
875 changedVisibleIndex(idx);
878 const QList<FxViewItem *> oldVisible = visibleItems;
879 visibleItems.clear();
881 if (mode == QQuickItemView::Beginning && idx == 0) {
883 changedVisibleIndex(idx);
893 setPosition(qMin(itemPos, maxExtent));
896 for (FxViewItem *item : oldVisible)
897 releaseItem(item, reusableFlag);
898 item = visibleItem(idx);
901 const bool stickyHeader = hasStickyHeader();
902 const bool stickyFooter = hasStickyFooter();
903 const qreal stickyHeaderSize = stickyHeader ? headerSize() : 0;
904 const qreal stickyFooterSize = stickyFooter ? footerSize() : 0;
906 const qreal itemPos = item->position();
908 case QQuickItemView::Beginning:
910 if (header && (index < 0 || stickyHeader))
913 case QQuickItemView::Center:
914 pos = itemPos - (viewSize - item->size())/2;
916 case QQuickItemView::End:
917 pos = itemPos - viewSize + item->size();
918 if (footer && (index >= modelCount || stickyFooter))
921 case QQuickItemView::Visible:
922 if (itemPos > pos + viewSize - stickyFooterSize)
923 pos = item->endPosition() - viewSize + stickyFooterSize;
924 else if (item->endPosition() <= pos - stickyHeaderSize)
925 pos = itemPos - stickyHeaderSize;
927 case QQuickItemView::Contain:
928 if (item->endPosition() >= pos + viewSize + stickyFooterSize)
929 pos = itemPos - viewSize + item->size() + stickyFooterSize;
930 if (itemPos - stickyHeaderSize < pos)
931 pos = itemPos - stickyHeaderSize;
933 case QQuickItemView::SnapPosition:
934 pos = itemPos - highlightRangeStart - stickyHeaderSize;
937 pos = qMin(pos, maxExtent);
938 qreal minExtent = calculatedMinExtent();
939 pos = qMax(pos, minExtent);
940 moveReason = QQuickItemViewPrivate::Other;
945 resetHighlightPosition();
952void QQuickItemView::positionViewAtIndex(
int index,
int mode)
955 if (!d->isValid() || index < 0 || index >= d->model->count())
957 d->positionViewAtIndex(index, mode);
961void QQuickItemView::positionViewAtBeginning()
966 d->positionViewAtIndex(-1, Beginning);
969void QQuickItemView::positionViewAtEnd()
974 d->positionViewAtIndex(d->model->count(), End);
979 for (FxViewItem *item : items) {
980 if (item->contains(x, y))
986int QQuickItemView::indexAt(qreal x, qreal y)
const
988 Q_D(
const QQuickItemView);
989 const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y);
990 return item ? item->index : -1;
993QQuickItem *QQuickItemView::itemAt(qreal x, qreal y)
const
995 Q_D(
const QQuickItemView);
996 const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y);
997 return item ? item->item :
nullptr;
1000QQuickItem *QQuickItemView::itemAtIndex(
int index)
const
1002 Q_D(
const QQuickItemView);
1003 const FxViewItem *item = d->visibleItem(index);
1004 return item ? item->item :
nullptr;
1007void QQuickItemView::forceLayout()
1009 Q_D(QQuickItemView);
1010 if (isComponentComplete() && (d->currentChanges.hasPendingChanges() || d->forceLayout))
1014void QQuickItemViewPrivate::applyPendingChanges()
1016 Q_Q(QQuickItemView);
1017 if (q->isComponentComplete() && currentChanges.hasPendingChanges())
1021int QQuickItemViewPrivate::findMoveKeyIndex(QQmlChangeSet::MoveKey key,
const QList<QQmlChangeSet::Change> &changes)
const
1023 for (
int i=0; i<changes.size(); i++) {
1024 for (
int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
1025 if (changes[i].moveKey(j) == key)
1032qreal QQuickItemViewPrivate::minExtentForAxis(
const AxisData &axisData,
bool forXAxis)
const
1034 Q_Q(
const QQuickItemView);
1036 qreal highlightStart;
1038 qreal endPositionFirstItem = 0;
1039 qreal extent = -startPosition() + axisData.startMargin;
1040 if (isContentFlowReversed()) {
1041 if (model && model->count())
1042 endPositionFirstItem = positionAt(model->count()-1);
1044 extent += headerSize();
1045 highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
1046 highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
1047 extent += footerSize();
1048 qreal maxExtentAlongAxis = forXAxis ? q->maxXExtent() : q->maxYExtent();
1049 if (extent < maxExtentAlongAxis)
1050 extent = maxExtentAlongAxis;
1052 endPositionFirstItem = endPositionAt(0);
1053 highlightStart = highlightRangeStart;
1054 highlightEnd = highlightRangeEnd;
1055 extent += headerSize();
1057 if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
1058 extent += highlightStart;
1059 FxViewItem *firstItem = visibleItem(0);
1061 extent -= firstItem->sectionSize();
1062 extent = isContentFlowReversed()
1063 ? qMin(extent, endPositionFirstItem + highlightEnd)
1064 : qMax(extent, -(endPositionFirstItem - highlightEnd));
1069qreal QQuickItemViewPrivate::maxExtentForAxis(
const AxisData &axisData,
bool forXAxis)
const
1071 Q_Q(
const QQuickItemView);
1073 qreal highlightStart;
1075 qreal lastItemPosition = 0;
1077 if (isContentFlowReversed()) {
1078 highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
1079 highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
1080 lastItemPosition = endPosition();
1082 highlightStart = highlightRangeStart;
1083 highlightEnd = highlightRangeEnd;
1084 if (model && model->count())
1085 lastItemPosition = positionAt(model->count()-1);
1087 if (!model || !model->count()) {
1088 if (!isContentFlowReversed())
1089 maxExtent = header ? -headerSize() : 0;
1090 extent += forXAxis ? q->width() : q->height();
1091 }
else if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
1092 extent = -(lastItemPosition - highlightStart);
1093 if (highlightEnd != highlightStart) {
1094 extent = isContentFlowReversed()
1095 ? qMax(extent, -(endPosition() - highlightEnd))
1096 : qMin(extent, -(endPosition() - highlightEnd));
1099 extent = -(endPosition() - (forXAxis ? q->width() : q->height()));
1101 if (isContentFlowReversed()) {
1102 extent -= headerSize();
1103 extent -= axisData.endMargin;
1105 extent -= footerSize();
1106 extent -= axisData.endMargin;
1107 qreal minExtentAlongAxis = forXAxis ? q->minXExtent() : q->minYExtent();
1108 if (extent > minExtentAlongAxis)
1109 extent = minExtentAlongAxis;
1115qreal QQuickItemViewPrivate::calculatedMinExtent()
const
1117 Q_Q(
const QQuickItemView);
1119 if (layoutOrientation() == Qt::Vertical)
1120 minExtent = isContentFlowReversed() ? q->maxYExtent() - size(): -q->minYExtent();
1122 minExtent = isContentFlowReversed() ? q->maxXExtent() - size(): -q->minXExtent();
1127qreal QQuickItemViewPrivate::calculatedMaxExtent()
const
1129 Q_Q(
const QQuickItemView);
1131 if (layoutOrientation() == Qt::Vertical)
1132 maxExtent = isContentFlowReversed() ? q->minYExtent() - size(): -q->maxYExtent();
1134 maxExtent = isContentFlowReversed() ? q->minXExtent() - size(): -q->maxXExtent();
1138void QQuickItemViewPrivate::connectModel(QQuickItemView *q, QQmlDelegateModelPointer *model)
1140 QQmlInstanceModel *instanceModel = model->instanceModel();
1144 bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
1145 QObject::connect(instanceModel, &QQmlInstanceModel::createdItem,
1146 q, &QQuickItemView::createdItem);
1147 QObject::connect(instanceModel, &QQmlInstanceModel::initItem,
1148 q, &QQuickItemView::initItem);
1149 QObject::connect(instanceModel, &QQmlInstanceModel::destroyingItem,
1150 q, &QQuickItemView::destroyingItem);
1151 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
1152 QObject::connect(delegateModel, &QQmlInstanceModel::itemPooled,
1153 q, &QQuickItemView::onItemPooled);
1154 QObject::connect(delegateModel, &QQmlInstanceModel::itemReused,
1155 q, &QQuickItemView::onItemReused);
1158 if (q->isComponentComplete()) {
1159 updateSectionCriteria();
1162
1164 q->setCurrentIndex(instanceModel->count() > 0 ? 0 : -1);
1167#if QT_CONFIG(quick_viewtransitions)
1168 if (transitioner && transitioner->populateTransition) {
1169 transitioner->setPopulateTransitionEnabled(
true);
1170 forceLayoutPolish();
1175 QObject::connect(instanceModel, &QQmlInstanceModel::modelUpdated,
1176 q, &QQuickItemView::modelUpdated);
1177 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
1178 QObjectPrivate::connect(
1179 dataModel, &QQmlDelegateModel::delegateChanged,
1180 this, &QQuickItemViewPrivate::applyDelegateChange);
1181 QObjectPrivate::connect(
1182 dataModel, &QQmlDelegateModel::delegateModelAccessChanged,
1183 this, &QQuickItemViewPrivate::applyDelegateModelAccessChange);
1185 QObject::connect(dataModel, &QQmlDelegateModel::modelChanged,
1186 q, &QQuickItemView::modelChanged);
1193void QQuickItemViewPrivate::disconnectModel(QQuickItemView *q, QQmlDelegateModelPointer *model)
1195 QQmlInstanceModel *instanceModel = model->instanceModel();
1200 QObject::disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
1201 q, &QQuickItemView::modelUpdated);
1202 QObject::disconnect(instanceModel, &QQmlInstanceModel::initItem,
1203 q, &QQuickItemView::initItem);
1204 QObject::disconnect(instanceModel, &QQmlInstanceModel::createdItem,
1205 q, &QQuickItemView::createdItem);
1206 QObject::disconnect(instanceModel, &QQmlInstanceModel::destroyingItem,
1207 q, &QQuickItemView::destroyingItem);
1208 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
1209 QObject::disconnect(delegateModel, &QQmlInstanceModel::itemPooled,
1210 q, &QQuickItemView::onItemPooled);
1211 QObject::disconnect(delegateModel, &QQmlInstanceModel::itemReused,
1212 q, &QQuickItemView::onItemReused);
1213 QObjectPrivate::disconnect(
1214 delegateModel, &QQmlDelegateModel::delegateChanged,
1215 this, &QQuickItemViewPrivate::applyDelegateChange);
1216 QObjectPrivate::disconnect(
1217 delegateModel, &QQmlDelegateModel::delegateModelAccessChanged,
1218 this, &QQuickItemViewPrivate::applyDelegateModelAccessChange);
1220 QObject::disconnect(delegateModel, &QQmlDelegateModel::modelChanged,
1221 q, &QQuickItemView::modelChanged);
1226void QQuickItemViewPrivate::applyDelegateChange()
1228 Q_Q(QQuickItemView);
1230 QQmlDelegateModel::applyDelegateChangeOnView(q,
this);
1232 releaseVisibleItems(QQmlDelegateModel::NotReusable);
1233 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1234 updateSectionCriteria();
1236 moveReason = QQuickItemViewPrivate::SetIndex;
1237 updateCurrent(currentIndex);
1238 if (highlight && currentItem) {
1240 resetHighlightPosition();
1241 updateTrackedItem();
1243 moveReason = QQuickItemViewPrivate::Other;
1248void QQuickItemViewPrivate::checkVisible()
const
1251 for (
int i = 0; i < visibleItems.size(); ++i) {
1252 FxViewItem *item = visibleItems.at(i);
1253 if (item->index == -1) {
1255 }
else if (item->index != visibleIndex + i - skip) {
1256 qFatal(
"index %d %d %d", visibleIndex, i, item->index);
1262void QQuickItemViewPrivate::showVisibleItems()
const
1264 qDebug() <<
"Visible items:";
1265 for (FxViewItem *item : visibleItems) {
1266 qDebug() <<
"\t" << item->index
1267 << item->item->objectName()
1268 << item->position();
1273void QQuickItemViewPrivate::emitCountChanged()
1275 Q_Q(QQuickItemView);
1276 qCDebug(lcCount).nospace() <<
"about to emit countChanged for " << q <<
"; count changed to " << q->count();
1277 emit q->countChanged();
1280void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change,
1281 const QRectF &oldGeometry)
1283 Q_Q(QQuickItemView);
1284 QQuickFlickablePrivate::itemGeometryChanged(item, change, oldGeometry);
1285 if (!q->isComponentComplete())
1288 if (header && header->item == item) {
1292 if (!q->isMoving() && !q->isFlicking())
1294 }
else if (footer && footer->item == item) {
1298 if (!q->isMoving() && !q->isFlicking())
1302 if (currentItem && currentItem->item == item) {
1305 bool prevInLayout = inLayout;
1306#if QT_CONFIG(quick_viewtransitions)
1308 FxViewItem *actualItem = transitioner ? visibleItem(currentIndex) :
nullptr;
1309 if (actualItem && actualItem->transitionRunning())
1314 inLayout = prevInLayout;
1317 if (trackedItem && trackedItem->item == item)
1318 q->trackedPositionChanged();
1321void QQuickItemView::destroyRemoved()
1323 Q_D(QQuickItemView);
1325#if QT_CONFIG(quick_viewtransitions)
1326 bool hasRemoveTransition =
false;
1327 bool hasRemoveTransitionAsTarget =
false;
1328 if (d->transitioner) {
1329 hasRemoveTransition = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false);
1330 hasRemoveTransitionAsTarget = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true);
1334 for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
1335 it != d->visibleItems.end();) {
1336 FxViewItem *item = *it;
1337 if (item->index == -1 && (!item->attached || item->attached->delayRemove() ==
false)) {
1338#if QT_CONFIG(quick_viewtransitions)
1339 if (hasRemoveTransitionAsTarget) {
1341 d->runDelayedRemoveTransition =
true;
1342 QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()),
this, SLOT(destroyRemoved()));
1345 if (hasRemoveTransition)
1346 d->runDelayedRemoveTransition =
true;
1348 d->releaseItem(item, d->reusableFlag);
1349 it = d->visibleItems.erase(it);
1350#if QT_CONFIG(quick_viewtransitions)
1359 d->forceLayoutPolish();
1362void QQuickItemView::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
1364 Q_D(QQuickItemView);
1367#if QT_CONFIG(quick_viewtransitions)
1368 if (d->transitioner)
1369 d->transitioner->setPopulateTransitionEnabled(
true);
1371 d->moveReason = QQuickItemViewPrivate::SetIndex;
1373 if (d->highlight && d->currentItem) {
1374 if (d->autoHighlight)
1375 d->resetHighlightPosition();
1376 d->updateTrackedItem();
1378 d->moveReason = QQuickItemViewPrivate::Other;
1379 d->emitCountChanged();
1380#if QT_CONFIG(quick_viewtransitions)
1381 if (d->transitioner && d->transitioner->populateTransition)
1382 d->forceLayoutPolish();
1386 d->bufferedChanges.prepare(d->currentIndex, d->itemCount);
1387 d->bufferedChanges.applyChanges(changeSet);
1389 if (d->bufferedChanges.hasPendingChanges()) {
1390 d->currentChanges.applyBufferedChanges(d->bufferedChanges);
1391 d->bufferedChanges.reset();
1393 d->currentChanges.prepare(d->currentIndex, d->itemCount);
1394 d->currentChanges.applyChanges(changeSet);
1400void QQuickItemView::animStopped()
1402 Q_D(QQuickItemView);
1403 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
1404 d->refillOrLayout();
1405 if (d->haveHighlightRange && d->highlightRange == QQuickItemView::StrictlyEnforceRange)
1406 d->updateHighlight();
1410void QQuickItemView::trackedPositionChanged()
1412 Q_D(QQuickItemView);
1413 if (!d->trackedItem || !d->currentItem)
1421 const bool needMoveToTrackHighlight = d->autoHighlight || d->highlightRange != NoHighlightRange;
1423 if (d->moveReason == QQuickItemViewPrivate::SetIndex && needMoveToTrackHighlight) {
1424 qreal trackedPos = d->trackedItem->position();
1425 qreal trackedSize = d->trackedItem->size();
1426 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
1427 qreal pos = viewPos;
1428 if (d->haveHighlightRange) {
1429 if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
1430 pos = trackedPos - d->highlightRangeEnd + trackedSize;
1431 if (trackedPos < pos + d->highlightRangeStart)
1432 pos = trackedPos - d->highlightRangeStart;
1433 if (d->highlightRange != StrictlyEnforceRange) {
1434 qreal maxExtent = d->calculatedMaxExtent();
1435 if (pos > maxExtent)
1437 qreal minExtent = d->calculatedMinExtent();
1438 if (pos < minExtent)
1442 if (d->trackedItem != d->currentItem) {
1444 trackedPos -= d->currentItem->sectionSize();
1445 trackedSize += d->currentItem->sectionSize();
1447 qreal trackedEndPos = d->trackedItem->endPosition();
1448 qreal toItemPos = d->currentItem->position();
1449 qreal toItemEndPos = d->currentItem->endPosition();
1450 if (d->showHeaderForIndex(d->currentIndex)) {
1451 qreal startOffset = -d->contentStartOffset();
1452 trackedPos -= startOffset;
1453 trackedEndPos -= startOffset;
1454 toItemPos -= startOffset;
1455 toItemEndPos -= startOffset;
1456 }
else if (d->showFooterForIndex(d->currentIndex)) {
1457 qreal endOffset = d->footerSize();
1458 if (d->layoutOrientation() == Qt::Vertical) {
1459 if (d->isContentFlowReversed())
1460 endOffset += d->vData.startMargin;
1462 endOffset += d->vData.endMargin;
1464 if (d->isContentFlowReversed())
1465 endOffset += d->hData.startMargin;
1467 endOffset += d->hData.endMargin;
1469 trackedPos += endOffset;
1470 trackedEndPos += endOffset;
1471 toItemPos += endOffset;
1472 toItemEndPos += endOffset;
1475 if (trackedEndPos >= viewPos + d->size()
1476 && toItemEndPos >= viewPos + d->size()) {
1477 if (trackedEndPos <= toItemEndPos) {
1478 pos = trackedEndPos - d->size();
1479 if (trackedSize > d->size())
1482 pos = toItemEndPos - d->size();
1483 if (d->currentItem->size() > d->size())
1484 pos = d->currentItem->position();
1487 if (trackedPos < pos && toItemPos < pos)
1488 pos = qMax(trackedPos, toItemPos);
1490 if (viewPos != pos) {
1491 d->calcVelocity =
true;
1492 d->setPosition(pos);
1493 d->calcVelocity =
false;
1498void QQuickItemView::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
1500 Q_D(QQuickItemView);
1501 d->markExtentsDirty();
1502 if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty()))
1503 d->forceLayoutPolish();
1504 QQuickFlickable::geometryChange(newGeometry, oldGeometry);
1507qreal QQuickItemView::minYExtent()
const
1509 Q_D(
const QQuickItemView);
1510 if (d->layoutOrientation() == Qt::Horizontal)
1511 return QQuickFlickable::minYExtent();
1513 if (d->vData.minExtentDirty) {
1514 d->minExtent = d->minExtentForAxis(d->vData,
false);
1515 d->vData.minExtentDirty =
false;
1518 return d->minExtent;
1521qreal QQuickItemView::maxYExtent()
const
1523 Q_D(
const QQuickItemView);
1524 if (d->layoutOrientation() == Qt::Horizontal)
1525 return QQuickFlickable::maxYExtent();
1527 if (d->vData.maxExtentDirty) {
1528 d->maxExtent = d->maxExtentForAxis(d->vData,
false);
1529 d->vData.maxExtentDirty =
false;
1532 return d->maxExtent;
1535qreal QQuickItemView::minXExtent()
const
1537 Q_D(
const QQuickItemView);
1538 if (d->layoutOrientation() == Qt::Vertical)
1539 return QQuickFlickable::minXExtent();
1541 if (d->hData.minExtentDirty) {
1542 d->minExtent = d->minExtentForAxis(d->hData,
true);
1543 d->hData.minExtentDirty =
false;
1546 return d->minExtent;
1549qreal QQuickItemView::maxXExtent()
const
1551 Q_D(
const QQuickItemView);
1552 if (d->layoutOrientation() == Qt::Vertical)
1553 return QQuickFlickable::maxXExtent();
1555 if (d->hData.maxExtentDirty) {
1556 d->maxExtent = d->maxExtentForAxis(d->hData,
true);
1557 d->hData.maxExtentDirty =
false;
1560 return d->maxExtent;
1563void QQuickItemView::setContentX(qreal pos)
1565 Q_D(QQuickItemView);
1567 d->moveReason = QQuickItemViewPrivate::Other;
1568 QQuickFlickable::setContentX(pos);
1571void QQuickItemView::setContentY(qreal pos)
1573 Q_D(QQuickItemView);
1575 d->moveReason = QQuickItemViewPrivate::Other;
1576 QQuickFlickable::setContentY(pos);
1579qreal QQuickItemView::originX()
const
1581 Q_D(
const QQuickItemView);
1582 if (d->layoutOrientation() == Qt::Horizontal
1583 && effectiveLayoutDirection() == Qt::RightToLeft
1584 && contentWidth() < width()) {
1585 return -d->lastPosition() - d->footerSize();
1587 return QQuickFlickable::originX();
1590qreal QQuickItemView::originY()
const
1592 Q_D(
const QQuickItemView);
1593 if (d->layoutOrientation() == Qt::Vertical
1594 && d->verticalLayoutDirection == QQuickItemView::BottomToTop
1595 && contentHeight() < height()) {
1596 return -d->lastPosition() - d->footerSize();
1598 return QQuickFlickable::originY();
1601void QQuickItemView::updatePolish()
1603 Q_D(QQuickItemView);
1604 QQuickFlickable::updatePolish();
1608void QQuickItemView::componentComplete()
1610 Q_D(QQuickItemView);
1611 if (d->model && d->ownModel)
1612 static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
1614 QQuickFlickable::componentComplete();
1616 d->updateSectionCriteria();
1619 d->updateViewport();
1620 d->setPosition(d->contentStartOffset());
1621#if QT_CONFIG(quick_viewtransitions)
1622 if (d->transitioner)
1623 d->transitioner->setPopulateTransitionEnabled(
true);
1628 d->moveReason = QQuickItemViewPrivate::SetIndex;
1629 if (d->currentIndex < 0 && !d->currentIndexCleared)
1630 d->updateCurrent(0);
1632 d->updateCurrent(d->currentIndex);
1633 if (d->highlight && d->currentItem) {
1634 if (d->autoHighlight)
1635 d->resetHighlightPosition();
1636 d->updateTrackedItem();
1638 d->moveReason = QQuickItemViewPrivate::Other;
1641 if (d->model && d->model->count())
1642 d->emitCountChanged();
1647QQuickItemViewPrivate::QQuickItemViewPrivate()
1650 , displayMarginBeginning(0), displayMarginEnd(0)
1651 , layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom)
1653 , currentIndex(-1), currentItem(
nullptr)
1654 , trackedItem(
nullptr), requestedIndex(-1)
1655 , highlightComponent(
nullptr), highlight(
nullptr)
1656 , highlightRange(QQuickItemView::NoHighlightRange)
1657 , highlightRangeStart(0), highlightRangeEnd(0)
1658 , highlightMoveDuration(150)
1659 , headerComponent(
nullptr), header(
nullptr), footerComponent(
nullptr), footer(
nullptr)
1660#if QT_CONFIG(quick_viewtransitions)
1661 , transitioner(
nullptr)
1663 , minExtent(0), maxExtent(0)
1664 , ownModel(
false), wrap(
false)
1665 , keyNavigationEnabled(
true)
1666 , explicitKeyNavigationEnabled(
false)
1667 , inLayout(
false), inViewportMoved(
false), forceLayout(
false), currentIndexCleared(
false)
1668 , haveHighlightRange(
false), autoHighlight(
true), highlightRangeStartValid(
false), highlightRangeEndValid(
false)
1669 , fillCacheBuffer(
false), inRequest(
false)
1670#if QT_CONFIG(quick_viewtransitions)
1671 , runDelayedRemoveTransition(
false)
1673 , delegateValidated(
false)
1675 , explicitDelegate(
false)
1676 , explicitDelegateModelAccess(
false)
1679 bufferPause.addAnimationChangeListener(
this, QAbstractAnimationJob::Completion);
1680 bufferPause.setLoopCount(1);
1681 bufferPause.setDuration(16);
1686QQuickItemViewPrivate::~QQuickItemViewPrivate()
1688#if QT_CONFIG(quick_viewtransitions)
1690 transitioner->setChangeListener(
nullptr);
1691 delete transitioner;
1695bool QQuickItemViewPrivate::isValid()
const
1697 return model && model->count() && model->isValid();
1700qreal QQuickItemViewPrivate::position()
const
1702 Q_Q(
const QQuickItemView);
1703 return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
1706qreal QQuickItemViewPrivate::size()
const
1708 Q_Q(
const QQuickItemView);
1709 return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
1712qreal QQuickItemViewPrivate::startPosition()
const
1714 return isContentFlowReversed() ? -lastPosition() : originPosition();
1717qreal QQuickItemViewPrivate::endPosition()
const
1719 return isContentFlowReversed() ? -originPosition() : lastPosition();
1722qreal QQuickItemViewPrivate::contentStartOffset()
const
1724 qreal pos = -headerSize();
1725 if (layoutOrientation() == Qt::Vertical) {
1726 if (isContentFlowReversed())
1727 pos -= vData.endMargin;
1729 pos -= vData.startMargin;
1731 if (isContentFlowReversed())
1732 pos -= hData.endMargin;
1734 pos -= hData.startMargin;
1739int QQuickItemViewPrivate::findLastVisibleIndex(
int defaultValue)
const
1741 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1743 if (item->index != -1)
1746 return defaultValue;
1749FxViewItem *QQuickItemViewPrivate::visibleItem(
int modelIndex)
const {
1750 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.size()) {
1751 for (
int i = modelIndex - visibleIndex; i < visibleItems.size(); ++i) {
1752 FxViewItem *item = visibleItems.at(i);
1753 if (item->index == modelIndex)
1760FxViewItem *QQuickItemViewPrivate::firstItemInView()
const {
1761 const qreal pos = isContentFlowReversed() ? -position()-size() : position();
1762 for (FxViewItem *item : visibleItems) {
1763 if (item->index != -1 && item->endPosition() > pos)
1766 return visibleItems.size() ? visibleItems.first() : 0;
1769int QQuickItemViewPrivate::findLastIndexInView()
const
1771 const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
1772 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1774 if (item->index != -1 && item->position() <= viewEndPos)
1783int QQuickItemViewPrivate::mapFromModel(
int modelIndex)
const
1785 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.size())
1787 for (
int i = 0; i < visibleItems.size(); ++i) {
1788 FxViewItem *item = visibleItems.at(i);
1789 if (item->index == modelIndex)
1791 if (item->index > modelIndex)
1797void QQuickItemViewPrivate::init()
1799 Q_Q(QQuickItemView);
1800 q->setFlag(QQuickItem::ItemIsFocusScope);
1801 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
1802 QObject::connect(q, &QQuickFlickable::interactiveChanged, q, &QQuickItemView::keyNavigationEnabledChanged);
1803 q->setFlickableDirection(QQuickFlickable::VerticalFlick);
1806void QQuickItemViewPrivate::updateCurrent(
int modelIndex)
1808 Q_Q(QQuickItemView);
1809 applyPendingChanges();
1810 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
1812 if (currentItem->attached)
1813 currentItem->attached->setIsCurrentItem(
false);
1814 releaseCurrentItem(reusableFlag);
1815 currentIndex = modelIndex;
1816 emit q->currentIndexChanged();
1817 emit q->currentItemChanged();
1819 }
else if (currentIndex != modelIndex) {
1820 currentIndex = modelIndex;
1821 emit q->currentIndexChanged();
1826 if (currentItem && currentIndex == modelIndex) {
1831 FxViewItem *oldCurrentItem = currentItem;
1832 int oldCurrentIndex = currentIndex;
1833 currentIndex = modelIndex;
1834 currentItem = createItem(modelIndex, QQmlIncubator::AsynchronousIfNested);
1835 if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
1836 oldCurrentItem->attached->setIsCurrentItem(
false);
1838 currentItem->item->setFocus(
true);
1839 if (currentItem->attached)
1840 currentItem->attached->setIsCurrentItem(
true);
1841 initializeCurrentItem();
1845 if (oldCurrentIndex != currentIndex)
1846 emit q->currentIndexChanged();
1847 if (oldCurrentItem != currentItem
1848 && (!oldCurrentItem || !currentItem || oldCurrentItem->item != currentItem->item))
1849 emit q->currentItemChanged();
1850 releaseItem(oldCurrentItem, reusableFlag);
1853void QQuickItemViewPrivate::clear(
bool onDestruction)
1855 Q_Q(QQuickItemView);
1858 auto cleanup = qScopeGuard([
this] { isClearing =
false; });
1860 currentChanges.reset();
1861 bufferedChanges.reset();
1864 releaseVisibleItems(QQmlInstanceModel::NotReusable);
1867#if QT_CONFIG(quick_viewtransitions)
1868 for (FxViewItem *item : std::as_const(releasePendingTransition)) {
1869 item->releaseAfterTransition =
false;
1870 releaseItem(item, QQmlInstanceModel::NotReusable);
1872 releasePendingTransition.clear();
1875 const bool hadCurrentItem = currentItem !=
nullptr;
1876 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1878 emit q->currentItemChanged();
1879 createHighlight(onDestruction);
1880 trackedItem =
nullptr;
1882 if (requestedIndex >= 0) {
1884 model->cancel(requestedIndex);
1885 requestedIndex = -1;
1893void QQuickItemViewPrivate::mirrorChange()
1895 Q_Q(QQuickItemView);
1897 emit q->effectiveLayoutDirectionChanged();
1900void QQuickItemViewPrivate::animationFinished(QAbstractAnimationJob *)
1902 Q_Q(QQuickItemView);
1903 fillCacheBuffer =
true;
1907void QQuickItemViewPrivate::refill()
1909 qreal s = qMax(size(), qreal(0.));
1910 const auto pos = position();
1911 if (isContentFlowReversed())
1912 refill(-pos - displayMarginBeginning-s, -pos + displayMarginEnd);
1914 refill(pos - displayMarginBeginning, pos + displayMarginEnd+s);
1917void QQuickItemViewPrivate::refill(qreal from, qreal to)
1919 Q_Q(QQuickItemView);
1920 if (!model || !model->isValid() || !q->isComponentComplete())
1922 if (q->size().isNull() && visibleItems.isEmpty())
1924 if (!model->count()) {
1937 if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) {
1938 currentChanges.reset();
1939 bufferedChanges.reset();
1940 releaseVisibleItems(reusableFlag);
1943 int prevCount = itemCount;
1944 itemCount = model->count();
1945 qreal bufferFrom = from - buffer;
1946 qreal bufferTo = to + buffer;
1947 qreal fillFrom = from;
1950 bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
false);
1952 if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
1956 bufferPause.start();
1958 if (bufferMode & BufferAfter)
1960 if (bufferMode & BufferBefore)
1961 fillFrom = bufferFrom;
1962 added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
true);
1966 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
1968 if (added || removed) {
1970 updateBeginningEnd();
1971 visibleItemsChanged();
1977 if (prevCount != itemCount)
1979 }
while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges());
1980 storeFirstVisibleItemPosition();
1984void QQuickItemViewPrivate::regenerate(
bool orientationChanged)
1986 Q_Q(QQuickItemView);
1987 if (q->isComponentComplete()) {
1988 if (orientationChanged) {
1998 setPosition(contentStartOffset());
2000 updateCurrent(currentIndex);
2004void QQuickItemViewPrivate::updateViewport()
2006 Q_Q(QQuickItemView);
2007 qreal extra = headerSize() + footerSize();
2008 qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
2009 if (layoutOrientation() == Qt::Vertical)
2010 q->setContentHeight(contentSize + extra);
2012 q->setContentWidth(contentSize + extra);
2015void QQuickItemViewPrivate::layout()
2017 Q_Q(QQuickItemView);
2024 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2029 if ((!isValid() && !visibleItems.size()) || q->size().isNull()) {
2030 if (q->size().isNull() && hasPendingChanges()) {
2041 setPosition(contentStartOffset());
2043#if QT_CONFIG(quick_viewtransitions)
2045 transitioner->setPopulateTransitionEnabled(
false);
2051#if QT_CONFIG(quick_viewtransitions)
2052 if (runDelayedRemoveTransition && transitioner
2053 && transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2056 for (
int i=0; i<visibleItems.size(); i++)
2057 visibleItems[i]->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2061 ChangeResult insertionPosChanges;
2062 ChangeResult removalPosChanges;
2063 if (!applyModelChanges(&insertionPosChanges, &removalPosChanges) && !forceLayout) {
2064 if (fillCacheBuffer) {
2065 fillCacheBuffer =
false;
2071 forceLayout =
false;
2073#if QT_CONFIG(quick_viewtransitions)
2074 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true)) {
2078 for (FxViewItem *item : std::as_const(visibleItems)) {
2079 if (!item->transitionScheduledOrRunning())
2080 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition,
true);
2086 layoutVisibleItems();
2087 storeFirstVisibleItemPosition();
2089#if QT_CONFIG(quick_viewtransitions)
2090 int lastIndexInView = findLastIndexInView();
2096 if (!q->isMoving() && !q->isFlicking() && !movingFromHighlight()) {
2104 updateUnrequestedPositions();
2106#if QT_CONFIG(quick_viewtransitions)
2110 if (lastIndexInView != -1 &&
2111 (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
false)
2112 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false))) {
2113 translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
2116 prepareVisibleItemTransitions();
2119 for (
int i = 0, count = releasePendingTransition.size(); i < count;) {
2120 auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds);
2125 const int old_count = count;
2126 count = releasePendingTransition.size();
2127 if (old_count > count)
2131 releaseItem(releasePendingTransition[i], reusableFlag);
2132 releasePendingTransition.remove(i);
2139 for (
int i=0; i<visibleItems.size(); i++)
2140 visibleItems[i]->startTransition(transitioner);
2141 for (
int i=0; i<releasePendingTransition.size(); i++)
2142 releasePendingTransition[i]->startTransition(transitioner);
2144 transitioner->setPopulateTransitionEnabled(
false);
2145 transitioner->resetTargetLists();
2150 updateCurrent(currentIndex);
2152#if QT_CONFIG(quick_viewtransitions)
2153 runDelayedRemoveTransition =
false;
2158bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult)
2160 Q_Q(QQuickItemView);
2161 if (!q->isComponentComplete() || !hasPendingChanges())
2164 if (bufferedChanges.hasPendingChanges()) {
2165 currentChanges.applyBufferedChanges(bufferedChanges);
2166 bufferedChanges.reset();
2169 updateUnrequestedIndexes();
2171 FxViewItem *prevVisibleItemsFirst = visibleItems.size() ? *visibleItems.constBegin() :
nullptr;
2172 int prevItemCount = itemCount;
2173 int prevVisibleItemsCount = visibleItems.size();
2174 bool visibleAffected =
false;
2175 bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
2176 || !currentChanges.pendingChanges.inserts().isEmpty();
2178 FxViewItem *prevFirstItemInView = firstItemInView();
2179 QQmlNullableValue<qreal> prevFirstItemInViewPos;
2180 int prevFirstItemInViewIndex = -1;
2181 if (prevFirstItemInView) {
2182 prevFirstItemInViewPos = prevFirstItemInView->position();
2183 prevFirstItemInViewIndex = prevFirstItemInView->index;
2185 qreal prevVisibleItemsFirstPos = visibleItems.size() ? firstVisibleItemPosition : 0.0;
2187 totalInsertionResult->visiblePos = prevFirstItemInViewPos;
2188 totalRemovalResult->visiblePos = prevFirstItemInViewPos;
2190 const QList<QQmlChangeSet::Change> &removals = currentChanges.pendingChanges.removes();
2191 const QList<QQmlChangeSet::Change> &insertions = currentChanges.pendingChanges.inserts();
2192 ChangeResult insertionResult(prevFirstItemInViewPos);
2193 ChangeResult removalResult(prevFirstItemInViewPos);
2195 int removedCount = 0;
2196 for (
const QQmlChangeSet::Change &r : removals) {
2197 itemCount -= r.count;
2198 if (applyRemovalChange(r, &removalResult, &removedCount))
2199 visibleAffected =
true;
2200 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(r.index))
2201 visibleAffected =
true;
2202 const int correctedFirstVisibleIndex = prevFirstItemInViewIndex - removalResult.countChangeBeforeVisible;
2203 if (correctedFirstVisibleIndex >= 0 && r.index < correctedFirstVisibleIndex) {
2204 if (r.index + r.count < correctedFirstVisibleIndex)
2205 removalResult.countChangeBeforeVisible += r.count;
2207 removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - r.index);
2210#if QT_CONFIG(quick_viewtransitions)
2211 if (runDelayedRemoveTransition) {
2212 QQmlChangeSet::Change removal;
2213 for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
2214 FxViewItem *item = *it;
2215 if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) {
2216 removeItem(item, removal, &removalResult);
2218 it = visibleItems.erase(it);
2225 *totalRemovalResult += removalResult;
2226 if (!removals.isEmpty()) {
2227 updateVisibleIndex();
2230 if (!insertions.isEmpty()) {
2231 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2232 layoutVisibleItems(removals.first().index);
2233 storeFirstVisibleItemPosition();
2237 QList<FxViewItem *> newItems;
2238 QList<MovedItem> movingIntoView;
2240 for (
int i=0; i<insertions.size(); i++) {
2241 bool wasEmpty = visibleItems.isEmpty();
2242 if (applyInsertionChange(insertions[i], &insertionResult, &newItems, &movingIntoView))
2243 visibleAffected =
true;
2244 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index))
2245 visibleAffected =
true;
2246 if (wasEmpty && !visibleItems.isEmpty())
2247 resetFirstItemPosition();
2248 *totalInsertionResult += insertionResult;
2251 if (i < insertions.size() - 1) {
2252 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2253 layoutVisibleItems(insertions[i].index);
2254 storeFirstVisibleItemPosition();
2256 itemCount += insertions[i].count;
2258 for (FxViewItem *item : std::as_const(newItems)) {
2260 item->attached->emitAdd();
2263#if QT_CONFIG(quick_viewtransitions)
2267 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
true)) {
2268 for (
const MovedItem &m : std::as_const(movingIntoView)) {
2269 int fromIndex = findMoveKeyIndex(m.moveKey, removals);
2270 if (fromIndex >= 0) {
2271 if (prevFirstItemInViewIndex >= 0 && fromIndex < prevFirstItemInViewIndex)
2272 repositionItemAt(m.item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
2274 repositionItemAt(m.item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
2275 m.item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2282 if (removedCount != prevVisibleItemsCount)
2283 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2286#if QT_CONFIG(quick_viewtransitions)
2287 prepareRemoveTransitions(¤tChanges.removedItems);
2289 for (
auto it = currentChanges.removedItems.begin();
2290 it != currentChanges.removedItems.end(); ++it) {
2291 releaseItem(it.value(), reusableFlag);
2293 currentChanges.removedItems.clear();
2295 if (currentChanges.currentChanged) {
2296 if (currentChanges.currentRemoved && currentItem) {
2297 if (currentItem->item && currentItem->attached)
2298 currentItem->attached->setIsCurrentItem(
false);
2299 const bool hadCurrentItem = currentItem !=
nullptr;
2300 releaseCurrentItem(reusableFlag);
2302 emit q->currentItemChanged();
2304 if (!currentIndexCleared)
2305 updateCurrent(currentChanges.newCurrentIndex);
2308 if (!visibleAffected)
2309 visibleAffected = !currentChanges.pendingChanges.changes().isEmpty();
2310 currentChanges.reset();
2313 if (prevItemCount != itemCount)
2315 if (!visibleAffected && viewportChanged)
2318 return visibleAffected;
2321bool QQuickItemViewPrivate::applyRemovalChange(
const QQmlChangeSet::Change &removal, ChangeResult *removeResult,
int *removedCount)
2323 Q_Q(QQuickItemView);
2324 bool visibleAffected =
false;
2326 if (visibleItems.size() && removal.index + removal.count > visibleItems.constLast()->index) {
2327 if (removal.index > visibleItems.constLast()->index)
2328 removeResult->countChangeAfterVisibleItems += removal.count;
2330 removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.constLast()->index);
2333 QList<FxViewItem*>::Iterator it = visibleItems.begin();
2334 while (it != visibleItems.end()) {
2335 FxViewItem *item = *it;
2336 if (item->index == -1 || item->index < removal.index) {
2338 if (!visibleAffected && item->index < removal.index)
2339 visibleAffected =
true;
2341 }
else if (item->index >= removal.index + removal.count) {
2343 item->index -= removal.count;
2344#if QT_CONFIG(quick_viewtransitions)
2345 if (removal.isMove())
2346 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
false);
2348 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2353 visibleAffected =
true;
2354 if (!removal.isMove() && item->item && item->attached)
2355 item->attached->emitRemove();
2357 if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) {
2359 QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
2362 removeItem(item, removal, removeResult);
2363 if (!removal.isMove())
2365 it = visibleItems.erase(it);
2370 return visibleAffected;
2373void QQuickItemViewPrivate::removeItem(FxViewItem *item,
const QQmlChangeSet::Change &removal, ChangeResult *removeResult)
2375 if (removeResult->visiblePos.isValid()) {
2376 if (item->position() < removeResult->visiblePos)
2377 updateSizeChangesBeforeVisiblePos(item, removeResult);
2379 removeResult->sizeChangesAfterVisiblePos += item->size();
2381 if (removal.isMove()) {
2382 currentChanges.removedItems.replace(removal.moveKey(item->index), item);
2383#if QT_CONFIG(quick_viewtransitions)
2384 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2388 currentChanges.removedItems.insert(QQmlChangeSet::MoveKey(), item);
2390 if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
2391 removeResult->changedFirstItem =
true;
2394void QQuickItemViewPrivate::updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
2396 removeResult->sizeChangesBeforeVisiblePos += item->size();
2399void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
2400 qreal prevVisibleItemsFirstPos,
2401 FxViewItem *prevFirstVisible,
2402 ChangeResult *insertionResult,
2403 ChangeResult *removalResult)
2405 const QQmlNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
2408 if (visibleItems.size()) {
2409 if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
2410 resetFirstItemPosition(prevVisibleItemsFirstPos);
2412 if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible
2413 && prevFirstVisible != *visibleItems.constBegin()) {
2416 if (!insertionResult->changedFirstItem)
2417 resetFirstItemPosition(prevVisibleItemsFirstPos);
2419 }
else if (prevViewPos.isValid()) {
2420 qreal moveForwardsBy = 0;
2421 qreal moveBackwardsBy = 0;
2424 const auto pos = visibleItems.constFirst()->position();
2425 if (pos > prevViewPos) {
2426 moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
2427 moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
2428 }
else if (pos < prevViewPos) {
2429 moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
2430 moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
2432 adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->countChangeBeforeVisible - removalResult->countChangeBeforeVisible);
2434 insertionResult->reset();
2435 removalResult->reset();
2439#if QT_CONFIG(quick_viewtransitions)
2440void QQuickItemViewPrivate::createTransitioner()
2442 if (!transitioner) {
2443 transitioner =
new QQuickItemViewTransitioner;
2444 transitioner->setChangeListener(
this);
2448void QQuickItemViewPrivate::prepareVisibleItemTransitions()
2450 Q_Q(QQuickItemView);
2455 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2456 for (
int i=0; i<visibleItems.size(); i++)
2457 visibleItems[i]->prepareTransition(transitioner, viewBounds);
2460void QQuickItemViewPrivate::prepareRemoveTransitions(QMultiHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems)
2465 if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true)
2466 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2467 for (
auto it = removedItems->begin(); it != removedItems->end(); ) {
2468 bool isRemove = it.key().moveId < 0;
2470 FxViewItem *item = *it;
2471 item->trackGeometry(
false);
2472 item->releaseAfterTransition =
true;
2473 releasePendingTransition.append(item);
2474 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
true);
2475 it = removedItems->erase(it);
2483bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item,
const QRectF &viewBounds)
2493 if (item->scheduledTransitionType() == QQuickItemViewTransitioner::MoveTransition)
2494 repositionItemAt(item, item->index, 0);
2496 bool success =
false;
2497 ACTION_IF_DELETED(item, success = item->prepareTransition(transitioner, viewBounds),
return success);
2500 item->releaseAfterTransition =
true;
2506void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
2508 for (
int i=0; i<releasePendingTransition.size(); i++) {
2509 if (releasePendingTransition.at(i)->transitionableItem == item) {
2510 releaseItem(releasePendingTransition.takeAt(i), reusableFlag);
2518
2519
2520
2521
2522FxViewItem *QQuickItemViewPrivate::createItem(
int modelIndex, QQmlIncubator::IncubationMode incubationMode)
2524 Q_Q(QQuickItemView);
2526 if (requestedIndex == modelIndex && incubationMode == QQmlIncubator::Asynchronous)
2529#if QT_CONFIG(quick_viewtransitions)
2530 for (
int i=0; i<releasePendingTransition.size(); i++) {
2531 if (releasePendingTransition.at(i)->index == modelIndex
2532 && !releasePendingTransition.at(i)->isPendingRemoval()) {
2533 releasePendingTransition[i]->releaseAfterTransition =
false;
2534 return releasePendingTransition.takeAt(i);
2543 QObject* object = modelIndex < model->count() ? model->object(modelIndex, incubationMode) :
nullptr;
2544 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
2548 if (requestedIndex == -1 && model->incubationStatus(modelIndex) == QQmlIncubator::Loading) {
2552 requestedIndex = modelIndex;
2555 model->release(object);
2556 if (!delegateValidated) {
2557 delegateValidated =
true;
2558 QObject* delegate = q->delegate();
2559 qmlWarning(delegate ? delegate : q) << QQuickItemView::tr(
"Delegate must be of Item type");
2568 if (qobject_cast<QQmlObjectModel *>(model))
2569 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(
this, itemChangeListenerTypes);
2571 item->setParentItem(q->contentItem());
2572 if (requestedIndex == modelIndex)
2573 requestedIndex = -1;
2574 FxViewItem *viewItem = newViewItem(modelIndex, item);
2576 viewItem->index = modelIndex;
2579 initializeViewItem(viewItem);
2580 unrequestedItems.remove(item);
2587void QQuickItemView::createdItem(
int index, QObject* object)
2589 Q_D(QQuickItemView);
2591 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2592 if (!d->inRequest) {
2593 d->unrequestedItems.insert(item, index);
2594 d->requestedIndex = -1;
2595 if (d->hasPendingChanges())
2599 if (d->unrequestedItems.contains(item))
2600 d->repositionPackageItemAt(item, index);
2601 else if (index == d->currentIndex)
2602 d->updateCurrent(index);
2606void QQuickItemView::initItem(
int, QObject *object)
2608 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2610 if (qFuzzyIsNull(item->z()))
2612 item->setParentItem(contentItem());
2613 QQuickItemPrivate::get(item)->setCulled(
true);
2618void QQuickItemView::destroyingItem(QObject *object)
2620 Q_D(QQuickItemView);
2621 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2623 item->setParentItem(
nullptr);
2624 d->unrequestedItems.remove(item);
2625 QQuickItemPrivate::get(item)->removeItemChangeListener(d, itemChangeListenerTypes);
2629void QQuickItemView::onItemPooled(
int modelIndex, QObject *object)
2631 Q_UNUSED(modelIndex);
2633 if (
auto *attached = d_func()->getAttachedObject(object))
2634 emit attached->pooled();
2637void QQuickItemView::onItemReused(
int modelIndex, QObject *object)
2639 Q_UNUSED(modelIndex);
2641 if (
auto *attached = d_func()->getAttachedObject(object))
2642 emit attached->reused();
2645bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag)
2647 Q_Q(QQuickItemView);
2650 if (trackedItem == item)
2651 trackedItem =
nullptr;
2652 item->trackGeometry(
false);
2654 QQmlInstanceModel::ReleaseFlags flags = {};
2655 if (QPointer<QQuickItem> quickItem = item->item) {
2657 flags = model->release(quickItem, reusableFlag);
2660 if (quickItem->parentItem() == contentItem) {
2663 QQuickItemPrivate::get(quickItem)->setCulled(
true);
2667 if (!isClearing && !QObjectPrivate::get(quickItem)->deleteLaterCalled)
2668 unrequestedItems.insert(quickItem, model->indexOf(quickItem, q));
2669 }
else if (flags & QQmlInstanceModel::Destroyed) {
2670 quickItem->setParentItem(
nullptr);
2671 }
else if (flags & QQmlInstanceModel::Pooled) {
2672 item->setVisible(
false);
2676 QQuickItemPrivate::get(quickItem)->removeItemChangeListener(
this, itemChangeListenerTypes);
2677#if QT_CONFIG(quick_viewtransitions)
2678 delete item->transitionableItem;
2679 item->transitionableItem =
nullptr;
2684 return flags != QQmlInstanceModel::Referenced;
2688
2689
2690
2691
2692
2693
2694
2695
2696void QQuickItemViewPrivate::itemDestroyed(QQuickItem *item)
2700 FxViewItem *visibleFxItem =
nullptr;
2701 const int indexOfItem = -1;
2702 for (
auto *fxItem : std::as_const(visibleItems)) {
2703 if (fxItem->item == item) {
2704 visibleFxItem = fxItem;
2711 if (currentItem && visibleFxItem)
2712 Q_ASSERT(currentItem != visibleFxItem);
2714 if (visibleFxItem) {
2715 qCDebug(lcItemViewDelegateLifecycle) <<
"removing deleted item"
2716 << item << visibleFxItem <<
"at index" << indexOfItem <<
"without running transitions";
2719 const bool removedVisibleFxItem = visibleItems.removeOne(visibleFxItem);
2720 Q_ASSERT(removedVisibleFxItem);
2721 releaseItem(visibleFxItem, QQmlDelegateModel::NotReusable);
2724 if (currentItem && currentItem->item == item) {
2725 releaseItem(currentItem, QQmlDelegateModel::NotReusable);
2726 currentItem =
nullptr;
2730 forceLayoutPolish();
2733QQuickItem *QQuickItemViewPrivate::createHighlightItem()
2735 QQuickItem *item =
nullptr;
2738 item = createComponentItem(highlightComponent, 0.0,
true);
2744QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue,
bool createDefault)
const
2746 Q_Q(
const QQuickItemView);
2748 QQuickItem *item =
nullptr;
2750 QQmlContext *context = component->creationContext();
2752 context = qmlContext(q);
2754 if (QObject *nobj = component->beginCreate(context)) {
2755 item = qobject_cast<QQuickItem *>(nobj);
2759 }
else if (createDefault) {
2760 item =
new QQuickItem;
2763 if (qFuzzyIsNull(item->z()))
2765 QQml_setParent_noEvent(item, q->contentItem());
2766 item->setParentItem(q->contentItem());
2768 initializeComponentItem(item);
2771 component->completeCreate();
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785void QQuickItemViewPrivate::initializeComponentItem(QQuickItem *item)
const
2790void QQuickItemViewPrivate::updateTrackedItem()
2792 Q_Q(QQuickItemView);
2793 FxViewItem *item = currentItem;
2795 item = highlight.get();
2799 q->trackedPositionChanged();
2802void QQuickItemViewPrivate::updateUnrequestedIndexes()
2804 Q_Q(QQuickItemView);
2805 for (QHash<QQuickItem*,
int>::iterator it = unrequestedItems.begin(), end = unrequestedItems.end(); it != end; ++it)
2806 *it = model->indexOf(it.key(), q);
2809void QQuickItemViewPrivate::updateUnrequestedPositions()
2811 for (QHash<QQuickItem*,
int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) {
2812 if (it.value() >= 0)
2813 repositionPackageItemAt(it.key(), it.value());
2817void QQuickItemViewPrivate::updateVisibleIndex()
2819 typedef QList<FxViewItem*>::const_iterator FxViewItemListConstIt;
2822 for (FxViewItemListConstIt it = visibleItems.constBegin(), cend = visibleItems.constEnd(); it != cend; ++it) {
2823 if ((*it)->index != -1) {
2824 visibleIndex = (*it)->index;
2830QQmlDelegateModel::DelegateModelAccess QQuickItemView::delegateModelAccess()
const
2832 Q_D(
const QQuickItemView);
2833 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->model))
2834 return dataModel->delegateModelAccess();
2835 return QQmlDelegateModel::Qt5ReadWrite;
2838void QQuickItemView::setDelegateModelAccess(
2839 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
2841 Q_D(QQuickItemView);
2842 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
2843 delegateModel->setDelegateModelAccess(delegateModelAccess);
2844 d->explicitDelegateModelAccess =
true;
2848 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2850 d->explicitDelegateModelAccess =
true;
2854 setExplicitDelegateModelAccess(QQmlDelegateModel::createForView(
this, d));
2859 emit delegateModelAccessChanged();
2863 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
2866 d->explicitDelegateModelAccess =
false;
2867 setExplicitDelegateModelAccess(delegateModel);
2871 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2872 d->explicitDelegateModelAccess =
true;
2874 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
2875 "non-DelegateModel";
2881#include "moc_qquickitemview_p.cpp"
Combined button and popup list for selecting options.
static const QQuickItemPrivate::ChangeTypes itemChangeListenerTypes
static FxViewItem * fxViewItemAtPosition(const QList< FxViewItem * > &items, qreal x, qreal y)
#define QML_VIEW_DEFAULTCACHEBUFFER