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();
869 qreal itemPos = positionAt(idx);
870 changedVisibleIndex(idx);
872 const QList<FxViewItem *> oldVisible = visibleItems;
873 visibleItems.clear();
874 setPosition(qMin(itemPos, maxExtent));
876 for (FxViewItem *item : oldVisible)
877 releaseItem(item, reusableFlag);
878 item = visibleItem(idx);
881 const bool stickyHeader = hasStickyHeader();
882 const bool stickyFooter = hasStickyFooter();
883 const qreal stickyHeaderSize = stickyHeader ? headerSize() : 0;
884 const qreal stickyFooterSize = stickyFooter ? footerSize() : 0;
886 const qreal itemPos = item->position();
888 case QQuickItemView::Beginning:
890 if (header && (index < 0 || stickyHeader))
893 case QQuickItemView::Center:
894 pos = itemPos - (viewSize - item->size())/2;
896 case QQuickItemView::End:
897 pos = itemPos - viewSize + item->size();
898 if (footer && (index >= modelCount || stickyFooter))
901 case QQuickItemView::Visible:
902 if (itemPos > pos + viewSize - stickyFooterSize)
903 pos = item->endPosition() - viewSize + stickyFooterSize;
904 else if (item->endPosition() <= pos - stickyHeaderSize)
905 pos = itemPos - stickyHeaderSize;
907 case QQuickItemView::Contain:
908 if (item->endPosition() >= pos + viewSize + stickyFooterSize)
909 pos = itemPos - viewSize + item->size() + stickyFooterSize;
910 if (itemPos - stickyHeaderSize < pos)
911 pos = itemPos - stickyHeaderSize;
913 case QQuickItemView::SnapPosition:
914 pos = itemPos - highlightRangeStart - stickyHeaderSize;
917 pos = qMin(pos, maxExtent);
918 qreal minExtent = calculatedMinExtent();
919 pos = qMax(pos, minExtent);
920 moveReason = QQuickItemViewPrivate::Other;
925 resetHighlightPosition();
932void QQuickItemView::positionViewAtIndex(
int index,
int mode)
935 if (!d->isValid() || index < 0 || index >= d->model->count())
937 d->positionViewAtIndex(index, mode);
941void QQuickItemView::positionViewAtBeginning()
946 d->positionViewAtIndex(-1, Beginning);
949void QQuickItemView::positionViewAtEnd()
954 d->positionViewAtIndex(d->model->count(), End);
959 for (FxViewItem *item : items) {
960 if (item->contains(x, y))
966int QQuickItemView::indexAt(qreal x, qreal y)
const
968 Q_D(
const QQuickItemView);
969 const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y);
970 return item ? item->index : -1;
973QQuickItem *QQuickItemView::itemAt(qreal x, qreal y)
const
975 Q_D(
const QQuickItemView);
976 const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y);
977 return item ? item->item :
nullptr;
980QQuickItem *QQuickItemView::itemAtIndex(
int index)
const
982 Q_D(
const QQuickItemView);
983 const FxViewItem *item = d->visibleItem(index);
984 return item ? item->item :
nullptr;
987void QQuickItemView::forceLayout()
990 if (isComponentComplete() && (d->currentChanges.hasPendingChanges() || d->forceLayout))
994void QQuickItemViewPrivate::applyPendingChanges()
997 if (q->isComponentComplete() && currentChanges.hasPendingChanges())
1001int QQuickItemViewPrivate::findMoveKeyIndex(QQmlChangeSet::MoveKey key,
const QVector<QQmlChangeSet::Change> &changes)
const
1003 for (
int i=0; i<changes.size(); i++) {
1004 for (
int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
1005 if (changes[i].moveKey(j) == key)
1012qreal QQuickItemViewPrivate::minExtentForAxis(
const AxisData &axisData,
bool forXAxis)
const
1014 Q_Q(
const QQuickItemView);
1016 qreal highlightStart;
1018 qreal endPositionFirstItem = 0;
1019 qreal extent = -startPosition() + axisData.startMargin;
1020 if (isContentFlowReversed()) {
1021 if (model && model->count())
1022 endPositionFirstItem = positionAt(model->count()-1);
1024 extent += headerSize();
1025 highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
1026 highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
1027 extent += footerSize();
1028 qreal maxExtentAlongAxis = forXAxis ? q->maxXExtent() : q->maxYExtent();
1029 if (extent < maxExtentAlongAxis)
1030 extent = maxExtentAlongAxis;
1032 endPositionFirstItem = endPositionAt(0);
1033 highlightStart = highlightRangeStart;
1034 highlightEnd = highlightRangeEnd;
1035 extent += headerSize();
1037 if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
1038 extent += highlightStart;
1039 FxViewItem *firstItem = visibleItem(0);
1041 extent -= firstItem->sectionSize();
1042 extent = isContentFlowReversed()
1043 ? qMin(extent, endPositionFirstItem + highlightEnd)
1044 : qMax(extent, -(endPositionFirstItem - highlightEnd));
1049qreal QQuickItemViewPrivate::maxExtentForAxis(
const AxisData &axisData,
bool forXAxis)
const
1051 Q_Q(
const QQuickItemView);
1053 qreal highlightStart;
1055 qreal lastItemPosition = 0;
1057 if (isContentFlowReversed()) {
1058 highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
1059 highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
1060 lastItemPosition = endPosition();
1062 highlightStart = highlightRangeStart;
1063 highlightEnd = highlightRangeEnd;
1064 if (model && model->count())
1065 lastItemPosition = positionAt(model->count()-1);
1067 if (!model || !model->count()) {
1068 if (!isContentFlowReversed())
1069 maxExtent = header ? -headerSize() : 0;
1070 extent += forXAxis ? q->width() : q->height();
1071 }
else if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
1072 extent = -(lastItemPosition - highlightStart);
1073 if (highlightEnd != highlightStart) {
1074 extent = isContentFlowReversed()
1075 ? qMax(extent, -(endPosition() - highlightEnd))
1076 : qMin(extent, -(endPosition() - highlightEnd));
1079 extent = -(endPosition() - (forXAxis ? q->width() : q->height()));
1081 if (isContentFlowReversed()) {
1082 extent -= headerSize();
1083 extent -= axisData.endMargin;
1085 extent -= footerSize();
1086 extent -= axisData.endMargin;
1087 qreal minExtentAlongAxis = forXAxis ? q->minXExtent() : q->minYExtent();
1088 if (extent > minExtentAlongAxis)
1089 extent = minExtentAlongAxis;
1095qreal QQuickItemViewPrivate::calculatedMinExtent()
const
1097 Q_Q(
const QQuickItemView);
1099 if (layoutOrientation() == Qt::Vertical)
1100 minExtent = isContentFlowReversed() ? q->maxYExtent() - size(): -q->minYExtent();
1102 minExtent = isContentFlowReversed() ? q->maxXExtent() - size(): -q->minXExtent();
1107qreal QQuickItemViewPrivate::calculatedMaxExtent()
const
1109 Q_Q(
const QQuickItemView);
1111 if (layoutOrientation() == Qt::Vertical)
1112 maxExtent = isContentFlowReversed() ? q->minYExtent() - size(): -q->maxYExtent();
1114 maxExtent = isContentFlowReversed() ? q->minXExtent() - size(): -q->maxXExtent();
1118void QQuickItemViewPrivate::connectModel(QQuickItemView *q, QQmlDelegateModelPointer *model)
1120 QQmlInstanceModel *instanceModel = model->instanceModel();
1124 bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
1125 QObject::connect(instanceModel, &QQmlInstanceModel::createdItem,
1126 q, &QQuickItemView::createdItem);
1127 QObject::connect(instanceModel, &QQmlInstanceModel::initItem,
1128 q, &QQuickItemView::initItem);
1129 QObject::connect(instanceModel, &QQmlInstanceModel::destroyingItem,
1130 q, &QQuickItemView::destroyingItem);
1131 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
1132 QObject::connect(delegateModel, &QQmlInstanceModel::itemPooled,
1133 q, &QQuickItemView::onItemPooled);
1134 QObject::connect(delegateModel, &QQmlInstanceModel::itemReused,
1135 q, &QQuickItemView::onItemReused);
1138 if (q->isComponentComplete()) {
1139 updateSectionCriteria();
1142
1144 q->setCurrentIndex(instanceModel->count() > 0 ? 0 : -1);
1147#if QT_CONFIG(quick_viewtransitions)
1148 if (transitioner && transitioner->populateTransition) {
1149 transitioner->setPopulateTransitionEnabled(
true);
1150 forceLayoutPolish();
1155 QObject::connect(instanceModel, &QQmlInstanceModel::modelUpdated,
1156 q, &QQuickItemView::modelUpdated);
1157 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
1158 QObjectPrivate::connect(
1159 dataModel, &QQmlDelegateModel::delegateChanged,
1160 this, &QQuickItemViewPrivate::applyDelegateChange);
1161 QObjectPrivate::connect(
1162 dataModel, &QQmlDelegateModel::delegateModelAccessChanged,
1163 this, &QQuickItemViewPrivate::applyDelegateModelAccessChange);
1165 QObject::connect(dataModel, &QQmlDelegateModel::modelChanged,
1166 q, &QQuickItemView::modelChanged);
1173void QQuickItemViewPrivate::disconnectModel(QQuickItemView *q, QQmlDelegateModelPointer *model)
1175 QQmlInstanceModel *instanceModel = model->instanceModel();
1180 QObject::disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
1181 q, &QQuickItemView::modelUpdated);
1182 QObject::disconnect(instanceModel, &QQmlInstanceModel::initItem,
1183 q, &QQuickItemView::initItem);
1184 QObject::disconnect(instanceModel, &QQmlInstanceModel::createdItem,
1185 q, &QQuickItemView::createdItem);
1186 QObject::disconnect(instanceModel, &QQmlInstanceModel::destroyingItem,
1187 q, &QQuickItemView::destroyingItem);
1188 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
1189 QObject::disconnect(delegateModel, &QQmlInstanceModel::itemPooled,
1190 q, &QQuickItemView::onItemPooled);
1191 QObject::disconnect(delegateModel, &QQmlInstanceModel::itemReused,
1192 q, &QQuickItemView::onItemReused);
1193 QObjectPrivate::disconnect(
1194 delegateModel, &QQmlDelegateModel::delegateChanged,
1195 this, &QQuickItemViewPrivate::applyDelegateChange);
1196 QObjectPrivate::disconnect(
1197 delegateModel, &QQmlDelegateModel::delegateModelAccessChanged,
1198 this, &QQuickItemViewPrivate::applyDelegateModelAccessChange);
1200 QObject::disconnect(delegateModel, &QQmlDelegateModel::modelChanged,
1201 q, &QQuickItemView::modelChanged);
1206void QQuickItemViewPrivate::applyDelegateChange()
1208 Q_Q(QQuickItemView);
1210 QQmlDelegateModel::applyDelegateChangeOnView(q,
this);
1212 releaseVisibleItems(QQmlDelegateModel::NotReusable);
1213 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1214 updateSectionCriteria();
1216 moveReason = QQuickItemViewPrivate::SetIndex;
1217 updateCurrent(currentIndex);
1218 if (highlight && currentItem) {
1220 resetHighlightPosition();
1221 updateTrackedItem();
1223 moveReason = QQuickItemViewPrivate::Other;
1228void QQuickItemViewPrivate::checkVisible()
const
1231 for (
int i = 0; i < visibleItems.size(); ++i) {
1232 FxViewItem *item = visibleItems.at(i);
1233 if (item->index == -1) {
1235 }
else if (item->index != visibleIndex + i - skip) {
1236 qFatal(
"index %d %d %d", visibleIndex, i, item->index);
1242void QQuickItemViewPrivate::showVisibleItems()
const
1244 qDebug() <<
"Visible items:";
1245 for (FxViewItem *item : visibleItems) {
1246 qDebug() <<
"\t" << item->index
1247 << item->item->objectName()
1248 << item->position();
1253void QQuickItemViewPrivate::emitCountChanged()
1255 Q_Q(QQuickItemView);
1256 qCDebug(lcCount).nospace() <<
"about to emit countChanged for " << q <<
"; count changed to " << q->count();
1257 emit q->countChanged();
1260void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change,
1261 const QRectF &oldGeometry)
1263 Q_Q(QQuickItemView);
1264 QQuickFlickablePrivate::itemGeometryChanged(item, change, oldGeometry);
1265 if (!q->isComponentComplete())
1268 if (header && header->item == item) {
1272 if (!q->isMoving() && !q->isFlicking())
1274 }
else if (footer && footer->item == item) {
1278 if (!q->isMoving() && !q->isFlicking())
1282 if (currentItem && currentItem->item == item) {
1285 bool prevInLayout = inLayout;
1286#if QT_CONFIG(quick_viewtransitions)
1288 FxViewItem *actualItem = transitioner ? visibleItem(currentIndex) :
nullptr;
1289 if (actualItem && actualItem->transitionRunning())
1294 inLayout = prevInLayout;
1297 if (trackedItem && trackedItem->item == item)
1298 q->trackedPositionChanged();
1301void QQuickItemView::destroyRemoved()
1303 Q_D(QQuickItemView);
1305#if QT_CONFIG(quick_viewtransitions)
1306 bool hasRemoveTransition =
false;
1307 bool hasRemoveTransitionAsTarget =
false;
1308 if (d->transitioner) {
1309 hasRemoveTransition = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false);
1310 hasRemoveTransitionAsTarget = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true);
1314 for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
1315 it != d->visibleItems.end();) {
1316 FxViewItem *item = *it;
1317 if (item->index == -1 && (!item->attached || item->attached->delayRemove() ==
false)) {
1318#if QT_CONFIG(quick_viewtransitions)
1319 if (hasRemoveTransitionAsTarget) {
1321 d->runDelayedRemoveTransition =
true;
1322 QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()),
this, SLOT(destroyRemoved()));
1325 if (hasRemoveTransition)
1326 d->runDelayedRemoveTransition =
true;
1328 d->releaseItem(item, d->reusableFlag);
1329 it = d->visibleItems.erase(it);
1330#if QT_CONFIG(quick_viewtransitions)
1339 d->forceLayoutPolish();
1342void QQuickItemView::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
1344 Q_D(QQuickItemView);
1347#if QT_CONFIG(quick_viewtransitions)
1348 if (d->transitioner)
1349 d->transitioner->setPopulateTransitionEnabled(
true);
1351 d->moveReason = QQuickItemViewPrivate::SetIndex;
1353 if (d->highlight && d->currentItem) {
1354 if (d->autoHighlight)
1355 d->resetHighlightPosition();
1356 d->updateTrackedItem();
1358 d->moveReason = QQuickItemViewPrivate::Other;
1359 d->emitCountChanged();
1360#if QT_CONFIG(quick_viewtransitions)
1361 if (d->transitioner && d->transitioner->populateTransition)
1362 d->forceLayoutPolish();
1366 d->bufferedChanges.prepare(d->currentIndex, d->itemCount);
1367 d->bufferedChanges.applyChanges(changeSet);
1369 if (d->bufferedChanges.hasPendingChanges()) {
1370 d->currentChanges.applyBufferedChanges(d->bufferedChanges);
1371 d->bufferedChanges.reset();
1373 d->currentChanges.prepare(d->currentIndex, d->itemCount);
1374 d->currentChanges.applyChanges(changeSet);
1380void QQuickItemView::animStopped()
1382 Q_D(QQuickItemView);
1383 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
1384 d->refillOrLayout();
1385 if (d->haveHighlightRange && d->highlightRange == QQuickItemView::StrictlyEnforceRange)
1386 d->updateHighlight();
1390void QQuickItemView::trackedPositionChanged()
1392 Q_D(QQuickItemView);
1393 if (!d->trackedItem || !d->currentItem)
1401 const bool needMoveToTrackHighlight = d->autoHighlight || d->highlightRange != NoHighlightRange;
1403 if (d->moveReason == QQuickItemViewPrivate::SetIndex && needMoveToTrackHighlight) {
1404 qreal trackedPos = d->trackedItem->position();
1405 qreal trackedSize = d->trackedItem->size();
1406 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
1407 qreal pos = viewPos;
1408 if (d->haveHighlightRange) {
1409 if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
1410 pos = trackedPos - d->highlightRangeEnd + trackedSize;
1411 if (trackedPos < pos + d->highlightRangeStart)
1412 pos = trackedPos - d->highlightRangeStart;
1413 if (d->highlightRange != StrictlyEnforceRange) {
1414 qreal maxExtent = d->calculatedMaxExtent();
1415 if (pos > maxExtent)
1417 qreal minExtent = d->calculatedMinExtent();
1418 if (pos < minExtent)
1422 if (d->trackedItem != d->currentItem) {
1424 trackedPos -= d->currentItem->sectionSize();
1425 trackedSize += d->currentItem->sectionSize();
1427 qreal trackedEndPos = d->trackedItem->endPosition();
1428 qreal toItemPos = d->currentItem->position();
1429 qreal toItemEndPos = d->currentItem->endPosition();
1430 if (d->showHeaderForIndex(d->currentIndex)) {
1431 qreal startOffset = -d->contentStartOffset();
1432 trackedPos -= startOffset;
1433 trackedEndPos -= startOffset;
1434 toItemPos -= startOffset;
1435 toItemEndPos -= startOffset;
1436 }
else if (d->showFooterForIndex(d->currentIndex)) {
1437 qreal endOffset = d->footerSize();
1438 if (d->layoutOrientation() == Qt::Vertical) {
1439 if (d->isContentFlowReversed())
1440 endOffset += d->vData.startMargin;
1442 endOffset += d->vData.endMargin;
1444 if (d->isContentFlowReversed())
1445 endOffset += d->hData.startMargin;
1447 endOffset += d->hData.endMargin;
1449 trackedPos += endOffset;
1450 trackedEndPos += endOffset;
1451 toItemPos += endOffset;
1452 toItemEndPos += endOffset;
1455 if (trackedEndPos >= viewPos + d->size()
1456 && toItemEndPos >= viewPos + d->size()) {
1457 if (trackedEndPos <= toItemEndPos) {
1458 pos = trackedEndPos - d->size();
1459 if (trackedSize > d->size())
1462 pos = toItemEndPos - d->size();
1463 if (d->currentItem->size() > d->size())
1464 pos = d->currentItem->position();
1467 if (trackedPos < pos && toItemPos < pos)
1468 pos = qMax(trackedPos, toItemPos);
1470 if (viewPos != pos) {
1471 d->calcVelocity =
true;
1472 d->setPosition(pos);
1473 d->calcVelocity =
false;
1478void QQuickItemView::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
1480 Q_D(QQuickItemView);
1481 d->markExtentsDirty();
1482 if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty()))
1483 d->forceLayoutPolish();
1484 QQuickFlickable::geometryChange(newGeometry, oldGeometry);
1487qreal QQuickItemView::minYExtent()
const
1489 Q_D(
const QQuickItemView);
1490 if (d->layoutOrientation() == Qt::Horizontal)
1491 return QQuickFlickable::minYExtent();
1493 if (d->vData.minExtentDirty) {
1494 d->minExtent = d->minExtentForAxis(d->vData,
false);
1495 d->vData.minExtentDirty =
false;
1498 return d->minExtent;
1501qreal QQuickItemView::maxYExtent()
const
1503 Q_D(
const QQuickItemView);
1504 if (d->layoutOrientation() == Qt::Horizontal)
1505 return QQuickFlickable::maxYExtent();
1507 if (d->vData.maxExtentDirty) {
1508 d->maxExtent = d->maxExtentForAxis(d->vData,
false);
1509 d->vData.maxExtentDirty =
false;
1512 return d->maxExtent;
1515qreal QQuickItemView::minXExtent()
const
1517 Q_D(
const QQuickItemView);
1518 if (d->layoutOrientation() == Qt::Vertical)
1519 return QQuickFlickable::minXExtent();
1521 if (d->hData.minExtentDirty) {
1522 d->minExtent = d->minExtentForAxis(d->hData,
true);
1523 d->hData.minExtentDirty =
false;
1526 return d->minExtent;
1529qreal QQuickItemView::maxXExtent()
const
1531 Q_D(
const QQuickItemView);
1532 if (d->layoutOrientation() == Qt::Vertical)
1533 return QQuickFlickable::maxXExtent();
1535 if (d->hData.maxExtentDirty) {
1536 d->maxExtent = d->maxExtentForAxis(d->hData,
true);
1537 d->hData.maxExtentDirty =
false;
1540 return d->maxExtent;
1543void QQuickItemView::setContentX(qreal pos)
1545 Q_D(QQuickItemView);
1547 d->moveReason = QQuickItemViewPrivate::Other;
1548 QQuickFlickable::setContentX(pos);
1551void QQuickItemView::setContentY(qreal pos)
1553 Q_D(QQuickItemView);
1555 d->moveReason = QQuickItemViewPrivate::Other;
1556 QQuickFlickable::setContentY(pos);
1559qreal QQuickItemView::originX()
const
1561 Q_D(
const QQuickItemView);
1562 if (d->layoutOrientation() == Qt::Horizontal
1563 && effectiveLayoutDirection() == Qt::RightToLeft
1564 && contentWidth() < width()) {
1565 return -d->lastPosition() - d->footerSize();
1567 return QQuickFlickable::originX();
1570qreal QQuickItemView::originY()
const
1572 Q_D(
const QQuickItemView);
1573 if (d->layoutOrientation() == Qt::Vertical
1574 && d->verticalLayoutDirection == QQuickItemView::BottomToTop
1575 && contentHeight() < height()) {
1576 return -d->lastPosition() - d->footerSize();
1578 return QQuickFlickable::originY();
1581void QQuickItemView::updatePolish()
1583 Q_D(QQuickItemView);
1584 QQuickFlickable::updatePolish();
1588void QQuickItemView::componentComplete()
1590 Q_D(QQuickItemView);
1591 if (d->model && d->ownModel)
1592 static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
1594 QQuickFlickable::componentComplete();
1596 d->updateSectionCriteria();
1599 d->updateViewport();
1600 d->setPosition(d->contentStartOffset());
1601#if QT_CONFIG(quick_viewtransitions)
1602 if (d->transitioner)
1603 d->transitioner->setPopulateTransitionEnabled(
true);
1608 d->moveReason = QQuickItemViewPrivate::SetIndex;
1609 if (d->currentIndex < 0 && !d->currentIndexCleared)
1610 d->updateCurrent(0);
1612 d->updateCurrent(d->currentIndex);
1613 if (d->highlight && d->currentItem) {
1614 if (d->autoHighlight)
1615 d->resetHighlightPosition();
1616 d->updateTrackedItem();
1618 d->moveReason = QQuickItemViewPrivate::Other;
1621 if (d->model && d->model->count())
1622 d->emitCountChanged();
1627QQuickItemViewPrivate::QQuickItemViewPrivate()
1630 , displayMarginBeginning(0), displayMarginEnd(0)
1631 , layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom)
1633 , currentIndex(-1), currentItem(
nullptr)
1634 , trackedItem(
nullptr), requestedIndex(-1)
1635 , highlightComponent(
nullptr), highlight(
nullptr)
1636 , highlightRange(QQuickItemView::NoHighlightRange)
1637 , highlightRangeStart(0), highlightRangeEnd(0)
1638 , highlightMoveDuration(150)
1639 , headerComponent(
nullptr), header(
nullptr), footerComponent(
nullptr), footer(
nullptr)
1640#if QT_CONFIG(quick_viewtransitions)
1641 , transitioner(
nullptr)
1643 , minExtent(0), maxExtent(0)
1644 , ownModel(
false), wrap(
false)
1645 , keyNavigationEnabled(
true)
1646 , explicitKeyNavigationEnabled(
false)
1647 , inLayout(
false), inViewportMoved(
false), forceLayout(
false), currentIndexCleared(
false)
1648 , haveHighlightRange(
false), autoHighlight(
true), highlightRangeStartValid(
false), highlightRangeEndValid(
false)
1649 , fillCacheBuffer(
false), inRequest(
false)
1650#if QT_CONFIG(quick_viewtransitions)
1651 , runDelayedRemoveTransition(
false)
1653 , delegateValidated(
false)
1655 , explicitDelegate(
false)
1656 , explicitDelegateModelAccess(
false)
1658 bufferPause.addAnimationChangeListener(
this, QAbstractAnimationJob::Completion);
1659 bufferPause.setLoopCount(1);
1660 bufferPause.setDuration(16);
1665QQuickItemViewPrivate::~QQuickItemViewPrivate()
1667#if QT_CONFIG(quick_viewtransitions)
1669 transitioner->setChangeListener(
nullptr);
1670 delete transitioner;
1674bool QQuickItemViewPrivate::isValid()
const
1676 return model && model->count() && model->isValid();
1679qreal QQuickItemViewPrivate::position()
const
1681 Q_Q(
const QQuickItemView);
1682 return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
1685qreal QQuickItemViewPrivate::size()
const
1687 Q_Q(
const QQuickItemView);
1688 return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
1691qreal QQuickItemViewPrivate::startPosition()
const
1693 return isContentFlowReversed() ? -lastPosition() : originPosition();
1696qreal QQuickItemViewPrivate::endPosition()
const
1698 return isContentFlowReversed() ? -originPosition() : lastPosition();
1701qreal QQuickItemViewPrivate::contentStartOffset()
const
1703 qreal pos = -headerSize();
1704 if (layoutOrientation() == Qt::Vertical) {
1705 if (isContentFlowReversed())
1706 pos -= vData.endMargin;
1708 pos -= vData.startMargin;
1710 if (isContentFlowReversed())
1711 pos -= hData.endMargin;
1713 pos -= hData.startMargin;
1718int QQuickItemViewPrivate::findLastVisibleIndex(
int defaultValue)
const
1720 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1722 if (item->index != -1)
1725 return defaultValue;
1728FxViewItem *QQuickItemViewPrivate::visibleItem(
int modelIndex)
const {
1729 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.size()) {
1730 for (
int i = modelIndex - visibleIndex; i < visibleItems.size(); ++i) {
1731 FxViewItem *item = visibleItems.at(i);
1732 if (item->index == modelIndex)
1739FxViewItem *QQuickItemViewPrivate::firstItemInView()
const {
1740 const qreal pos = isContentFlowReversed() ? -position()-size() : position();
1741 for (FxViewItem *item : visibleItems) {
1742 if (item->index != -1 && item->endPosition() > pos)
1745 return visibleItems.size() ? visibleItems.first() : 0;
1748int QQuickItemViewPrivate::findLastIndexInView()
const
1750 const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
1751 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1753 if (item->index != -1 && item->position() <= viewEndPos)
1762int QQuickItemViewPrivate::mapFromModel(
int modelIndex)
const
1764 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.size())
1766 for (
int i = 0; i < visibleItems.size(); ++i) {
1767 FxViewItem *item = visibleItems.at(i);
1768 if (item->index == modelIndex)
1770 if (item->index > modelIndex)
1776void QQuickItemViewPrivate::init()
1778 Q_Q(QQuickItemView);
1779 q->setFlag(QQuickItem::ItemIsFocusScope);
1780 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
1781 QObject::connect(q, &QQuickFlickable::interactiveChanged, q, &QQuickItemView::keyNavigationEnabledChanged);
1782 q->setFlickableDirection(QQuickFlickable::VerticalFlick);
1785void QQuickItemViewPrivate::updateCurrent(
int modelIndex)
1787 Q_Q(QQuickItemView);
1788 applyPendingChanges();
1789 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
1791 if (currentItem->attached)
1792 currentItem->attached->setIsCurrentItem(
false);
1793 releaseCurrentItem(reusableFlag);
1794 currentIndex = modelIndex;
1795 emit q->currentIndexChanged();
1796 emit q->currentItemChanged();
1798 }
else if (currentIndex != modelIndex) {
1799 currentIndex = modelIndex;
1800 emit q->currentIndexChanged();
1805 if (currentItem && currentIndex == modelIndex) {
1810 FxViewItem *oldCurrentItem = currentItem;
1811 int oldCurrentIndex = currentIndex;
1812 currentIndex = modelIndex;
1813 currentItem = createItem(modelIndex, QQmlIncubator::AsynchronousIfNested);
1814 if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
1815 oldCurrentItem->attached->setIsCurrentItem(
false);
1817 currentItem->item->setFocus(
true);
1818 if (currentItem->attached)
1819 currentItem->attached->setIsCurrentItem(
true);
1820 initializeCurrentItem();
1824 if (oldCurrentIndex != currentIndex)
1825 emit q->currentIndexChanged();
1826 if (oldCurrentItem != currentItem
1827 && (!oldCurrentItem || !currentItem || oldCurrentItem->item != currentItem->item))
1828 emit q->currentItemChanged();
1829 releaseItem(oldCurrentItem, reusableFlag);
1832void QQuickItemViewPrivate::clear(
bool onDestruction)
1834 Q_Q(QQuickItemView);
1837 auto cleanup = qScopeGuard([
this] { isClearing =
false; });
1839 currentChanges.reset();
1840 bufferedChanges.reset();
1843 releaseVisibleItems(QQmlInstanceModel::NotReusable);
1846#if QT_CONFIG(quick_viewtransitions)
1847 for (FxViewItem *item : std::as_const(releasePendingTransition)) {
1848 item->releaseAfterTransition =
false;
1849 releaseItem(item, QQmlInstanceModel::NotReusable);
1851 releasePendingTransition.clear();
1854 const bool hadCurrentItem = currentItem !=
nullptr;
1855 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1857 emit q->currentItemChanged();
1858 createHighlight(onDestruction);
1859 trackedItem =
nullptr;
1861 if (requestedIndex >= 0) {
1863 model->cancel(requestedIndex);
1864 requestedIndex = -1;
1872void QQuickItemViewPrivate::mirrorChange()
1874 Q_Q(QQuickItemView);
1876 emit q->effectiveLayoutDirectionChanged();
1879void QQuickItemViewPrivate::animationFinished(QAbstractAnimationJob *)
1881 Q_Q(QQuickItemView);
1882 fillCacheBuffer =
true;
1886void QQuickItemViewPrivate::refill()
1888 qreal s = qMax(size(), qreal(0.));
1889 const auto pos = position();
1890 if (isContentFlowReversed())
1891 refill(-pos - displayMarginBeginning-s, -pos + displayMarginEnd);
1893 refill(pos - displayMarginBeginning, pos + displayMarginEnd+s);
1896void QQuickItemViewPrivate::refill(qreal from, qreal to)
1898 Q_Q(QQuickItemView);
1899 if (!model || !model->isValid() || !q->isComponentComplete())
1901 if (q->size().isNull() && visibleItems.isEmpty())
1903 if (!model->count()) {
1912 if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) {
1913 currentChanges.reset();
1914 bufferedChanges.reset();
1915 releaseVisibleItems(reusableFlag);
1918 int prevCount = itemCount;
1919 itemCount = model->count();
1920 qreal bufferFrom = from - buffer;
1921 qreal bufferTo = to + buffer;
1922 qreal fillFrom = from;
1925 bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
false);
1927 if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
1931 bufferPause.start();
1933 if (bufferMode & BufferAfter)
1935 if (bufferMode & BufferBefore)
1936 fillFrom = bufferFrom;
1937 added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
true);
1941 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
1943 if (added || removed) {
1945 updateBeginningEnd();
1946 visibleItemsChanged();
1952 if (prevCount != itemCount)
1954 }
while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges());
1955 storeFirstVisibleItemPosition();
1958void QQuickItemViewPrivate::regenerate(
bool orientationChanged)
1960 Q_Q(QQuickItemView);
1961 if (q->isComponentComplete()) {
1962 if (orientationChanged) {
1972 setPosition(contentStartOffset());
1974 updateCurrent(currentIndex);
1978void QQuickItemViewPrivate::updateViewport()
1980 Q_Q(QQuickItemView);
1981 qreal extra = headerSize() + footerSize();
1982 qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
1983 if (layoutOrientation() == Qt::Vertical)
1984 q->setContentHeight(contentSize + extra);
1986 q->setContentWidth(contentSize + extra);
1989void QQuickItemViewPrivate::layout()
1991 Q_Q(QQuickItemView);
1998 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2003 if ((!isValid() && !visibleItems.size()) || q->size().isNull()) {
2004 if (q->size().isNull() && hasPendingChanges()) {
2015 setPosition(contentStartOffset());
2017#if QT_CONFIG(quick_viewtransitions)
2019 transitioner->setPopulateTransitionEnabled(
false);
2025#if QT_CONFIG(quick_viewtransitions)
2026 if (runDelayedRemoveTransition && transitioner
2027 && transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2030 for (
int i=0; i<visibleItems.size(); i++)
2031 visibleItems[i]->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2035 ChangeResult insertionPosChanges;
2036 ChangeResult removalPosChanges;
2037 if (!applyModelChanges(&insertionPosChanges, &removalPosChanges) && !forceLayout) {
2038 if (fillCacheBuffer) {
2039 fillCacheBuffer =
false;
2045 forceLayout =
false;
2047#if QT_CONFIG(quick_viewtransitions)
2048 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true)) {
2052 for (FxViewItem *item : std::as_const(visibleItems)) {
2053 if (!item->transitionScheduledOrRunning())
2054 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition,
true);
2060 layoutVisibleItems();
2061 storeFirstVisibleItemPosition();
2063#if QT_CONFIG(quick_viewtransitions)
2064 int lastIndexInView = findLastIndexInView();
2070 if (!q->isMoving() && !q->isFlicking() && !movingFromHighlight()) {
2078 updateUnrequestedPositions();
2080#if QT_CONFIG(quick_viewtransitions)
2084 if (lastIndexInView != -1 &&
2085 (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
false)
2086 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false))) {
2087 translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
2090 prepareVisibleItemTransitions();
2093 for (
int i = 0, count = releasePendingTransition.size(); i < count;) {
2094 auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds);
2099 const int old_count = count;
2100 count = releasePendingTransition.size();
2101 if (old_count > count)
2105 releaseItem(releasePendingTransition[i], reusableFlag);
2106 releasePendingTransition.remove(i);
2113 for (
int i=0; i<visibleItems.size(); i++)
2114 visibleItems[i]->startTransition(transitioner);
2115 for (
int i=0; i<releasePendingTransition.size(); i++)
2116 releasePendingTransition[i]->startTransition(transitioner);
2118 transitioner->setPopulateTransitionEnabled(
false);
2119 transitioner->resetTargetLists();
2124 updateCurrent(currentIndex);
2126#if QT_CONFIG(quick_viewtransitions)
2127 runDelayedRemoveTransition =
false;
2132bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult)
2134 Q_Q(QQuickItemView);
2135 if (!q->isComponentComplete() || !hasPendingChanges())
2138 if (bufferedChanges.hasPendingChanges()) {
2139 currentChanges.applyBufferedChanges(bufferedChanges);
2140 bufferedChanges.reset();
2143 updateUnrequestedIndexes();
2145 FxViewItem *prevVisibleItemsFirst = visibleItems.size() ? *visibleItems.constBegin() :
nullptr;
2146 int prevItemCount = itemCount;
2147 int prevVisibleItemsCount = visibleItems.size();
2148 bool visibleAffected =
false;
2149 bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
2150 || !currentChanges.pendingChanges.inserts().isEmpty();
2152 FxViewItem *prevFirstItemInView = firstItemInView();
2153 QQmlNullableValue<qreal> prevFirstItemInViewPos;
2154 int prevFirstItemInViewIndex = -1;
2155 if (prevFirstItemInView) {
2156 prevFirstItemInViewPos = prevFirstItemInView->position();
2157 prevFirstItemInViewIndex = prevFirstItemInView->index;
2159 qreal prevVisibleItemsFirstPos = visibleItems.size() ? firstVisibleItemPosition : 0.0;
2161 totalInsertionResult->visiblePos = prevFirstItemInViewPos;
2162 totalRemovalResult->visiblePos = prevFirstItemInViewPos;
2164 const QVector<QQmlChangeSet::Change> &removals = currentChanges.pendingChanges.removes();
2165 const QVector<QQmlChangeSet::Change> &insertions = currentChanges.pendingChanges.inserts();
2166 ChangeResult insertionResult(prevFirstItemInViewPos);
2167 ChangeResult removalResult(prevFirstItemInViewPos);
2169 int removedCount = 0;
2170 for (
const QQmlChangeSet::Change &r : removals) {
2171 itemCount -= r.count;
2172 if (applyRemovalChange(r, &removalResult, &removedCount))
2173 visibleAffected =
true;
2174 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(r.index))
2175 visibleAffected =
true;
2176 const int correctedFirstVisibleIndex = prevFirstItemInViewIndex - removalResult.countChangeBeforeVisible;
2177 if (correctedFirstVisibleIndex >= 0 && r.index < correctedFirstVisibleIndex) {
2178 if (r.index + r.count < correctedFirstVisibleIndex)
2179 removalResult.countChangeBeforeVisible += r.count;
2181 removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - r.index);
2184#if QT_CONFIG(quick_viewtransitions)
2185 if (runDelayedRemoveTransition) {
2186 QQmlChangeSet::Change removal;
2187 for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
2188 FxViewItem *item = *it;
2189 if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) {
2190 removeItem(item, removal, &removalResult);
2192 it = visibleItems.erase(it);
2199 *totalRemovalResult += removalResult;
2200 if (!removals.isEmpty()) {
2201 updateVisibleIndex();
2204 if (!insertions.isEmpty()) {
2205 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2206 layoutVisibleItems(removals.first().index);
2207 storeFirstVisibleItemPosition();
2211 QList<FxViewItem *> newItems;
2212 QList<MovedItem> movingIntoView;
2214 for (
int i=0; i<insertions.size(); i++) {
2215 bool wasEmpty = visibleItems.isEmpty();
2216 if (applyInsertionChange(insertions[i], &insertionResult, &newItems, &movingIntoView))
2217 visibleAffected =
true;
2218 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index))
2219 visibleAffected =
true;
2220 if (wasEmpty && !visibleItems.isEmpty())
2221 resetFirstItemPosition();
2222 *totalInsertionResult += insertionResult;
2225 if (i < insertions.size() - 1) {
2226 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2227 layoutVisibleItems(insertions[i].index);
2228 storeFirstVisibleItemPosition();
2230 itemCount += insertions[i].count;
2232 for (FxViewItem *item : std::as_const(newItems)) {
2234 item->attached->emitAdd();
2237#if QT_CONFIG(quick_viewtransitions)
2241 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
true)) {
2242 for (
const MovedItem &m : std::as_const(movingIntoView)) {
2243 int fromIndex = findMoveKeyIndex(m.moveKey, removals);
2244 if (fromIndex >= 0) {
2245 if (prevFirstItemInViewIndex >= 0 && fromIndex < prevFirstItemInViewIndex)
2246 repositionItemAt(m.item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
2248 repositionItemAt(m.item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
2249 m.item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2256 if (removedCount != prevVisibleItemsCount)
2257 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2260#if QT_CONFIG(quick_viewtransitions)
2261 prepareRemoveTransitions(¤tChanges.removedItems);
2263 for (
auto it = currentChanges.removedItems.begin();
2264 it != currentChanges.removedItems.end(); ++it) {
2265 releaseItem(it.value(), reusableFlag);
2267 currentChanges.removedItems.clear();
2269 if (currentChanges.currentChanged) {
2270 if (currentChanges.currentRemoved && currentItem) {
2271 if (currentItem->item && currentItem->attached)
2272 currentItem->attached->setIsCurrentItem(
false);
2273 const bool hadCurrentItem = currentItem !=
nullptr;
2274 releaseCurrentItem(reusableFlag);
2276 emit q->currentItemChanged();
2278 if (!currentIndexCleared)
2279 updateCurrent(currentChanges.newCurrentIndex);
2282 if (!visibleAffected)
2283 visibleAffected = !currentChanges.pendingChanges.changes().isEmpty();
2284 currentChanges.reset();
2287 if (prevItemCount != itemCount)
2289 if (!visibleAffected && viewportChanged)
2292 return visibleAffected;
2295bool QQuickItemViewPrivate::applyRemovalChange(
const QQmlChangeSet::Change &removal, ChangeResult *removeResult,
int *removedCount)
2297 Q_Q(QQuickItemView);
2298 bool visibleAffected =
false;
2300 if (visibleItems.size() && removal.index + removal.count > visibleItems.constLast()->index) {
2301 if (removal.index > visibleItems.constLast()->index)
2302 removeResult->countChangeAfterVisibleItems += removal.count;
2304 removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.constLast()->index);
2307 QList<FxViewItem*>::Iterator it = visibleItems.begin();
2308 while (it != visibleItems.end()) {
2309 FxViewItem *item = *it;
2310 if (item->index == -1 || item->index < removal.index) {
2312 if (!visibleAffected && item->index < removal.index)
2313 visibleAffected =
true;
2315 }
else if (item->index >= removal.index + removal.count) {
2317 item->index -= removal.count;
2318#if QT_CONFIG(quick_viewtransitions)
2319 if (removal.isMove())
2320 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
false);
2322 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2327 visibleAffected =
true;
2328 if (!removal.isMove() && item->item && item->attached)
2329 item->attached->emitRemove();
2331 if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) {
2333 QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
2336 removeItem(item, removal, removeResult);
2337 if (!removal.isMove())
2339 it = visibleItems.erase(it);
2344 return visibleAffected;
2347void QQuickItemViewPrivate::removeItem(FxViewItem *item,
const QQmlChangeSet::Change &removal, ChangeResult *removeResult)
2349 if (removeResult->visiblePos.isValid()) {
2350 if (item->position() < removeResult->visiblePos)
2351 updateSizeChangesBeforeVisiblePos(item, removeResult);
2353 removeResult->sizeChangesAfterVisiblePos += item->size();
2355 if (removal.isMove()) {
2356 currentChanges.removedItems.replace(removal.moveKey(item->index), item);
2357#if QT_CONFIG(quick_viewtransitions)
2358 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2362 currentChanges.removedItems.insert(QQmlChangeSet::MoveKey(), item);
2364 if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
2365 removeResult->changedFirstItem =
true;
2368void QQuickItemViewPrivate::updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
2370 removeResult->sizeChangesBeforeVisiblePos += item->size();
2373void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
2374 qreal prevVisibleItemsFirstPos,
2375 FxViewItem *prevFirstVisible,
2376 ChangeResult *insertionResult,
2377 ChangeResult *removalResult)
2379 const QQmlNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
2382 if (visibleItems.size()) {
2383 if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
2384 resetFirstItemPosition(prevVisibleItemsFirstPos);
2386 if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible
2387 && prevFirstVisible != *visibleItems.constBegin()) {
2390 if (!insertionResult->changedFirstItem)
2391 resetFirstItemPosition(prevVisibleItemsFirstPos);
2393 }
else if (prevViewPos.isValid()) {
2394 qreal moveForwardsBy = 0;
2395 qreal moveBackwardsBy = 0;
2398 const auto pos = visibleItems.constFirst()->position();
2399 if (pos > prevViewPos) {
2400 moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
2401 moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
2402 }
else if (pos < prevViewPos) {
2403 moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
2404 moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
2406 adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->countChangeBeforeVisible - removalResult->countChangeBeforeVisible);
2408 insertionResult->reset();
2409 removalResult->reset();
2413#if QT_CONFIG(quick_viewtransitions)
2414void QQuickItemViewPrivate::createTransitioner()
2416 if (!transitioner) {
2417 transitioner =
new QQuickItemViewTransitioner;
2418 transitioner->setChangeListener(
this);
2422void QQuickItemViewPrivate::prepareVisibleItemTransitions()
2424 Q_Q(QQuickItemView);
2429 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2430 for (
int i=0; i<visibleItems.size(); i++)
2431 visibleItems[i]->prepareTransition(transitioner, viewBounds);
2434void QQuickItemViewPrivate::prepareRemoveTransitions(QMultiHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems)
2439 if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true)
2440 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2441 for (
auto it = removedItems->begin(); it != removedItems->end(); ) {
2442 bool isRemove = it.key().moveId < 0;
2444 FxViewItem *item = *it;
2445 item->trackGeometry(
false);
2446 item->releaseAfterTransition =
true;
2447 releasePendingTransition.append(item);
2448 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
true);
2449 it = removedItems->erase(it);
2457bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item,
const QRectF &viewBounds)
2467 if (item->scheduledTransitionType() == QQuickItemViewTransitioner::MoveTransition)
2468 repositionItemAt(item, item->index, 0);
2470 bool success =
false;
2471 ACTION_IF_DELETED(item, success = item->prepareTransition(transitioner, viewBounds),
return success);
2474 item->releaseAfterTransition =
true;
2480void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
2482 for (
int i=0; i<releasePendingTransition.size(); i++) {
2483 if (releasePendingTransition.at(i)->transitionableItem == item) {
2484 releaseItem(releasePendingTransition.takeAt(i), reusableFlag);
2492
2493
2494
2495
2496FxViewItem *QQuickItemViewPrivate::createItem(
int modelIndex, QQmlIncubator::IncubationMode incubationMode)
2498 Q_Q(QQuickItemView);
2500 if (requestedIndex == modelIndex && incubationMode == QQmlIncubator::Asynchronous)
2503#if QT_CONFIG(quick_viewtransitions)
2504 for (
int i=0; i<releasePendingTransition.size(); i++) {
2505 if (releasePendingTransition.at(i)->index == modelIndex
2506 && !releasePendingTransition.at(i)->isPendingRemoval()) {
2507 releasePendingTransition[i]->releaseAfterTransition =
false;
2508 return releasePendingTransition.takeAt(i);
2517 QObject* object = modelIndex < model->count() ? model->object(modelIndex, incubationMode) :
nullptr;
2518 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
2522 if (requestedIndex == -1 && model->incubationStatus(modelIndex) == QQmlIncubator::Loading) {
2526 requestedIndex = modelIndex;
2529 model->release(object);
2530 if (!delegateValidated) {
2531 delegateValidated =
true;
2532 QObject* delegate = q->delegate();
2533 qmlWarning(delegate ? delegate : q) << QQuickItemView::tr(
"Delegate must be of Item type");
2542 if (qobject_cast<QQmlObjectModel *>(model))
2543 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(
this, itemChangeListenerTypes);
2545 item->setParentItem(q->contentItem());
2546 if (requestedIndex == modelIndex)
2547 requestedIndex = -1;
2548 FxViewItem *viewItem = newViewItem(modelIndex, item);
2550 viewItem->index = modelIndex;
2553 initializeViewItem(viewItem);
2554 unrequestedItems.remove(item);
2561void QQuickItemView::createdItem(
int index, QObject* object)
2563 Q_D(QQuickItemView);
2565 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2566 if (!d->inRequest) {
2567 d->unrequestedItems.insert(item, index);
2568 d->requestedIndex = -1;
2569 if (d->hasPendingChanges())
2573 if (d->unrequestedItems.contains(item))
2574 d->repositionPackageItemAt(item, index);
2575 else if (index == d->currentIndex)
2576 d->updateCurrent(index);
2580void QQuickItemView::initItem(
int, QObject *object)
2582 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2584 if (qFuzzyIsNull(item->z()))
2586 item->setParentItem(contentItem());
2587 QQuickItemPrivate::get(item)->setCulled(
true);
2592void QQuickItemView::destroyingItem(QObject *object)
2594 Q_D(QQuickItemView);
2595 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2597 item->setParentItem(
nullptr);
2598 d->unrequestedItems.remove(item);
2599 QQuickItemPrivate::get(item)->removeItemChangeListener(d, itemChangeListenerTypes);
2603void QQuickItemView::onItemPooled(
int modelIndex, QObject *object)
2605 Q_UNUSED(modelIndex);
2607 if (
auto *attached = d_func()->getAttachedObject(object))
2608 emit attached->pooled();
2611void QQuickItemView::onItemReused(
int modelIndex, QObject *object)
2613 Q_UNUSED(modelIndex);
2615 if (
auto *attached = d_func()->getAttachedObject(object))
2616 emit attached->reused();
2619bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag)
2621 Q_Q(QQuickItemView);
2624 if (trackedItem == item)
2625 trackedItem =
nullptr;
2626 item->trackGeometry(
false);
2628 QQmlInstanceModel::ReleaseFlags flags = {};
2629 if (QPointer<QQuickItem> quickItem = item->item) {
2631 flags = model->release(quickItem, reusableFlag);
2634 if (quickItem->parentItem() == contentItem) {
2637 QQuickItemPrivate::get(quickItem)->setCulled(
true);
2641 if (!isClearing && !QObjectPrivate::get(quickItem)->deleteLaterCalled)
2642 unrequestedItems.insert(quickItem, model->indexOf(quickItem, q));
2643 }
else if (flags & QQmlInstanceModel::Destroyed) {
2644 quickItem->setParentItem(
nullptr);
2645 }
else if (flags & QQmlInstanceModel::Pooled) {
2646 item->setVisible(
false);
2650 QQuickItemPrivate::get(quickItem)->removeItemChangeListener(
this, itemChangeListenerTypes);
2651 delete item->transitionableItem;
2652 item->transitionableItem =
nullptr;
2656 return flags != QQmlInstanceModel::Referenced;
2660
2661
2662
2663
2664
2665
2666
2667
2668void QQuickItemViewPrivate::itemDestroyed(QQuickItem *item)
2672 FxViewItem *visibleFxItem =
nullptr;
2673 const int indexOfItem = -1;
2674 for (
auto *fxItem : std::as_const(visibleItems)) {
2675 if (fxItem->item == item) {
2676 visibleFxItem = fxItem;
2683 if (currentItem && visibleFxItem)
2684 Q_ASSERT(currentItem != visibleFxItem);
2686 if (visibleFxItem) {
2687 qCDebug(lcItemViewDelegateLifecycle) <<
"removing deleted item"
2688 << item << visibleFxItem <<
"at index" << indexOfItem <<
"without running transitions";
2691 const bool removedVisibleFxItem = visibleItems.removeOne(visibleFxItem);
2692 Q_ASSERT(removedVisibleFxItem);
2693 releaseItem(visibleFxItem, QQmlDelegateModel::NotReusable);
2696 if (currentItem && currentItem->item == item) {
2697 releaseItem(currentItem, QQmlDelegateModel::NotReusable);
2698 currentItem =
nullptr;
2702 forceLayoutPolish();
2705QQuickItem *QQuickItemViewPrivate::createHighlightItem()
2707 QQuickItem *item =
nullptr;
2710 item = createComponentItem(highlightComponent, 0.0,
true);
2716QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue,
bool createDefault)
const
2718 Q_Q(
const QQuickItemView);
2720 QQuickItem *item =
nullptr;
2722 QQmlContext *context = component->creationContext();
2724 context = qmlContext(q);
2726 if (QObject *nobj = component->beginCreate(context)) {
2727 item = qobject_cast<QQuickItem *>(nobj);
2731 }
else if (createDefault) {
2732 item =
new QQuickItem;
2735 if (qFuzzyIsNull(item->z()))
2737 QQml_setParent_noEvent(item, q->contentItem());
2738 item->setParentItem(q->contentItem());
2740 initializeComponentItem(item);
2743 component->completeCreate();
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757void QQuickItemViewPrivate::initializeComponentItem(QQuickItem *item)
const
2762void QQuickItemViewPrivate::updateTrackedItem()
2764 Q_Q(QQuickItemView);
2765 FxViewItem *item = currentItem;
2767 item = highlight.get();
2771 q->trackedPositionChanged();
2774void QQuickItemViewPrivate::updateUnrequestedIndexes()
2776 Q_Q(QQuickItemView);
2777 for (QHash<QQuickItem*,
int>::iterator it = unrequestedItems.begin(), end = unrequestedItems.end(); it != end; ++it)
2778 *it = model->indexOf(it.key(), q);
2781void QQuickItemViewPrivate::updateUnrequestedPositions()
2783 for (QHash<QQuickItem*,
int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) {
2784 if (it.value() >= 0)
2785 repositionPackageItemAt(it.key(), it.value());
2789void QQuickItemViewPrivate::updateVisibleIndex()
2791 typedef QList<FxViewItem*>::const_iterator FxViewItemListConstIt;
2794 for (FxViewItemListConstIt it = visibleItems.constBegin(), cend = visibleItems.constEnd(); it != cend; ++it) {
2795 if ((*it)->index != -1) {
2796 visibleIndex = (*it)->index;
2802QQmlDelegateModel::DelegateModelAccess QQuickItemView::delegateModelAccess()
const
2804 Q_D(
const QQuickItemView);
2805 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->model))
2806 return dataModel->delegateModelAccess();
2807 return QQmlDelegateModel::Qt5ReadWrite;
2810void QQuickItemView::setDelegateModelAccess(
2811 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
2813 Q_D(QQuickItemView);
2814 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
2815 delegateModel->setDelegateModelAccess(delegateModelAccess);
2816 d->explicitDelegateModelAccess =
true;
2820 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2822 d->explicitDelegateModelAccess =
true;
2826 setExplicitDelegateModelAccess(QQmlDelegateModel::createForView(
this, d));
2831 emit delegateModelAccessChanged();
2835 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
2838 d->explicitDelegateModelAccess =
false;
2839 setExplicitDelegateModelAccess(delegateModel);
2843 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2844 d->explicitDelegateModelAccess =
true;
2846 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
2847 "non-DelegateModel";
2853#include "moc_qquickitemview_p.cpp"
static const QQuickItemPrivate::ChangeTypes itemChangeListenerTypes
static FxViewItem * fxViewItemAtPosition(const QList< FxViewItem * > &items, qreal x, qreal y)
#define QML_VIEW_DEFAULTCACHEBUFFER