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 QList<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)
1659 bufferPause.addAnimationChangeListener(
this, QAbstractAnimationJob::Completion);
1660 bufferPause.setLoopCount(1);
1661 bufferPause.setDuration(16);
1666QQuickItemViewPrivate::~QQuickItemViewPrivate()
1668#if QT_CONFIG(quick_viewtransitions)
1670 transitioner->setChangeListener(
nullptr);
1671 delete transitioner;
1675bool QQuickItemViewPrivate::isValid()
const
1677 return model && model->count() && model->isValid();
1680qreal QQuickItemViewPrivate::position()
const
1682 Q_Q(
const QQuickItemView);
1683 return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
1686qreal QQuickItemViewPrivate::size()
const
1688 Q_Q(
const QQuickItemView);
1689 return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
1692qreal QQuickItemViewPrivate::startPosition()
const
1694 return isContentFlowReversed() ? -lastPosition() : originPosition();
1697qreal QQuickItemViewPrivate::endPosition()
const
1699 return isContentFlowReversed() ? -originPosition() : lastPosition();
1702qreal QQuickItemViewPrivate::contentStartOffset()
const
1704 qreal pos = -headerSize();
1705 if (layoutOrientation() == Qt::Vertical) {
1706 if (isContentFlowReversed())
1707 pos -= vData.endMargin;
1709 pos -= vData.startMargin;
1711 if (isContentFlowReversed())
1712 pos -= hData.endMargin;
1714 pos -= hData.startMargin;
1719int QQuickItemViewPrivate::findLastVisibleIndex(
int defaultValue)
const
1721 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1723 if (item->index != -1)
1726 return defaultValue;
1729FxViewItem *QQuickItemViewPrivate::visibleItem(
int modelIndex)
const {
1730 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.size()) {
1731 for (
int i = modelIndex - visibleIndex; i < visibleItems.size(); ++i) {
1732 FxViewItem *item = visibleItems.at(i);
1733 if (item->index == modelIndex)
1740FxViewItem *QQuickItemViewPrivate::firstItemInView()
const {
1741 const qreal pos = isContentFlowReversed() ? -position()-size() : position();
1742 for (FxViewItem *item : visibleItems) {
1743 if (item->index != -1 && item->endPosition() > pos)
1746 return visibleItems.size() ? visibleItems.first() : 0;
1749int QQuickItemViewPrivate::findLastIndexInView()
const
1751 const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
1752 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1754 if (item->index != -1 && item->position() <= viewEndPos)
1763int QQuickItemViewPrivate::mapFromModel(
int modelIndex)
const
1765 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.size())
1767 for (
int i = 0; i < visibleItems.size(); ++i) {
1768 FxViewItem *item = visibleItems.at(i);
1769 if (item->index == modelIndex)
1771 if (item->index > modelIndex)
1777void QQuickItemViewPrivate::init()
1779 Q_Q(QQuickItemView);
1780 q->setFlag(QQuickItem::ItemIsFocusScope);
1781 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
1782 QObject::connect(q, &QQuickFlickable::interactiveChanged, q, &QQuickItemView::keyNavigationEnabledChanged);
1783 q->setFlickableDirection(QQuickFlickable::VerticalFlick);
1786void QQuickItemViewPrivate::updateCurrent(
int modelIndex)
1788 Q_Q(QQuickItemView);
1789 applyPendingChanges();
1790 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
1792 if (currentItem->attached)
1793 currentItem->attached->setIsCurrentItem(
false);
1794 releaseCurrentItem(reusableFlag);
1795 currentIndex = modelIndex;
1796 emit q->currentIndexChanged();
1797 emit q->currentItemChanged();
1799 }
else if (currentIndex != modelIndex) {
1800 currentIndex = modelIndex;
1801 emit q->currentIndexChanged();
1806 if (currentItem && currentIndex == modelIndex) {
1811 FxViewItem *oldCurrentItem = currentItem;
1812 int oldCurrentIndex = currentIndex;
1813 currentIndex = modelIndex;
1814 currentItem = createItem(modelIndex, QQmlIncubator::AsynchronousIfNested);
1815 if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
1816 oldCurrentItem->attached->setIsCurrentItem(
false);
1818 currentItem->item->setFocus(
true);
1819 if (currentItem->attached)
1820 currentItem->attached->setIsCurrentItem(
true);
1821 initializeCurrentItem();
1825 if (oldCurrentIndex != currentIndex)
1826 emit q->currentIndexChanged();
1827 if (oldCurrentItem != currentItem
1828 && (!oldCurrentItem || !currentItem || oldCurrentItem->item != currentItem->item))
1829 emit q->currentItemChanged();
1830 releaseItem(oldCurrentItem, reusableFlag);
1833void QQuickItemViewPrivate::clear(
bool onDestruction)
1835 Q_Q(QQuickItemView);
1838 auto cleanup = qScopeGuard([
this] { isClearing =
false; });
1840 currentChanges.reset();
1841 bufferedChanges.reset();
1844 releaseVisibleItems(QQmlInstanceModel::NotReusable);
1847#if QT_CONFIG(quick_viewtransitions)
1848 for (FxViewItem *item : std::as_const(releasePendingTransition)) {
1849 item->releaseAfterTransition =
false;
1850 releaseItem(item, QQmlInstanceModel::NotReusable);
1852 releasePendingTransition.clear();
1855 const bool hadCurrentItem = currentItem !=
nullptr;
1856 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1858 emit q->currentItemChanged();
1859 createHighlight(onDestruction);
1860 trackedItem =
nullptr;
1862 if (requestedIndex >= 0) {
1864 model->cancel(requestedIndex);
1865 requestedIndex = -1;
1873void QQuickItemViewPrivate::mirrorChange()
1875 Q_Q(QQuickItemView);
1877 emit q->effectiveLayoutDirectionChanged();
1880void QQuickItemViewPrivate::animationFinished(QAbstractAnimationJob *)
1882 Q_Q(QQuickItemView);
1883 fillCacheBuffer =
true;
1887void QQuickItemViewPrivate::refill()
1889 qreal s = qMax(size(), qreal(0.));
1890 const auto pos = position();
1891 if (isContentFlowReversed())
1892 refill(-pos - displayMarginBeginning-s, -pos + displayMarginEnd);
1894 refill(pos - displayMarginBeginning, pos + displayMarginEnd+s);
1897void QQuickItemViewPrivate::refill(qreal from, qreal to)
1899 Q_Q(QQuickItemView);
1900 if (!model || !model->isValid() || !q->isComponentComplete())
1902 if (q->size().isNull() && visibleItems.isEmpty())
1904 if (!model->count()) {
1917 if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) {
1918 currentChanges.reset();
1919 bufferedChanges.reset();
1920 releaseVisibleItems(reusableFlag);
1923 int prevCount = itemCount;
1924 itemCount = model->count();
1925 qreal bufferFrom = from - buffer;
1926 qreal bufferTo = to + buffer;
1927 qreal fillFrom = from;
1930 bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
false);
1932 if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
1936 bufferPause.start();
1938 if (bufferMode & BufferAfter)
1940 if (bufferMode & BufferBefore)
1941 fillFrom = bufferFrom;
1942 added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
true);
1946 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
1948 if (added || removed) {
1950 updateBeginningEnd();
1951 visibleItemsChanged();
1957 if (prevCount != itemCount)
1959 }
while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges());
1960 storeFirstVisibleItemPosition();
1964void QQuickItemViewPrivate::regenerate(
bool orientationChanged)
1966 Q_Q(QQuickItemView);
1967 if (q->isComponentComplete()) {
1968 if (orientationChanged) {
1978 setPosition(contentStartOffset());
1980 updateCurrent(currentIndex);
1984void QQuickItemViewPrivate::updateViewport()
1986 Q_Q(QQuickItemView);
1987 qreal extra = headerSize() + footerSize();
1988 qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
1989 if (layoutOrientation() == Qt::Vertical)
1990 q->setContentHeight(contentSize + extra);
1992 q->setContentWidth(contentSize + extra);
1995void QQuickItemViewPrivate::layout()
1997 Q_Q(QQuickItemView);
2004 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2009 if ((!isValid() && !visibleItems.size()) || q->size().isNull()) {
2010 if (q->size().isNull() && hasPendingChanges()) {
2021 setPosition(contentStartOffset());
2023#if QT_CONFIG(quick_viewtransitions)
2025 transitioner->setPopulateTransitionEnabled(
false);
2031#if QT_CONFIG(quick_viewtransitions)
2032 if (runDelayedRemoveTransition && transitioner
2033 && transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2036 for (
int i=0; i<visibleItems.size(); i++)
2037 visibleItems[i]->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2041 ChangeResult insertionPosChanges;
2042 ChangeResult removalPosChanges;
2043 if (!applyModelChanges(&insertionPosChanges, &removalPosChanges) && !forceLayout) {
2044 if (fillCacheBuffer) {
2045 fillCacheBuffer =
false;
2051 forceLayout =
false;
2053#if QT_CONFIG(quick_viewtransitions)
2054 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true)) {
2058 for (FxViewItem *item : std::as_const(visibleItems)) {
2059 if (!item->transitionScheduledOrRunning())
2060 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition,
true);
2066 layoutVisibleItems();
2067 storeFirstVisibleItemPosition();
2069#if QT_CONFIG(quick_viewtransitions)
2070 int lastIndexInView = findLastIndexInView();
2076 if (!q->isMoving() && !q->isFlicking() && !movingFromHighlight()) {
2084 updateUnrequestedPositions();
2086#if QT_CONFIG(quick_viewtransitions)
2090 if (lastIndexInView != -1 &&
2091 (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
false)
2092 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false))) {
2093 translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
2096 prepareVisibleItemTransitions();
2099 for (
int i = 0, count = releasePendingTransition.size(); i < count;) {
2100 auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds);
2105 const int old_count = count;
2106 count = releasePendingTransition.size();
2107 if (old_count > count)
2111 releaseItem(releasePendingTransition[i], reusableFlag);
2112 releasePendingTransition.remove(i);
2119 for (
int i=0; i<visibleItems.size(); i++)
2120 visibleItems[i]->startTransition(transitioner);
2121 for (
int i=0; i<releasePendingTransition.size(); i++)
2122 releasePendingTransition[i]->startTransition(transitioner);
2124 transitioner->setPopulateTransitionEnabled(
false);
2125 transitioner->resetTargetLists();
2130 updateCurrent(currentIndex);
2132#if QT_CONFIG(quick_viewtransitions)
2133 runDelayedRemoveTransition =
false;
2138bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult)
2140 Q_Q(QQuickItemView);
2141 if (!q->isComponentComplete() || !hasPendingChanges())
2144 if (bufferedChanges.hasPendingChanges()) {
2145 currentChanges.applyBufferedChanges(bufferedChanges);
2146 bufferedChanges.reset();
2149 updateUnrequestedIndexes();
2151 FxViewItem *prevVisibleItemsFirst = visibleItems.size() ? *visibleItems.constBegin() :
nullptr;
2152 int prevItemCount = itemCount;
2153 int prevVisibleItemsCount = visibleItems.size();
2154 bool visibleAffected =
false;
2155 bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
2156 || !currentChanges.pendingChanges.inserts().isEmpty();
2158 FxViewItem *prevFirstItemInView = firstItemInView();
2159 QQmlNullableValue<qreal> prevFirstItemInViewPos;
2160 int prevFirstItemInViewIndex = -1;
2161 if (prevFirstItemInView) {
2162 prevFirstItemInViewPos = prevFirstItemInView->position();
2163 prevFirstItemInViewIndex = prevFirstItemInView->index;
2165 qreal prevVisibleItemsFirstPos = visibleItems.size() ? firstVisibleItemPosition : 0.0;
2167 totalInsertionResult->visiblePos = prevFirstItemInViewPos;
2168 totalRemovalResult->visiblePos = prevFirstItemInViewPos;
2170 const QList<QQmlChangeSet::Change> &removals = currentChanges.pendingChanges.removes();
2171 const QList<QQmlChangeSet::Change> &insertions = currentChanges.pendingChanges.inserts();
2172 ChangeResult insertionResult(prevFirstItemInViewPos);
2173 ChangeResult removalResult(prevFirstItemInViewPos);
2175 int removedCount = 0;
2176 for (
const QQmlChangeSet::Change &r : removals) {
2177 itemCount -= r.count;
2178 if (applyRemovalChange(r, &removalResult, &removedCount))
2179 visibleAffected =
true;
2180 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(r.index))
2181 visibleAffected =
true;
2182 const int correctedFirstVisibleIndex = prevFirstItemInViewIndex - removalResult.countChangeBeforeVisible;
2183 if (correctedFirstVisibleIndex >= 0 && r.index < correctedFirstVisibleIndex) {
2184 if (r.index + r.count < correctedFirstVisibleIndex)
2185 removalResult.countChangeBeforeVisible += r.count;
2187 removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - r.index);
2190#if QT_CONFIG(quick_viewtransitions)
2191 if (runDelayedRemoveTransition) {
2192 QQmlChangeSet::Change removal;
2193 for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
2194 FxViewItem *item = *it;
2195 if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) {
2196 removeItem(item, removal, &removalResult);
2198 it = visibleItems.erase(it);
2205 *totalRemovalResult += removalResult;
2206 if (!removals.isEmpty()) {
2207 updateVisibleIndex();
2210 if (!insertions.isEmpty()) {
2211 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2212 layoutVisibleItems(removals.first().index);
2213 storeFirstVisibleItemPosition();
2217 QList<FxViewItem *> newItems;
2218 QList<MovedItem> movingIntoView;
2220 for (
int i=0; i<insertions.size(); i++) {
2221 bool wasEmpty = visibleItems.isEmpty();
2222 if (applyInsertionChange(insertions[i], &insertionResult, &newItems, &movingIntoView))
2223 visibleAffected =
true;
2224 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index))
2225 visibleAffected =
true;
2226 if (wasEmpty && !visibleItems.isEmpty())
2227 resetFirstItemPosition();
2228 *totalInsertionResult += insertionResult;
2231 if (i < insertions.size() - 1) {
2232 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2233 layoutVisibleItems(insertions[i].index);
2234 storeFirstVisibleItemPosition();
2236 itemCount += insertions[i].count;
2238 for (FxViewItem *item : std::as_const(newItems)) {
2240 item->attached->emitAdd();
2243#if QT_CONFIG(quick_viewtransitions)
2247 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
true)) {
2248 for (
const MovedItem &m : std::as_const(movingIntoView)) {
2249 int fromIndex = findMoveKeyIndex(m.moveKey, removals);
2250 if (fromIndex >= 0) {
2251 if (prevFirstItemInViewIndex >= 0 && fromIndex < prevFirstItemInViewIndex)
2252 repositionItemAt(m.item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
2254 repositionItemAt(m.item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
2255 m.item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2262 if (removedCount != prevVisibleItemsCount)
2263 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2266#if QT_CONFIG(quick_viewtransitions)
2267 prepareRemoveTransitions(¤tChanges.removedItems);
2269 for (
auto it = currentChanges.removedItems.begin();
2270 it != currentChanges.removedItems.end(); ++it) {
2271 releaseItem(it.value(), reusableFlag);
2273 currentChanges.removedItems.clear();
2275 if (currentChanges.currentChanged) {
2276 if (currentChanges.currentRemoved && currentItem) {
2277 if (currentItem->item && currentItem->attached)
2278 currentItem->attached->setIsCurrentItem(
false);
2279 const bool hadCurrentItem = currentItem !=
nullptr;
2280 releaseCurrentItem(reusableFlag);
2282 emit q->currentItemChanged();
2284 if (!currentIndexCleared)
2285 updateCurrent(currentChanges.newCurrentIndex);
2288 if (!visibleAffected)
2289 visibleAffected = !currentChanges.pendingChanges.changes().isEmpty();
2290 currentChanges.reset();
2293 if (prevItemCount != itemCount)
2295 if (!visibleAffected && viewportChanged)
2298 return visibleAffected;
2301bool QQuickItemViewPrivate::applyRemovalChange(
const QQmlChangeSet::Change &removal, ChangeResult *removeResult,
int *removedCount)
2303 Q_Q(QQuickItemView);
2304 bool visibleAffected =
false;
2306 if (visibleItems.size() && removal.index + removal.count > visibleItems.constLast()->index) {
2307 if (removal.index > visibleItems.constLast()->index)
2308 removeResult->countChangeAfterVisibleItems += removal.count;
2310 removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.constLast()->index);
2313 QList<FxViewItem*>::Iterator it = visibleItems.begin();
2314 while (it != visibleItems.end()) {
2315 FxViewItem *item = *it;
2316 if (item->index == -1 || item->index < removal.index) {
2318 if (!visibleAffected && item->index < removal.index)
2319 visibleAffected =
true;
2321 }
else if (item->index >= removal.index + removal.count) {
2323 item->index -= removal.count;
2324#if QT_CONFIG(quick_viewtransitions)
2325 if (removal.isMove())
2326 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
false);
2328 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2333 visibleAffected =
true;
2334 if (!removal.isMove() && item->item && item->attached)
2335 item->attached->emitRemove();
2337 if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) {
2339 QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
2342 removeItem(item, removal, removeResult);
2343 if (!removal.isMove())
2345 it = visibleItems.erase(it);
2350 return visibleAffected;
2353void QQuickItemViewPrivate::removeItem(FxViewItem *item,
const QQmlChangeSet::Change &removal, ChangeResult *removeResult)
2355 if (removeResult->visiblePos.isValid()) {
2356 if (item->position() < removeResult->visiblePos)
2357 updateSizeChangesBeforeVisiblePos(item, removeResult);
2359 removeResult->sizeChangesAfterVisiblePos += item->size();
2361 if (removal.isMove()) {
2362 currentChanges.removedItems.replace(removal.moveKey(item->index), item);
2363#if QT_CONFIG(quick_viewtransitions)
2364 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2368 currentChanges.removedItems.insert(QQmlChangeSet::MoveKey(), item);
2370 if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
2371 removeResult->changedFirstItem =
true;
2374void QQuickItemViewPrivate::updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
2376 removeResult->sizeChangesBeforeVisiblePos += item->size();
2379void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
2380 qreal prevVisibleItemsFirstPos,
2381 FxViewItem *prevFirstVisible,
2382 ChangeResult *insertionResult,
2383 ChangeResult *removalResult)
2385 const QQmlNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
2388 if (visibleItems.size()) {
2389 if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
2390 resetFirstItemPosition(prevVisibleItemsFirstPos);
2392 if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible
2393 && prevFirstVisible != *visibleItems.constBegin()) {
2396 if (!insertionResult->changedFirstItem)
2397 resetFirstItemPosition(prevVisibleItemsFirstPos);
2399 }
else if (prevViewPos.isValid()) {
2400 qreal moveForwardsBy = 0;
2401 qreal moveBackwardsBy = 0;
2404 const auto pos = visibleItems.constFirst()->position();
2405 if (pos > prevViewPos) {
2406 moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
2407 moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
2408 }
else if (pos < prevViewPos) {
2409 moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
2410 moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
2412 adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->countChangeBeforeVisible - removalResult->countChangeBeforeVisible);
2414 insertionResult->reset();
2415 removalResult->reset();
2419#if QT_CONFIG(quick_viewtransitions)
2420void QQuickItemViewPrivate::createTransitioner()
2422 if (!transitioner) {
2423 transitioner =
new QQuickItemViewTransitioner;
2424 transitioner->setChangeListener(
this);
2428void QQuickItemViewPrivate::prepareVisibleItemTransitions()
2430 Q_Q(QQuickItemView);
2435 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2436 for (
int i=0; i<visibleItems.size(); i++)
2437 visibleItems[i]->prepareTransition(transitioner, viewBounds);
2440void QQuickItemViewPrivate::prepareRemoveTransitions(QMultiHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems)
2445 if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true)
2446 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2447 for (
auto it = removedItems->begin(); it != removedItems->end(); ) {
2448 bool isRemove = it.key().moveId < 0;
2450 FxViewItem *item = *it;
2451 item->trackGeometry(
false);
2452 item->releaseAfterTransition =
true;
2453 releasePendingTransition.append(item);
2454 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
true);
2455 it = removedItems->erase(it);
2463bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item,
const QRectF &viewBounds)
2473 if (item->scheduledTransitionType() == QQuickItemViewTransitioner::MoveTransition)
2474 repositionItemAt(item, item->index, 0);
2476 bool success =
false;
2477 ACTION_IF_DELETED(item, success = item->prepareTransition(transitioner, viewBounds),
return success);
2480 item->releaseAfterTransition =
true;
2486void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
2488 for (
int i=0; i<releasePendingTransition.size(); i++) {
2489 if (releasePendingTransition.at(i)->transitionableItem == item) {
2490 releaseItem(releasePendingTransition.takeAt(i), reusableFlag);
2498
2499
2500
2501
2502FxViewItem *QQuickItemViewPrivate::createItem(
int modelIndex, QQmlIncubator::IncubationMode incubationMode)
2504 Q_Q(QQuickItemView);
2506 if (requestedIndex == modelIndex && incubationMode == QQmlIncubator::Asynchronous)
2509#if QT_CONFIG(quick_viewtransitions)
2510 for (
int i=0; i<releasePendingTransition.size(); i++) {
2511 if (releasePendingTransition.at(i)->index == modelIndex
2512 && !releasePendingTransition.at(i)->isPendingRemoval()) {
2513 releasePendingTransition[i]->releaseAfterTransition =
false;
2514 return releasePendingTransition.takeAt(i);
2523 QObject* object = modelIndex < model->count() ? model->object(modelIndex, incubationMode) :
nullptr;
2524 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
2528 if (requestedIndex == -1 && model->incubationStatus(modelIndex) == QQmlIncubator::Loading) {
2532 requestedIndex = modelIndex;
2535 model->release(object);
2536 if (!delegateValidated) {
2537 delegateValidated =
true;
2538 QObject* delegate = q->delegate();
2539 qmlWarning(delegate ? delegate : q) << QQuickItemView::tr(
"Delegate must be of Item type");
2548 if (qobject_cast<QQmlObjectModel *>(model))
2549 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(
this, itemChangeListenerTypes);
2551 item->setParentItem(q->contentItem());
2552 if (requestedIndex == modelIndex)
2553 requestedIndex = -1;
2554 FxViewItem *viewItem = newViewItem(modelIndex, item);
2556 viewItem->index = modelIndex;
2559 initializeViewItem(viewItem);
2560 unrequestedItems.remove(item);
2567void QQuickItemView::createdItem(
int index, QObject* object)
2569 Q_D(QQuickItemView);
2571 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2572 if (!d->inRequest) {
2573 d->unrequestedItems.insert(item, index);
2574 d->requestedIndex = -1;
2575 if (d->hasPendingChanges())
2579 if (d->unrequestedItems.contains(item))
2580 d->repositionPackageItemAt(item, index);
2581 else if (index == d->currentIndex)
2582 d->updateCurrent(index);
2586void QQuickItemView::initItem(
int, QObject *object)
2588 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2590 if (qFuzzyIsNull(item->z()))
2592 item->setParentItem(contentItem());
2593 QQuickItemPrivate::get(item)->setCulled(
true);
2598void QQuickItemView::destroyingItem(QObject *object)
2600 Q_D(QQuickItemView);
2601 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2603 item->setParentItem(
nullptr);
2604 d->unrequestedItems.remove(item);
2605 QQuickItemPrivate::get(item)->removeItemChangeListener(d, itemChangeListenerTypes);
2609void QQuickItemView::onItemPooled(
int modelIndex, QObject *object)
2611 Q_UNUSED(modelIndex);
2613 if (
auto *attached = d_func()->getAttachedObject(object))
2614 emit attached->pooled();
2617void QQuickItemView::onItemReused(
int modelIndex, QObject *object)
2619 Q_UNUSED(modelIndex);
2621 if (
auto *attached = d_func()->getAttachedObject(object))
2622 emit attached->reused();
2625bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag)
2627 Q_Q(QQuickItemView);
2630 if (trackedItem == item)
2631 trackedItem =
nullptr;
2632 item->trackGeometry(
false);
2634 QQmlInstanceModel::ReleaseFlags flags = {};
2635 if (QPointer<QQuickItem> quickItem = item->item) {
2637 flags = model->release(quickItem, reusableFlag);
2640 if (quickItem->parentItem() == contentItem) {
2643 QQuickItemPrivate::get(quickItem)->setCulled(
true);
2647 if (!isClearing && !QObjectPrivate::get(quickItem)->deleteLaterCalled)
2648 unrequestedItems.insert(quickItem, model->indexOf(quickItem, q));
2649 }
else if (flags & QQmlInstanceModel::Destroyed) {
2650 quickItem->setParentItem(
nullptr);
2651 }
else if (flags & QQmlInstanceModel::Pooled) {
2652 item->setVisible(
false);
2656 QQuickItemPrivate::get(quickItem)->removeItemChangeListener(
this, itemChangeListenerTypes);
2657 delete item->transitionableItem;
2658 item->transitionableItem =
nullptr;
2662 return flags != QQmlInstanceModel::Referenced;
2666
2667
2668
2669
2670
2671
2672
2673
2674void QQuickItemViewPrivate::itemDestroyed(QQuickItem *item)
2678 FxViewItem *visibleFxItem =
nullptr;
2679 const int indexOfItem = -1;
2680 for (
auto *fxItem : std::as_const(visibleItems)) {
2681 if (fxItem->item == item) {
2682 visibleFxItem = fxItem;
2689 if (currentItem && visibleFxItem)
2690 Q_ASSERT(currentItem != visibleFxItem);
2692 if (visibleFxItem) {
2693 qCDebug(lcItemViewDelegateLifecycle) <<
"removing deleted item"
2694 << item << visibleFxItem <<
"at index" << indexOfItem <<
"without running transitions";
2697 const bool removedVisibleFxItem = visibleItems.removeOne(visibleFxItem);
2698 Q_ASSERT(removedVisibleFxItem);
2699 releaseItem(visibleFxItem, QQmlDelegateModel::NotReusable);
2702 if (currentItem && currentItem->item == item) {
2703 releaseItem(currentItem, QQmlDelegateModel::NotReusable);
2704 currentItem =
nullptr;
2708 forceLayoutPolish();
2711QQuickItem *QQuickItemViewPrivate::createHighlightItem()
2713 QQuickItem *item =
nullptr;
2716 item = createComponentItem(highlightComponent, 0.0,
true);
2722QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue,
bool createDefault)
const
2724 Q_Q(
const QQuickItemView);
2726 QQuickItem *item =
nullptr;
2728 QQmlContext *context = component->creationContext();
2730 context = qmlContext(q);
2732 if (QObject *nobj = component->beginCreate(context)) {
2733 item = qobject_cast<QQuickItem *>(nobj);
2737 }
else if (createDefault) {
2738 item =
new QQuickItem;
2741 if (qFuzzyIsNull(item->z()))
2743 QQml_setParent_noEvent(item, q->contentItem());
2744 item->setParentItem(q->contentItem());
2746 initializeComponentItem(item);
2749 component->completeCreate();
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763void QQuickItemViewPrivate::initializeComponentItem(QQuickItem *item)
const
2768void QQuickItemViewPrivate::updateTrackedItem()
2770 Q_Q(QQuickItemView);
2771 FxViewItem *item = currentItem;
2773 item = highlight.get();
2777 q->trackedPositionChanged();
2780void QQuickItemViewPrivate::updateUnrequestedIndexes()
2782 Q_Q(QQuickItemView);
2783 for (QHash<QQuickItem*,
int>::iterator it = unrequestedItems.begin(), end = unrequestedItems.end(); it != end; ++it)
2784 *it = model->indexOf(it.key(), q);
2787void QQuickItemViewPrivate::updateUnrequestedPositions()
2789 for (QHash<QQuickItem*,
int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) {
2790 if (it.value() >= 0)
2791 repositionPackageItemAt(it.key(), it.value());
2795void QQuickItemViewPrivate::updateVisibleIndex()
2797 typedef QList<FxViewItem*>::const_iterator FxViewItemListConstIt;
2800 for (FxViewItemListConstIt it = visibleItems.constBegin(), cend = visibleItems.constEnd(); it != cend; ++it) {
2801 if ((*it)->index != -1) {
2802 visibleIndex = (*it)->index;
2808QQmlDelegateModel::DelegateModelAccess QQuickItemView::delegateModelAccess()
const
2810 Q_D(
const QQuickItemView);
2811 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->model))
2812 return dataModel->delegateModelAccess();
2813 return QQmlDelegateModel::Qt5ReadWrite;
2816void QQuickItemView::setDelegateModelAccess(
2817 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
2819 Q_D(QQuickItemView);
2820 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
2821 delegateModel->setDelegateModelAccess(delegateModelAccess);
2822 d->explicitDelegateModelAccess =
true;
2826 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2828 d->explicitDelegateModelAccess =
true;
2832 setExplicitDelegateModelAccess(QQmlDelegateModel::createForView(
this, d));
2837 emit delegateModelAccessChanged();
2841 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
2844 d->explicitDelegateModelAccess =
false;
2845 setExplicitDelegateModelAccess(delegateModel);
2849 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2850 d->explicitDelegateModelAccess =
true;
2852 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
2853 "non-DelegateModel";
2859#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