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
22constexpr QQuickItemPrivate::ChangeTypes itemChangeListenerTypes = QQuickItemPrivate::Destroyed;
24FxViewItem::FxViewItem(QQuickItem *i, QQuickItemView *v,
bool own, QQuickItemViewAttached *attached)
25 : QQuickItemViewFxItem(i, own, QQuickItemViewPrivate::get(v))
31QQuickItemViewChangeSet::QQuickItemViewChangeSet()
37bool QQuickItemViewChangeSet::hasPendingChanges()
const
39 return !pendingChanges.isEmpty();
42void QQuickItemViewChangeSet::applyChanges(
const QQmlChangeSet &changeSet)
44 pendingChanges.apply(changeSet);
49 for (
const QQmlChangeSet::Change &r : changeSet.removes()) {
51 if (moveId == -1 && newCurrentIndex >= r.index + r.count) {
52 newCurrentIndex -= r.count;
53 currentChanged =
true;
54 }
else if (moveId == -1 && newCurrentIndex >= r.index && newCurrentIndex < r.index + r.count) {
58 moveOffset = newCurrentIndex - r.index;
60 currentRemoved =
true;
63 newCurrentIndex = qMin(r.index, itemCount - 1);
65 currentChanged =
true;
68 for (
const QQmlChangeSet::Change &i : changeSet.inserts()) {
70 if (itemCount && newCurrentIndex >= i.index) {
71 newCurrentIndex += i.count;
72 currentChanged =
true;
73 }
else if (newCurrentIndex < 0) {
75 currentChanged =
true;
76 }
else if (newCurrentIndex == 0 && !itemCount) {
78 currentChanged =
true;
80 }
else if (moveId == i.moveId) {
81 newCurrentIndex = i.index + moveOffset;
87void QQuickItemViewChangeSet::applyBufferedChanges(
const QQuickItemViewChangeSet &other)
89 if (!other.hasPendingChanges())
92 pendingChanges.apply(other.pendingChanges);
93 itemCount = other.itemCount;
94 newCurrentIndex = other.newCurrentIndex;
95 currentChanged = other.currentChanged;
96 currentRemoved = other.currentRemoved;
99void QQuickItemViewChangeSet::prepare(
int currentIndex,
int count)
106 newCurrentIndex = currentIndex;
109void QQuickItemViewChangeSet::reset()
112 newCurrentIndex = -1;
113 pendingChanges.clear();
114 removedItems.clear();
116 currentChanged =
false;
117 currentRemoved =
false;
122QQuickItemView::QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent)
123 : QQuickFlickable(dd, parent)
129QQuickItemView::~QQuickItemView()
136 QQmlDelegateModelPointer model(d->model);
137 d->disconnectModel(
this, &model);
142 for (
auto it = d->unrequestedItems.keyBegin(); it != d->unrequestedItems.keyEnd(); ++it)
143 QQuickItemPrivate::get(*it)->removeItemChangeListener(d, itemChangeListenerTypes);
147QQuickItem *QQuickItemView::currentItem()
const
149 Q_D(
const QQuickItemView);
150 return d->currentItem ? d->currentItem->item :
nullptr;
153QVariant QQuickItemView::model()
const
155 Q_D(
const QQuickItemView);
157 return static_cast<QQmlDelegateModel *>(d->model.data())->model();
159 return QVariant::fromValue(d->model.data());
163void QQuickItemView::setModel(
const QVariant &m)
167 if (model.userType() == qMetaTypeId<QJSValue>())
168 model = model.value<QJSValue>().toVariant();
170 QQmlDelegateModelPointer oldModel(d->model);
172 if (oldModel.delegateModel()->model() == model)
174 }
else if (QVariant::fromValue(d->model) == model) {
178 d->disconnectModel(
this, &oldModel);
182 d->setPosition(d->contentStartOffset());
184 QObject *object = qvariant_cast<QObject *>(model);
186 QQmlDelegateModelPointer newModel(qobject_cast<QQmlInstanceModel *>(object));
188 if (d->explicitDelegate) {
189 QQmlComponent *delegate =
nullptr;
190 if (QQmlDelegateModel *old = oldModel.delegateModel())
191 delegate = old->delegate();
193 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
194 delegateModel->setDelegate(delegate);
195 }
else if (delegate) {
196 qmlWarning(
this) <<
"Cannot retain explicitly set delegate on non-DelegateModel";
197 d->explicitDelegate =
false;
201 if (d->explicitDelegateModelAccess) {
202 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
203 if (QQmlDelegateModel *old = oldModel.delegateModel())
204 access = old->delegateModelAccess();
206 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
207 delegateModel->setDelegateModelAccess(access);
208 }
else if (access != QQmlDelegateModel::Qt5ReadWrite) {
209 qmlWarning(
this) <<
"Cannot retain explicitly set delegate model access "
210 "on non-DelegateModel";
211 d->explicitDelegateModelAccess =
false;
216 delete oldModel.instanceModel();
219 d->model = newModel.instanceModel();
220 }
else if (d->ownModel) {
222 Q_ASSERT(oldModel.delegateModel());
224 d->model = newModel.instanceModel();
225 newModel.delegateModel()->setModel(model);
227 newModel = QQmlDelegateModel::createForView(
this, d);
228 if (d->explicitDelegate) {
229 QQmlComponent *delegate =
nullptr;
230 if (QQmlDelegateModel *old = oldModel.delegateModel())
231 delegate = old->delegate();
232 newModel.delegateModel()->setDelegate(delegate);
235 if (d->explicitDelegateModelAccess) {
236 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
237 if (QQmlDelegateModel *old = oldModel.delegateModel())
238 access = old->delegateModelAccess();
239 newModel.delegateModel()->setDelegateModelAccess(access);
242 newModel.delegateModel()->setModel(model);
245 d->connectModel(
this, &newModel);
247 d->moveReason = QQuickItemViewPrivate::Other;
250QQmlComponent *QQuickItemView::delegate()
const
252 Q_D(
const QQuickItemView);
254 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
255 return dataModel->delegate();
261void QQuickItemView::setDelegate(QQmlComponent *delegate)
264 const auto setExplicitDelegate = [&](QQmlDelegateModel *delegateModel) {
265 int oldCount = delegateModel->count();
266 delegateModel->setDelegate(delegate);
267 if (oldCount != delegateModel->count())
268 d->emitCountChanged();
269 d->explicitDelegate =
true;
270 d->delegateValidated =
false;
276 d->explicitDelegate =
true;
280 setExplicitDelegate(QQmlDelegateModel::createForView(
this, d));
284 emit delegateChanged();
288 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
290 d->explicitDelegate =
false;
291 setExplicitDelegate(delegateModel);
296 qmlWarning(
this) <<
"Cannot set a delegate on an explicitly provided non-DelegateModel";
298 d->explicitDelegate =
true;
302int QQuickItemView::count()
const
304 Q_D(
const QQuickItemView);
307 return d->model->count();
310int QQuickItemView::currentIndex()
const
312 Q_D(
const QQuickItemView);
313 return d->currentIndex;
316void QQuickItemView::setCurrentIndex(
int index)
321 d->currentIndexCleared = (index == -1);
323 d->applyPendingChanges();
324 if (index == d->currentIndex)
326 if (isComponentComplete() && d->isValid()) {
327 d->moveReason = QQuickItemViewPrivate::SetIndex;
328 d->updateCurrent(index);
329 }
else if (d->currentIndex != index) {
330 d->currentIndex = index;
331 emit currentIndexChanged();
336bool QQuickItemView::isWrapEnabled()
const
338 Q_D(
const QQuickItemView);
342void QQuickItemView::setWrapEnabled(
bool wrap)
348 emit keyNavigationWrapsChanged();
351bool QQuickItemView::isKeyNavigationEnabled()
const
353 Q_D(
const QQuickItemView);
354 return d->explicitKeyNavigationEnabled ? d->keyNavigationEnabled : d->interactive;
357void QQuickItemView::setKeyNavigationEnabled(
bool keyNavigationEnabled)
361 const bool wasImplicit = !d->explicitKeyNavigationEnabled;
363 QObject::disconnect(
this, &QQuickFlickable::interactiveChanged,
this, &QQuickItemView::keyNavigationEnabledChanged);
365 d->explicitKeyNavigationEnabled =
true;
368 if (d->keyNavigationEnabled != keyNavigationEnabled || wasImplicit) {
369 d->keyNavigationEnabled = keyNavigationEnabled;
370 emit keyNavigationEnabledChanged();
374int QQuickItemView::cacheBuffer()
const
376 Q_D(
const QQuickItemView);
380void QQuickItemView::setCacheBuffer(
int b)
384 qmlWarning(
this) <<
"Cannot set a negative cache buffer";
388 if (d->buffer != b) {
390 if (isComponentComplete()) {
391 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
394 emit cacheBufferChanged();
398int QQuickItemView::displayMarginBeginning()
const
400 Q_D(
const QQuickItemView);
401 return d->displayMarginBeginning;
404void QQuickItemView::setDisplayMarginBeginning(
int margin)
407 if (d->displayMarginBeginning != margin) {
408 d->displayMarginBeginning = margin;
409 if (isComponentComplete()) {
410 d->forceLayoutPolish();
412 emit displayMarginBeginningChanged();
416int QQuickItemView::displayMarginEnd()
const
418 Q_D(
const QQuickItemView);
419 return d->displayMarginEnd;
422void QQuickItemView::setDisplayMarginEnd(
int margin)
425 if (d->displayMarginEnd != margin) {
426 d->displayMarginEnd = margin;
427 if (isComponentComplete()) {
428 d->forceLayoutPolish();
430 emit displayMarginEndChanged();
434Qt::LayoutDirection QQuickItemView::layoutDirection()
const
436 Q_D(
const QQuickItemView);
437 return d->layoutDirection;
440void QQuickItemView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
443 if (d->layoutDirection != layoutDirection) {
444 d->layoutDirection = layoutDirection;
446 emit layoutDirectionChanged();
447 emit effectiveLayoutDirectionChanged();
451Qt::LayoutDirection QQuickItemView::effectiveLayoutDirection()
const
453 Q_D(
const QQuickItemView);
454 if (d->effectiveLayoutMirror)
455 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
457 return d->layoutDirection;
460QQuickItemView::VerticalLayoutDirection QQuickItemView::verticalLayoutDirection()
const
462 Q_D(
const QQuickItemView);
463 return d->verticalLayoutDirection;
466void QQuickItemView::setVerticalLayoutDirection(VerticalLayoutDirection layoutDirection)
469 if (d->verticalLayoutDirection != layoutDirection) {
470 d->verticalLayoutDirection = layoutDirection;
472 emit verticalLayoutDirectionChanged();
476QQmlComponent *QQuickItemView::header()
const
478 Q_D(
const QQuickItemView);
479 return d->headerComponent;
482QQuickItem *QQuickItemView::headerItem()
const
484 Q_D(
const QQuickItemView);
485 return d->header ? d->header->item :
nullptr;
488void QQuickItemView::setHeader(QQmlComponent *headerComponent)
491 if (d->headerComponent != headerComponent) {
492 d->applyPendingChanges();
495 d->headerComponent = headerComponent;
497 d->markExtentsDirty();
499 if (isComponentComplete()) {
505 emit headerItemChanged();
507 emit headerChanged();
511QQmlComponent *QQuickItemView::footer()
const
513 Q_D(
const QQuickItemView);
514 return d->footerComponent;
517QQuickItem *QQuickItemView::footerItem()
const
519 Q_D(
const QQuickItemView);
520 return d->footer ? d->footer->item :
nullptr;
523void QQuickItemView::setFooter(QQmlComponent *footerComponent)
526 if (d->footerComponent != footerComponent) {
527 d->applyPendingChanges();
530 d->footerComponent = footerComponent;
532 if (isComponentComplete()) {
537 emit footerItemChanged();
539 emit footerChanged();
543QQmlComponent *QQuickItemView::highlight()
const
545 Q_D(
const QQuickItemView);
546 return d->highlightComponent;
549void QQuickItemView::setHighlight(QQmlComponent *highlightComponent)
552 if (highlightComponent != d->highlightComponent) {
553 d->applyPendingChanges();
554 d->highlightComponent = highlightComponent;
555 d->createHighlight();
557 d->updateHighlight();
558 emit highlightChanged();
562QQuickItem *QQuickItemView::highlightItem()
const
564 Q_D(
const QQuickItemView);
565 return d->highlight ? d->highlight->item :
nullptr;
568bool QQuickItemView::highlightFollowsCurrentItem()
const
570 Q_D(
const QQuickItemView);
571 return d->autoHighlight;
574void QQuickItemView::setHighlightFollowsCurrentItem(
bool autoHighlight)
577 if (d->autoHighlight != autoHighlight) {
578 d->autoHighlight = autoHighlight;
580 d->updateHighlight();
581 emit highlightFollowsCurrentItemChanged();
585QQuickItemView::HighlightRangeMode QQuickItemView::highlightRangeMode()
const
587 Q_D(
const QQuickItemView);
588 return static_cast<QQuickItemView::HighlightRangeMode>(d->highlightRange);
591void QQuickItemView::setHighlightRangeMode(HighlightRangeMode mode)
594 if (d->highlightRange == mode)
596 d->highlightRange = mode;
597 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
598 if (isComponentComplete()) {
600 d->moveReason = QQuickItemViewPrivate::Other;
603 emit highlightRangeModeChanged();
607qreal QQuickItemView::preferredHighlightBegin()
const
609 Q_D(
const QQuickItemView);
610 return d->highlightRangeStart;
613void QQuickItemView::setPreferredHighlightBegin(qreal start)
616 d->highlightRangeStartValid =
true;
617 if (d->highlightRangeStart == start)
619 d->highlightRangeStart = start;
620 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
621 if (isComponentComplete()) {
623 if (!isMoving() && !isFlicking()) {
624 d->moveReason = QQuickItemViewPrivate::Other;
628 emit preferredHighlightBeginChanged();
631void QQuickItemView::resetPreferredHighlightBegin()
634 d->highlightRangeStartValid =
false;
635 if (d->highlightRangeStart == 0)
637 d->highlightRangeStart = 0;
638 if (isComponentComplete()) {
640 if (!isMoving() && !isFlicking()) {
641 d->moveReason = QQuickItemViewPrivate::Other;
645 emit preferredHighlightBeginChanged();
648qreal QQuickItemView::preferredHighlightEnd()
const
650 Q_D(
const QQuickItemView);
651 return d->highlightRangeEnd;
654void QQuickItemView::setPreferredHighlightEnd(qreal end)
657 d->highlightRangeEndValid =
true;
658 if (d->highlightRangeEnd == end)
660 d->highlightRangeEnd = end;
661 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
662 if (isComponentComplete()) {
664 if (!isMoving() && !isFlicking()) {
665 d->moveReason = QQuickItemViewPrivate::Other;
669 emit preferredHighlightEndChanged();
672void QQuickItemView::resetPreferredHighlightEnd()
675 d->highlightRangeEndValid =
false;
676 if (d->highlightRangeEnd == 0)
678 d->highlightRangeEnd = 0;
679 if (isComponentComplete()) {
681 if (!isMoving() && !isFlicking()) {
682 d->moveReason = QQuickItemViewPrivate::Other;
686 emit preferredHighlightEndChanged();
689int QQuickItemView::highlightMoveDuration()
const
691 Q_D(
const QQuickItemView);
692 return d->highlightMoveDuration;
695void QQuickItemView::setHighlightMoveDuration(
int duration)
698 if (d->highlightMoveDuration != duration) {
699 d->highlightMoveDuration = duration;
700 emit highlightMoveDurationChanged();
704bool QQuickItemView::reuseItems()
const
706 return bool(d_func()->reusableFlag == QQmlDelegateModel::Reusable);
709void QQuickItemView::setReuseItems(
bool reuse)
712 if (reuseItems() == reuse)
715 d->reusableFlag = reuse ? QQmlDelegateModel::Reusable : QQmlDelegateModel::NotReusable;
717 if (!reuse && d->model) {
720 d->model->drainReusableItemsPool(0);
723 emit reuseItemsChanged();
726#if QT_CONFIG(quick_viewtransitions)
727QQuickTransition *QQuickItemView::populateTransition()
const
729 Q_D(
const QQuickItemView);
730 return d->transitioner ? d->transitioner->populateTransition :
nullptr;
733void QQuickItemView::setPopulateTransition(QQuickTransition *transition)
736 d->createTransitioner();
737 if (d->transitioner->populateTransition != transition) {
738 d->transitioner->populateTransition = transition;
739 emit populateTransitionChanged();
743QQuickTransition *QQuickItemView::addTransition()
const
745 Q_D(
const QQuickItemView);
746 return d->transitioner ? d->transitioner->addTransition :
nullptr;
749void QQuickItemView::setAddTransition(QQuickTransition *transition)
752 d->createTransitioner();
753 if (d->transitioner->addTransition != transition) {
754 d->transitioner->addTransition = transition;
755 emit addTransitionChanged();
759QQuickTransition *QQuickItemView::addDisplacedTransition()
const
761 Q_D(
const QQuickItemView);
762 return d->transitioner ? d->transitioner->addDisplacedTransition :
nullptr;
765void QQuickItemView::setAddDisplacedTransition(QQuickTransition *transition)
768 d->createTransitioner();
769 if (d->transitioner->addDisplacedTransition != transition) {
770 d->transitioner->addDisplacedTransition = transition;
771 emit addDisplacedTransitionChanged();
775QQuickTransition *QQuickItemView::moveTransition()
const
777 Q_D(
const QQuickItemView);
778 return d->transitioner ? d->transitioner->moveTransition :
nullptr;
781void QQuickItemView::setMoveTransition(QQuickTransition *transition)
784 d->createTransitioner();
785 if (d->transitioner->moveTransition != transition) {
786 d->transitioner->moveTransition = transition;
787 emit moveTransitionChanged();
791QQuickTransition *QQuickItemView::moveDisplacedTransition()
const
793 Q_D(
const QQuickItemView);
794 return d->transitioner ? d->transitioner->moveDisplacedTransition :
nullptr;
797void QQuickItemView::setMoveDisplacedTransition(QQuickTransition *transition)
800 d->createTransitioner();
801 if (d->transitioner->moveDisplacedTransition != transition) {
802 d->transitioner->moveDisplacedTransition = transition;
803 emit moveDisplacedTransitionChanged();
807QQuickTransition *QQuickItemView::removeTransition()
const
809 Q_D(
const QQuickItemView);
810 return d->transitioner ? d->transitioner->removeTransition :
nullptr;
813void QQuickItemView::setRemoveTransition(QQuickTransition *transition)
816 d->createTransitioner();
817 if (d->transitioner->removeTransition != transition) {
818 d->transitioner->removeTransition = transition;
819 emit removeTransitionChanged();
823QQuickTransition *QQuickItemView::removeDisplacedTransition()
const
825 Q_D(
const QQuickItemView);
826 return d->transitioner ? d->transitioner->removeDisplacedTransition :
nullptr;
829void QQuickItemView::setRemoveDisplacedTransition(QQuickTransition *transition)
832 d->createTransitioner();
833 if (d->transitioner->removeDisplacedTransition != transition) {
834 d->transitioner->removeDisplacedTransition = transition;
835 emit removeDisplacedTransitionChanged();
839QQuickTransition *QQuickItemView::displacedTransition()
const
841 Q_D(
const QQuickItemView);
842 return d->transitioner ? d->transitioner->displacedTransition :
nullptr;
845void QQuickItemView::setDisplacedTransition(QQuickTransition *transition)
848 d->createTransitioner();
849 if (d->transitioner->displacedTransition != transition) {
850 d->transitioner->displacedTransition = transition;
851 emit displacedTransitionChanged();
856void QQuickItemViewPrivate::positionViewAtIndex(
int index,
int mode)
860 if (mode < QQuickItemView::Beginning || mode > QQuickItemView::SnapPosition)
865 applyPendingChanges();
866 const int modelCount = model->count();
867 int idx = qMax(qMin(index, modelCount - 1), 0);
869 const auto viewSize = size();
870 qreal pos = isContentFlowReversed() ? -position() - viewSize : position();
871 FxViewItem *item = visibleItem(idx);
872 qreal maxExtent = calculatedMaxExtent();
877 qreal itemPos = (mode == QQuickItemView::Beginning && idx == 0)
878 ? contentStartOffset()
880 changedVisibleIndex(idx);
883 const QList<FxViewItem *> oldVisible = visibleItems;
884 visibleItems.clear();
886 if (mode == QQuickItemView::Beginning && idx == 0) {
888 changedVisibleIndex(idx);
898 setPosition(qMin(itemPos, maxExtent));
901 for (FxViewItem *item : oldVisible)
902 releaseItem(item, reusableFlag);
903 item = visibleItem(idx);
906 const bool stickyHeader = hasStickyHeader();
907 const bool stickyFooter = hasStickyFooter();
908 const qreal stickyHeaderSize = stickyHeader ? headerSize() : 0;
909 const qreal stickyFooterSize = stickyFooter ? footerSize() : 0;
911 const qreal itemPos = item->position();
913 case QQuickItemView::Beginning:
915 if (header && (index < 0 || stickyHeader))
918 case QQuickItemView::Center:
919 pos = itemPos - (viewSize - item->size())/2;
921 case QQuickItemView::End:
922 pos = itemPos - viewSize + item->size();
923 if (footer && (index >= modelCount || stickyFooter))
926 case QQuickItemView::Visible:
927 if (itemPos > pos + viewSize - stickyFooterSize)
928 pos = item->endPosition() - viewSize + stickyFooterSize;
929 else if (item->endPosition() <= pos - stickyHeaderSize)
930 pos = itemPos - stickyHeaderSize;
932 case QQuickItemView::Contain:
933 if (item->endPosition() >= pos + viewSize + stickyFooterSize)
934 pos = itemPos - viewSize + item->size() + stickyFooterSize;
935 if (itemPos - stickyHeaderSize < pos)
936 pos = itemPos - stickyHeaderSize;
938 case QQuickItemView::SnapPosition:
939 pos = itemPos - highlightRangeStart - stickyHeaderSize;
942 pos = qMin(pos, maxExtent);
943 qreal minExtent = calculatedMinExtent();
944 pos = qMax(pos, minExtent);
945 moveReason = QQuickItemViewPrivate::Other;
950 resetHighlightPosition();
957void QQuickItemView::positionViewAtIndex(
int index,
int mode)
960 if (!d->isValid() || index < 0 || index >= d->model->count())
962 d->positionViewAtIndex(index, mode);
966void QQuickItemView::positionViewAtBeginning()
971 d->positionViewAtIndex(-1, Beginning);
974void QQuickItemView::positionViewAtEnd()
979 d->positionViewAtIndex(d->model->count(), End);
984 for (FxViewItem *item : items) {
985 if (item->contains(x, y))
991int QQuickItemView::indexAt(qreal x, qreal y)
const
993 Q_D(
const QQuickItemView);
994 const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y);
995 return item ? item->index : -1;
998QQuickItem *QQuickItemView::itemAt(qreal x, qreal y)
const
1000 Q_D(
const QQuickItemView);
1001 const FxViewItem *item = fxViewItemAtPosition(d->visibleItems, x, y);
1002 return item ? item->item :
nullptr;
1005QQuickItem *QQuickItemView::itemAtIndex(
int index)
const
1007 Q_D(
const QQuickItemView);
1008 const FxViewItem *item = d->visibleItem(index);
1009 return item ? item->item :
nullptr;
1012void QQuickItemView::forceLayout()
1014 Q_D(QQuickItemView);
1015 if (isComponentComplete() && (d->currentChanges.hasPendingChanges() || d->forceLayout))
1019void QQuickItemViewPrivate::applyPendingChanges()
1021 Q_Q(QQuickItemView);
1022 if (q->isComponentComplete() && currentChanges.hasPendingChanges())
1026int QQuickItemViewPrivate::findMoveKeyIndex(QQmlChangeSet::MoveKey key,
const QList<QQmlChangeSet::Change> &changes)
const
1028 for (
int i=0; i<changes.size(); i++) {
1029 for (
int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
1030 if (changes[i].moveKey(j) == key)
1037qreal QQuickItemViewPrivate::minExtentForAxis(
const AxisData &axisData,
bool forXAxis)
const
1039 Q_Q(
const QQuickItemView);
1041 qreal highlightStart;
1043 qreal endPositionFirstItem = 0;
1044 qreal extent = -startPosition() + axisData.startMargin;
1045 if (isContentFlowReversed()) {
1046 if (model && model->count())
1047 endPositionFirstItem = positionAt(model->count()-1);
1049 extent += headerSize();
1050 highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
1051 highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
1052 extent += footerSize();
1053 qreal maxExtentAlongAxis = forXAxis ? q->maxXExtent() : q->maxYExtent();
1054 if (extent < maxExtentAlongAxis)
1055 extent = maxExtentAlongAxis;
1057 endPositionFirstItem = endPositionAt(0);
1058 highlightStart = highlightRangeStart;
1059 highlightEnd = highlightRangeEnd;
1060 extent += headerSize();
1062 if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
1063 extent += highlightStart;
1064 FxViewItem *firstItem = visibleItem(0);
1066 extent -= firstItem->sectionSize();
1067 extent = isContentFlowReversed()
1068 ? qMin(extent, endPositionFirstItem + highlightEnd)
1069 : qMax(extent, -(endPositionFirstItem - highlightEnd));
1074qreal QQuickItemViewPrivate::maxExtentForAxis(
const AxisData &axisData,
bool forXAxis)
const
1076 Q_Q(
const QQuickItemView);
1078 qreal highlightStart;
1080 qreal lastItemPosition = 0;
1082 if (isContentFlowReversed()) {
1083 highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
1084 highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
1085 lastItemPosition = endPosition();
1087 highlightStart = highlightRangeStart;
1088 highlightEnd = highlightRangeEnd;
1089 if (model && model->count())
1090 lastItemPosition = positionAt(model->count()-1);
1092 if (!model || !model->count()) {
1093 if (!isContentFlowReversed())
1094 maxExtent = header ? -headerSize() : 0;
1095 extent += forXAxis ? q->width() : q->height();
1096 }
else if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
1097 extent = -(lastItemPosition - highlightStart);
1098 if (highlightEnd != highlightStart) {
1099 extent = isContentFlowReversed()
1100 ? qMax(extent, -(endPosition() - highlightEnd))
1101 : qMin(extent, -(endPosition() - highlightEnd));
1104 extent = -(endPosition() - (forXAxis ? q->width() : q->height()));
1106 if (isContentFlowReversed()) {
1107 extent -= headerSize();
1108 extent -= axisData.endMargin;
1110 extent -= footerSize();
1111 extent -= axisData.endMargin;
1112 qreal minExtentAlongAxis = forXAxis ? q->minXExtent() : q->minYExtent();
1113 if (extent > minExtentAlongAxis)
1114 extent = minExtentAlongAxis;
1120qreal QQuickItemViewPrivate::calculatedMinExtent()
const
1122 Q_Q(
const QQuickItemView);
1124 if (layoutOrientation() == Qt::Vertical)
1125 minExtent = isContentFlowReversed() ? q->maxYExtent() - size(): -q->minYExtent();
1127 minExtent = isContentFlowReversed() ? q->maxXExtent() - size(): -q->minXExtent();
1132qreal QQuickItemViewPrivate::calculatedMaxExtent()
const
1134 Q_Q(
const QQuickItemView);
1136 if (layoutOrientation() == Qt::Vertical)
1137 maxExtent = isContentFlowReversed() ? q->minYExtent() - size(): -q->maxYExtent();
1139 maxExtent = isContentFlowReversed() ? q->minXExtent() - size(): -q->maxXExtent();
1143void QQuickItemViewPrivate::connectModel(QQuickItemView *q, QQmlDelegateModelPointer *model)
1145 QQmlInstanceModel *instanceModel = model->instanceModel();
1149 bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
1150 QObject::connect(instanceModel, &QQmlInstanceModel::createdItem,
1151 q, &QQuickItemView::createdItem);
1152 QObject::connect(instanceModel, &QQmlInstanceModel::initItem,
1153 q, &QQuickItemView::initItem);
1154 QObject::connect(instanceModel, &QQmlInstanceModel::destroyingItem,
1155 q, &QQuickItemView::destroyingItem);
1156 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
1157 QObject::connect(delegateModel, &QQmlInstanceModel::itemPooled,
1158 q, &QQuickItemView::onItemPooled);
1159 QObject::connect(delegateModel, &QQmlInstanceModel::itemReused,
1160 q, &QQuickItemView::onItemReused);
1163 if (q->isComponentComplete()) {
1164 updateSectionCriteria();
1167
1169 q->setCurrentIndex(instanceModel->count() > 0 ? 0 : -1);
1172#if QT_CONFIG(quick_viewtransitions)
1173 if (transitioner && transitioner->populateTransition) {
1174 transitioner->setPopulateTransitionEnabled(
true);
1175 forceLayoutPolish();
1180 QObject::connect(instanceModel, &QQmlInstanceModel::modelUpdated,
1181 q, &QQuickItemView::modelUpdated);
1182 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
1183 QObjectPrivate::connect(
1184 dataModel, &QQmlDelegateModel::delegateChanged,
1185 this, &QQuickItemViewPrivate::applyDelegateChange);
1186 QObjectPrivate::connect(
1187 dataModel, &QQmlDelegateModel::delegateModelAccessChanged,
1188 this, &QQuickItemViewPrivate::applyDelegateModelAccessChange);
1190 QObject::connect(dataModel, &QQmlDelegateModel::modelChanged,
1191 q, &QQuickItemView::modelChanged);
1198void QQuickItemViewPrivate::disconnectModel(QQuickItemView *q, QQmlDelegateModelPointer *model)
1200 QQmlInstanceModel *instanceModel = model->instanceModel();
1205 QObject::disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
1206 q, &QQuickItemView::modelUpdated);
1207 QObject::disconnect(instanceModel, &QQmlInstanceModel::initItem,
1208 q, &QQuickItemView::initItem);
1209 QObject::disconnect(instanceModel, &QQmlInstanceModel::createdItem,
1210 q, &QQuickItemView::createdItem);
1211 QObject::disconnect(instanceModel, &QQmlInstanceModel::destroyingItem,
1212 q, &QQuickItemView::destroyingItem);
1213 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
1214 QObject::disconnect(delegateModel, &QQmlInstanceModel::itemPooled,
1215 q, &QQuickItemView::onItemPooled);
1216 QObject::disconnect(delegateModel, &QQmlInstanceModel::itemReused,
1217 q, &QQuickItemView::onItemReused);
1218 QObjectPrivate::disconnect(
1219 delegateModel, &QQmlDelegateModel::delegateChanged,
1220 this, &QQuickItemViewPrivate::applyDelegateChange);
1221 QObjectPrivate::disconnect(
1222 delegateModel, &QQmlDelegateModel::delegateModelAccessChanged,
1223 this, &QQuickItemViewPrivate::applyDelegateModelAccessChange);
1225 QObject::disconnect(delegateModel, &QQmlDelegateModel::modelChanged,
1226 q, &QQuickItemView::modelChanged);
1231void QQuickItemViewPrivate::applyDelegateChange()
1233 Q_Q(QQuickItemView);
1235 QQmlDelegateModel::applyDelegateChangeOnView(q,
this);
1237 releaseVisibleItems(QQmlDelegateModel::NotReusable);
1238 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1239 updateSectionCriteria();
1241 moveReason = QQuickItemViewPrivate::SetIndex;
1242 updateCurrent(currentIndex);
1243 if (highlight && currentItem) {
1245 resetHighlightPosition();
1246 updateTrackedItem();
1248 moveReason = QQuickItemViewPrivate::Other;
1253void QQuickItemViewPrivate::checkVisible()
const
1256 for (
int i = 0; i < visibleItems.size(); ++i) {
1257 FxViewItem *item = visibleItems.at(i);
1258 if (item->index == -1) {
1260 }
else if (item->index != visibleIndex + i - skip) {
1261 qFatal(
"index %d %d %d", visibleIndex, i, item->index);
1267void QQuickItemViewPrivate::showVisibleItems()
const
1269 qDebug() <<
"Visible items:";
1270 for (FxViewItem *item : visibleItems) {
1271 qDebug() <<
"\t" << item->index
1272 << item->item->objectName()
1273 << item->position();
1278void QQuickItemViewPrivate::emitCountChanged()
1280 Q_Q(QQuickItemView);
1281 qCDebug(lcCount).nospace() <<
"about to emit countChanged for " << q <<
"; count changed to " << q->count();
1282 emit q->countChanged();
1285void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change,
1286 const QRectF &oldGeometry)
1288 Q_Q(QQuickItemView);
1289 QQuickFlickablePrivate::itemGeometryChanged(item, change, oldGeometry);
1290 if (!q->isComponentComplete())
1293 if (header && header->item == item) {
1297 if (!q->isMoving() && !q->isFlicking())
1299 }
else if (footer && footer->item == item) {
1303 if (!q->isMoving() && !q->isFlicking())
1307 if (currentItem && currentItem->item == item) {
1310 bool prevInLayout = inLayout;
1311#if QT_CONFIG(quick_viewtransitions)
1313 FxViewItem *actualItem = transitioner ? visibleItem(currentIndex) :
nullptr;
1314 if (actualItem && actualItem->transitionRunning())
1319 inLayout = prevInLayout;
1322 if (trackedItem && trackedItem->item == item)
1323 q->trackedPositionChanged();
1326void QQuickItemView::destroyRemoved()
1328 Q_D(QQuickItemView);
1330#if QT_CONFIG(quick_viewtransitions)
1331 bool hasRemoveTransition =
false;
1332 bool hasRemoveTransitionAsTarget =
false;
1333 if (d->transitioner) {
1334 hasRemoveTransition = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false);
1335 hasRemoveTransitionAsTarget = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true);
1339 for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
1340 it != d->visibleItems.end();) {
1341 FxViewItem *item = *it;
1342 if (item->index == -1 && (!item->attached || item->attached->delayRemove() ==
false)) {
1343#if QT_CONFIG(quick_viewtransitions)
1344 if (hasRemoveTransitionAsTarget) {
1346 d->runDelayedRemoveTransition =
true;
1347 QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()),
this, SLOT(destroyRemoved()));
1350 if (hasRemoveTransition)
1351 d->runDelayedRemoveTransition =
true;
1353 d->releaseItem(item, d->reusableFlag);
1354 it = d->visibleItems.erase(it);
1355#if QT_CONFIG(quick_viewtransitions)
1364 d->forceLayoutPolish();
1367void QQuickItemView::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
1369 Q_D(QQuickItemView);
1372#if QT_CONFIG(quick_viewtransitions)
1373 if (d->transitioner)
1374 d->transitioner->setPopulateTransitionEnabled(
true);
1376 d->moveReason = QQuickItemViewPrivate::SetIndex;
1378 if (d->highlight && d->currentItem) {
1379 if (d->autoHighlight)
1380 d->resetHighlightPosition();
1381 d->updateTrackedItem();
1383 d->moveReason = QQuickItemViewPrivate::Other;
1384 d->emitCountChanged();
1385#if QT_CONFIG(quick_viewtransitions)
1386 if (d->transitioner && d->transitioner->populateTransition)
1387 d->forceLayoutPolish();
1391 d->bufferedChanges.prepare(d->currentIndex, d->itemCount);
1392 d->bufferedChanges.applyChanges(changeSet);
1394 if (d->bufferedChanges.hasPendingChanges()) {
1395 d->currentChanges.applyBufferedChanges(d->bufferedChanges);
1396 d->bufferedChanges.reset();
1398 d->currentChanges.prepare(d->currentIndex, d->itemCount);
1399 d->currentChanges.applyChanges(changeSet);
1405void QQuickItemView::animStopped()
1407 Q_D(QQuickItemView);
1408 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
1409 d->refillOrLayout();
1410 if (d->haveHighlightRange && d->highlightRange == QQuickItemView::StrictlyEnforceRange)
1411 d->updateHighlight();
1415void QQuickItemView::trackedPositionChanged()
1417 Q_D(QQuickItemView);
1418 if (!d->trackedItem || !d->currentItem)
1426 const bool needMoveToTrackHighlight = d->autoHighlight || d->highlightRange != NoHighlightRange;
1428 if (d->moveReason == QQuickItemViewPrivate::SetIndex && needMoveToTrackHighlight) {
1429 qreal trackedPos = d->trackedItem->position();
1430 qreal trackedSize = d->trackedItem->size();
1431 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
1432 qreal pos = viewPos;
1433 if (d->haveHighlightRange) {
1434 if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
1435 pos = trackedPos - d->highlightRangeEnd + trackedSize;
1436 if (trackedPos < pos + d->highlightRangeStart)
1437 pos = trackedPos - d->highlightRangeStart;
1438 if (d->highlightRange != StrictlyEnforceRange) {
1439 qreal maxExtent = d->calculatedMaxExtent();
1440 if (pos > maxExtent)
1442 qreal minExtent = d->calculatedMinExtent();
1443 if (pos < minExtent)
1447 if (d->trackedItem != d->currentItem) {
1449 trackedPos -= d->currentItem->sectionSize();
1450 trackedSize += d->currentItem->sectionSize();
1452 qreal trackedEndPos = d->trackedItem->endPosition();
1453 qreal toItemPos = d->currentItem->position();
1454 qreal toItemEndPos = d->currentItem->endPosition();
1455 if (d->showHeaderForIndex(d->currentIndex)) {
1456 qreal startOffset = -d->contentStartOffset();
1457 trackedPos -= startOffset;
1458 trackedEndPos -= startOffset;
1459 toItemPos -= startOffset;
1460 toItemEndPos -= startOffset;
1461 }
else if (d->showFooterForIndex(d->currentIndex)) {
1462 qreal endOffset = d->footerSize();
1463 if (d->layoutOrientation() == Qt::Vertical) {
1464 if (d->isContentFlowReversed())
1465 endOffset += d->vData.startMargin;
1467 endOffset += d->vData.endMargin;
1469 if (d->isContentFlowReversed())
1470 endOffset += d->hData.startMargin;
1472 endOffset += d->hData.endMargin;
1474 trackedPos += endOffset;
1475 trackedEndPos += endOffset;
1476 toItemPos += endOffset;
1477 toItemEndPos += endOffset;
1480 if (trackedEndPos >= viewPos + d->size()
1481 && toItemEndPos >= viewPos + d->size()) {
1482 if (trackedEndPos <= toItemEndPos) {
1483 pos = trackedEndPos - d->size();
1484 if (trackedSize > d->size())
1487 pos = toItemEndPos - d->size();
1488 if (d->currentItem->size() > d->size())
1489 pos = d->currentItem->position();
1492 if (trackedPos < pos && toItemPos < pos)
1493 pos = qMax(trackedPos, toItemPos);
1495 if (viewPos != pos) {
1496 d->calcVelocity =
true;
1497 d->setPosition(pos);
1498 d->calcVelocity =
false;
1503void QQuickItemView::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
1505 Q_D(QQuickItemView);
1506 d->markExtentsDirty();
1507 if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty()))
1508 d->forceLayoutPolish();
1509 QQuickFlickable::geometryChange(newGeometry, oldGeometry);
1512qreal QQuickItemView::minYExtent()
const
1514 Q_D(
const QQuickItemView);
1515 if (d->layoutOrientation() == Qt::Horizontal)
1516 return QQuickFlickable::minYExtent();
1518 if (d->vData.minExtentDirty) {
1519 d->minExtent = d->minExtentForAxis(d->vData,
false);
1520 d->vData.minExtentDirty =
false;
1523 return d->minExtent;
1526qreal QQuickItemView::maxYExtent()
const
1528 Q_D(
const QQuickItemView);
1529 if (d->layoutOrientation() == Qt::Horizontal)
1530 return QQuickFlickable::maxYExtent();
1532 if (d->vData.maxExtentDirty) {
1533 d->maxExtent = d->maxExtentForAxis(d->vData,
false);
1534 d->vData.maxExtentDirty =
false;
1537 return d->maxExtent;
1540qreal QQuickItemView::minXExtent()
const
1542 Q_D(
const QQuickItemView);
1543 if (d->layoutOrientation() == Qt::Vertical)
1544 return QQuickFlickable::minXExtent();
1546 if (d->hData.minExtentDirty) {
1547 d->minExtent = d->minExtentForAxis(d->hData,
true);
1548 d->hData.minExtentDirty =
false;
1551 return d->minExtent;
1554qreal QQuickItemView::maxXExtent()
const
1556 Q_D(
const QQuickItemView);
1557 if (d->layoutOrientation() == Qt::Vertical)
1558 return QQuickFlickable::maxXExtent();
1560 if (d->hData.maxExtentDirty) {
1561 d->maxExtent = d->maxExtentForAxis(d->hData,
true);
1562 d->hData.maxExtentDirty =
false;
1565 return d->maxExtent;
1568void QQuickItemView::setContentX(qreal pos)
1570 Q_D(QQuickItemView);
1572 d->moveReason = QQuickItemViewPrivate::Other;
1573 QQuickFlickable::setContentX(pos);
1576void QQuickItemView::setContentY(qreal pos)
1578 Q_D(QQuickItemView);
1580 d->moveReason = QQuickItemViewPrivate::Other;
1581 QQuickFlickable::setContentY(pos);
1584qreal QQuickItemView::originX()
const
1586 Q_D(
const QQuickItemView);
1587 if (d->layoutOrientation() == Qt::Horizontal
1588 && effectiveLayoutDirection() == Qt::RightToLeft
1589 && contentWidth() < width()) {
1590 return -d->lastPosition() - d->footerSize();
1592 return QQuickFlickable::originX();
1595qreal QQuickItemView::originY()
const
1597 Q_D(
const QQuickItemView);
1598 if (d->layoutOrientation() == Qt::Vertical
1599 && d->verticalLayoutDirection == QQuickItemView::BottomToTop
1600 && contentHeight() < height()) {
1601 return -d->lastPosition() - d->footerSize();
1603 return QQuickFlickable::originY();
1606void QQuickItemView::updatePolish()
1608 Q_D(QQuickItemView);
1609 QQuickFlickable::updatePolish();
1613void QQuickItemView::componentComplete()
1615 Q_D(QQuickItemView);
1616 if (d->model && d->ownModel)
1617 static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
1619 QQuickFlickable::componentComplete();
1621 d->updateSectionCriteria();
1624 d->updateViewport();
1625 d->setPosition(d->contentStartOffset());
1626#if QT_CONFIG(quick_viewtransitions)
1627 if (d->transitioner)
1628 d->transitioner->setPopulateTransitionEnabled(
true);
1633 d->moveReason = QQuickItemViewPrivate::SetIndex;
1634 if (d->currentIndex < 0 && !d->currentIndexCleared)
1635 d->updateCurrent(0);
1637 d->updateCurrent(d->currentIndex);
1638 if (d->highlight && d->currentItem) {
1639 if (d->autoHighlight)
1640 d->resetHighlightPosition();
1641 d->updateTrackedItem();
1643 d->moveReason = QQuickItemViewPrivate::Other;
1646 if (d->model && d->model->count())
1647 d->emitCountChanged();
1652QQuickItemViewPrivate::QQuickItemViewPrivate()
1655 , displayMarginBeginning(0), displayMarginEnd(0)
1656 , layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom)
1658 , currentIndex(-1), currentItem(
nullptr)
1659 , trackedItem(
nullptr), requestedIndex(-1)
1660 , highlightComponent(
nullptr), highlight(
nullptr)
1661 , highlightRange(QQuickItemView::NoHighlightRange)
1662 , highlightRangeStart(0), highlightRangeEnd(0)
1663 , highlightMoveDuration(150)
1664 , headerComponent(
nullptr), header(
nullptr), footerComponent(
nullptr), footer(
nullptr)
1665#if QT_CONFIG(quick_viewtransitions)
1666 , transitioner(
nullptr)
1668 , minExtent(0), maxExtent(0)
1669 , ownModel(
false), wrap(
false)
1670 , keyNavigationEnabled(
true)
1671 , explicitKeyNavigationEnabled(
false)
1672 , inLayout(
false), inViewportMoved(
false), forceLayout(
false), currentIndexCleared(
false)
1673 , haveHighlightRange(
false), autoHighlight(
true), highlightRangeStartValid(
false), highlightRangeEndValid(
false)
1674 , fillCacheBuffer(
false), inRequest(
false)
1675#if QT_CONFIG(quick_viewtransitions)
1676 , runDelayedRemoveTransition(
false)
1678 , delegateValidated(
false)
1680 , explicitDelegate(
false)
1681 , explicitDelegateModelAccess(
false)
1684 bufferPause.addAnimationChangeListener(
this, QAbstractAnimationJob::Completion);
1685 bufferPause.setLoopCount(1);
1686 bufferPause.setDuration(16);
1689QQuickItemViewPrivate::~QQuickItemViewPrivate()
1691#if QT_CONFIG(quick_viewtransitions)
1693 transitioner->setChangeListener(
nullptr);
1694 delete transitioner;
1698bool QQuickItemViewPrivate::isValid()
const
1700 return model && model->count() && model->isValid();
1703qreal QQuickItemViewPrivate::position()
const
1705 Q_Q(
const QQuickItemView);
1706 return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
1709qreal QQuickItemViewPrivate::size()
const
1711 Q_Q(
const QQuickItemView);
1712 return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
1715qreal QQuickItemViewPrivate::startPosition()
const
1717 return isContentFlowReversed() ? -lastPosition() : originPosition();
1720qreal QQuickItemViewPrivate::endPosition()
const
1722 return isContentFlowReversed() ? -originPosition() : lastPosition();
1725qreal QQuickItemViewPrivate::contentStartOffset()
const
1727 qreal pos = -headerSize();
1728 if (layoutOrientation() == Qt::Vertical) {
1729 if (isContentFlowReversed())
1730 pos -= vData.endMargin;
1732 pos -= vData.startMargin;
1734 if (isContentFlowReversed())
1735 pos -= hData.endMargin;
1737 pos -= hData.startMargin;
1742int QQuickItemViewPrivate::findLastVisibleIndex(
int defaultValue)
const
1744 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1746 if (item->index != -1)
1749 return defaultValue;
1752FxViewItem *QQuickItemViewPrivate::visibleItem(
int modelIndex)
const {
1753 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.size()) {
1754 for (
int i = modelIndex - visibleIndex; i < visibleItems.size(); ++i) {
1755 FxViewItem *item = visibleItems.at(i);
1756 if (item->index == modelIndex)
1763FxViewItem *QQuickItemViewPrivate::firstItemInView()
const {
1764 const qreal pos = isContentFlowReversed() ? -position()-size() : position();
1765 for (FxViewItem *item : visibleItems) {
1766 if (item->index != -1 && item->endPosition() > pos)
1769 return visibleItems.size() ? visibleItems.first() : 0;
1772int QQuickItemViewPrivate::findLastIndexInView()
const
1774 const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
1775 for (
auto it = visibleItems.rbegin(), end = visibleItems.rend(); it != end; ++it) {
1777 if (item->index != -1 && item->position() <= viewEndPos)
1786int QQuickItemViewPrivate::mapFromModel(
int modelIndex)
const
1788 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.size())
1790 for (
int i = 0; i < visibleItems.size(); ++i) {
1791 FxViewItem *item = visibleItems.at(i);
1792 if (item->index == modelIndex)
1794 if (item->index > modelIndex)
1800void QQuickItemViewPrivate::init()
1802 Q_Q(QQuickItemView);
1803 q->setFlag(QQuickItem::ItemIsFocusScope);
1804 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
1805 QObject::connect(q, &QQuickFlickable::interactiveChanged, q, &QQuickItemView::keyNavigationEnabledChanged);
1806 q->setFlickableDirection(QQuickFlickable::VerticalFlick);
1809void QQuickItemViewPrivate::updateCurrent(
int modelIndex)
1811 Q_Q(QQuickItemView);
1812 applyPendingChanges();
1813 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
1815 if (currentItem->attached)
1816 currentItem->attached->setIsCurrentItem(
false);
1817 releaseCurrentItem(reusableFlag);
1818 currentIndex = modelIndex;
1819 emit q->currentIndexChanged();
1820 emit q->currentItemChanged();
1822 }
else if (currentIndex != modelIndex) {
1823 currentIndex = modelIndex;
1824 emit q->currentIndexChanged();
1829 if (currentItem && currentIndex == modelIndex) {
1834 FxViewItem *oldCurrentItem = currentItem;
1835 int oldCurrentIndex = currentIndex;
1836 currentIndex = modelIndex;
1837 currentItem = createItem(modelIndex, QQmlIncubator::AsynchronousIfNested);
1838 if (oldCurrentItem && oldCurrentItem->attached && (!currentItem || oldCurrentItem->item != currentItem->item))
1839 oldCurrentItem->attached->setIsCurrentItem(
false);
1841 currentItem->item->setFocus(
true);
1842 if (currentItem->attached)
1843 currentItem->attached->setIsCurrentItem(
true);
1844 initializeCurrentItem();
1848 if (oldCurrentIndex != currentIndex)
1849 emit q->currentIndexChanged();
1850 if (oldCurrentItem != currentItem
1851 && (!oldCurrentItem || !currentItem || oldCurrentItem->item != currentItem->item))
1852 emit q->currentItemChanged();
1853 releaseItem(oldCurrentItem, reusableFlag);
1856void QQuickItemViewPrivate::clear(
bool onDestruction)
1858 Q_Q(QQuickItemView);
1861 auto cleanup = qScopeGuard([
this] { isClearing =
false; });
1863 currentChanges.reset();
1864 bufferedChanges.reset();
1867 releaseVisibleItems(QQmlInstanceModel::NotReusable);
1870#if QT_CONFIG(quick_viewtransitions)
1871 for (FxViewItem *item : std::as_const(releasePendingTransition)) {
1872 item->releaseAfterTransition =
false;
1873 releaseItem(item, QQmlInstanceModel::NotReusable);
1875 releasePendingTransition.clear();
1878 const bool hadCurrentItem = currentItem !=
nullptr;
1879 releaseCurrentItem(QQmlDelegateModel::NotReusable);
1881 emit q->currentItemChanged();
1882 createHighlight(onDestruction);
1883 trackedItem =
nullptr;
1885 if (requestedIndex >= 0) {
1887 model->cancel(requestedIndex);
1888 requestedIndex = -1;
1896void QQuickItemViewPrivate::mirrorChange()
1898 Q_Q(QQuickItemView);
1900 emit q->effectiveLayoutDirectionChanged();
1903void QQuickItemViewPrivate::animationFinished(QAbstractAnimationJob *)
1905 Q_Q(QQuickItemView);
1906 fillCacheBuffer =
true;
1910void QQuickItemViewPrivate::refill()
1912 qreal s = qMax(size(), qreal(0.));
1913 const auto pos = position();
1914 if (isContentFlowReversed())
1915 refill(-pos - displayMarginBeginning-s, -pos + displayMarginEnd);
1917 refill(pos - displayMarginBeginning, pos + displayMarginEnd+s);
1920void QQuickItemViewPrivate::refill(qreal from, qreal to)
1922 Q_Q(QQuickItemView);
1923 if (!model || !model->isValid() || !q->isComponentComplete())
1925 if (q->size().isNull() && visibleItems.isEmpty())
1927 if (!model->count()) {
1940 if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) {
1941 currentChanges.reset();
1942 bufferedChanges.reset();
1943 releaseVisibleItems(reusableFlag);
1946 int prevCount = itemCount;
1947 itemCount = model->count();
1948 qreal bufferFrom = from - buffer;
1949 qreal bufferTo = to + buffer;
1950 qreal fillFrom = from;
1953 bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
false);
1955 if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
1959 bufferPause.start();
1961 if (bufferMode & BufferAfter)
1963 if (bufferMode & BufferBefore)
1964 fillFrom = bufferFrom;
1965 added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo,
true);
1969 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
1971 if (added || removed) {
1973 updateBeginningEnd();
1974 visibleItemsChanged();
1980 if (prevCount != itemCount)
1982 }
while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges());
1983 storeFirstVisibleItemPosition();
1987void QQuickItemViewPrivate::regenerate(
bool orientationChanged)
1989 Q_Q(QQuickItemView);
1990 if (q->isComponentComplete()) {
1991 if (orientationChanged) {
2001 setPosition(contentStartOffset());
2003 updateCurrent(currentIndex);
2007void QQuickItemViewPrivate::updateViewport()
2009 Q_Q(QQuickItemView);
2010 qreal extra = headerSize() + footerSize();
2011 qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
2012 if (layoutOrientation() == Qt::Vertical)
2013 q->setContentHeight(contentSize + extra);
2015 q->setContentWidth(contentSize + extra);
2018void QQuickItemViewPrivate::layout()
2020 Q_Q(QQuickItemView);
2027 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2032 if ((!isValid() && !visibleItems.size()) || q->size().isNull()) {
2033 if (q->size().isNull() && hasPendingChanges()) {
2044 setPosition(contentStartOffset());
2046#if QT_CONFIG(quick_viewtransitions)
2048 transitioner->setPopulateTransitionEnabled(
false);
2054#if QT_CONFIG(quick_viewtransitions)
2055 if (runDelayedRemoveTransition && transitioner
2056 && transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2059 for (
int i=0; i<visibleItems.size(); i++)
2060 visibleItems[i]->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2064 ChangeResult insertionPosChanges;
2065 ChangeResult removalPosChanges;
2066 if (!applyModelChanges(&insertionPosChanges, &removalPosChanges) && !forceLayout) {
2067 if (fillCacheBuffer) {
2068 fillCacheBuffer =
false;
2074 forceLayout =
false;
2076#if QT_CONFIG(quick_viewtransitions)
2077 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition,
true)) {
2081 for (FxViewItem *item : std::as_const(visibleItems)) {
2082 if (!item->transitionScheduledOrRunning())
2083 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition,
true);
2089 layoutVisibleItems();
2090 storeFirstVisibleItemPosition();
2092#if QT_CONFIG(quick_viewtransitions)
2093 int lastIndexInView = findLastIndexInView();
2099 if (!q->isMoving() && !q->isFlicking() && !movingFromHighlight()) {
2107 updateUnrequestedPositions();
2109#if QT_CONFIG(quick_viewtransitions)
2113 if (lastIndexInView != -1 &&
2114 (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
false)
2115 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false))) {
2116 translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
2119 prepareVisibleItemTransitions();
2122 for (
int i = 0, count = releasePendingTransition.size(); i < count;) {
2123 auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds);
2128 const int old_count = count;
2129 count = releasePendingTransition.size();
2130 if (old_count > count)
2134 releaseItem(releasePendingTransition[i], reusableFlag);
2135 releasePendingTransition.remove(i);
2142 for (
int i=0; i<visibleItems.size(); i++)
2143 visibleItems[i]->startTransition(transitioner);
2144 for (
int i=0; i<releasePendingTransition.size(); i++)
2145 releasePendingTransition[i]->startTransition(transitioner);
2147 transitioner->setPopulateTransitionEnabled(
false);
2148 transitioner->resetTargetLists();
2153 updateCurrent(currentIndex);
2155#if QT_CONFIG(quick_viewtransitions)
2156 runDelayedRemoveTransition =
false;
2161bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult)
2163 Q_Q(QQuickItemView);
2164 if (!q->isComponentComplete() || !hasPendingChanges())
2167 if (bufferedChanges.hasPendingChanges()) {
2168 currentChanges.applyBufferedChanges(bufferedChanges);
2169 bufferedChanges.reset();
2172 updateUnrequestedIndexes();
2174 FxViewItem *prevVisibleItemsFirst = visibleItems.size() ? *visibleItems.constBegin() :
nullptr;
2175 int prevItemCount = itemCount;
2176 int prevVisibleItemsCount = visibleItems.size();
2177 bool visibleAffected =
false;
2178 bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
2179 || !currentChanges.pendingChanges.inserts().isEmpty();
2181 FxViewItem *prevFirstItemInView = firstItemInView();
2182 QQmlNullableValue<qreal> prevFirstItemInViewPos;
2183 int prevFirstItemInViewIndex = -1;
2184 if (prevFirstItemInView) {
2185 prevFirstItemInViewPos = prevFirstItemInView->position();
2186 prevFirstItemInViewIndex = prevFirstItemInView->index;
2188 qreal prevVisibleItemsFirstPos = visibleItems.size() ? firstVisibleItemPosition : 0.0;
2190 totalInsertionResult->visiblePos = prevFirstItemInViewPos;
2191 totalRemovalResult->visiblePos = prevFirstItemInViewPos;
2193 const QList<QQmlChangeSet::Change> &removals = currentChanges.pendingChanges.removes();
2194 const QList<QQmlChangeSet::Change> &insertions = currentChanges.pendingChanges.inserts();
2195 ChangeResult insertionResult(prevFirstItemInViewPos);
2196 ChangeResult removalResult(prevFirstItemInViewPos);
2198 int removedCount = 0;
2199 for (
const QQmlChangeSet::Change &r : removals) {
2200 itemCount -= r.count;
2201 if (applyRemovalChange(r, &removalResult, &removedCount))
2202 visibleAffected =
true;
2203 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(r.index))
2204 visibleAffected =
true;
2205 const int correctedFirstVisibleIndex = prevFirstItemInViewIndex - removalResult.countChangeBeforeVisible;
2206 if (correctedFirstVisibleIndex >= 0 && r.index < correctedFirstVisibleIndex) {
2207 if (r.index + r.count < correctedFirstVisibleIndex)
2208 removalResult.countChangeBeforeVisible += r.count;
2210 removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - r.index);
2213#if QT_CONFIG(quick_viewtransitions)
2214 if (runDelayedRemoveTransition) {
2215 QQmlChangeSet::Change removal;
2216 for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
2217 FxViewItem *item = *it;
2218 if (item->index == -1 && (!item->attached || !item->attached->delayRemove())) {
2219 removeItem(item, removal, &removalResult);
2221 it = visibleItems.erase(it);
2228 *totalRemovalResult += removalResult;
2229 if (!removals.isEmpty()) {
2230 updateVisibleIndex();
2233 if (!insertions.isEmpty()) {
2234 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2235 layoutVisibleItems(removals.first().index);
2236 storeFirstVisibleItemPosition();
2240 QList<FxViewItem *> newItems;
2241 QList<MovedItem> movingIntoView;
2243 for (
int i=0; i<insertions.size(); i++) {
2244 bool wasEmpty = visibleItems.isEmpty();
2245 if (applyInsertionChange(insertions[i], &insertionResult, &newItems, &movingIntoView))
2246 visibleAffected =
true;
2247 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index))
2248 visibleAffected =
true;
2249 if (wasEmpty && !visibleItems.isEmpty())
2250 resetFirstItemPosition();
2251 *totalInsertionResult += insertionResult;
2254 if (i < insertions.size() - 1) {
2255 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2256 layoutVisibleItems(insertions[i].index);
2257 storeFirstVisibleItemPosition();
2259 itemCount += insertions[i].count;
2261 for (FxViewItem *item : std::as_const(newItems)) {
2263 item->attached->emitAdd();
2266#if QT_CONFIG(quick_viewtransitions)
2270 if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition,
true)) {
2271 for (
const MovedItem &m : std::as_const(movingIntoView)) {
2272 int fromIndex = findMoveKeyIndex(m.moveKey, removals);
2273 if (fromIndex >= 0) {
2274 if (prevFirstItemInViewIndex >= 0 && fromIndex < prevFirstItemInViewIndex)
2275 repositionItemAt(m.item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
2277 repositionItemAt(m.item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
2278 m.item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2285 if (removedCount != prevVisibleItemsCount)
2286 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstItemInView, &insertionResult, &removalResult);
2289#if QT_CONFIG(quick_viewtransitions)
2290 prepareRemoveTransitions(¤tChanges.removedItems);
2292 for (
auto it = currentChanges.removedItems.begin();
2293 it != currentChanges.removedItems.end(); ++it) {
2294 releaseItem(it.value(), reusableFlag);
2296 currentChanges.removedItems.clear();
2298 if (currentChanges.currentChanged) {
2299 if (currentChanges.currentRemoved && currentItem) {
2300 if (currentItem->item && currentItem->attached)
2301 currentItem->attached->setIsCurrentItem(
false);
2302 const bool hadCurrentItem = currentItem !=
nullptr;
2303 releaseCurrentItem(reusableFlag);
2305 emit q->currentItemChanged();
2307 if (!currentIndexCleared)
2308 updateCurrent(currentChanges.newCurrentIndex);
2311 if (!visibleAffected)
2312 visibleAffected = !currentChanges.pendingChanges.changes().isEmpty();
2313 currentChanges.reset();
2316 if (prevItemCount != itemCount)
2318 if (!visibleAffected && viewportChanged)
2321 return visibleAffected;
2324bool QQuickItemViewPrivate::applyRemovalChange(
const QQmlChangeSet::Change &removal, ChangeResult *removeResult,
int *removedCount)
2326 Q_Q(QQuickItemView);
2327 bool visibleAffected =
false;
2329 if (visibleItems.size() && removal.index + removal.count > visibleItems.constLast()->index) {
2330 if (removal.index > visibleItems.constLast()->index)
2331 removeResult->countChangeAfterVisibleItems += removal.count;
2333 removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.constLast()->index);
2336 QList<FxViewItem*>::Iterator it = visibleItems.begin();
2337 while (it != visibleItems.end()) {
2338 FxViewItem *item = *it;
2339 if (item->index == -1 || item->index < removal.index) {
2341 if (!visibleAffected && item->index < removal.index)
2342 visibleAffected =
true;
2344 }
else if (item->index >= removal.index + removal.count) {
2346 item->index -= removal.count;
2347#if QT_CONFIG(quick_viewtransitions)
2348 if (removal.isMove())
2349 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
false);
2351 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
false);
2356 visibleAffected =
true;
2357 if (!removal.isMove() && item->item && item->attached)
2358 item->attached->emitRemove();
2360 if (item->item && item->attached && item->attached->delayRemove() && !removal.isMove()) {
2362 QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
2365 removeItem(item, removal, removeResult);
2366 if (!removal.isMove())
2368 it = visibleItems.erase(it);
2373 return visibleAffected;
2376void QQuickItemViewPrivate::removeItem(FxViewItem *item,
const QQmlChangeSet::Change &removal, ChangeResult *removeResult)
2378 if (removeResult->visiblePos.isValid()) {
2379 if (item->position() < removeResult->visiblePos)
2380 updateSizeChangesBeforeVisiblePos(item, removeResult);
2382 removeResult->sizeChangesAfterVisiblePos += item->size();
2384 if (removal.isMove()) {
2385 currentChanges.removedItems.replace(removal.moveKey(item->index), item);
2386#if QT_CONFIG(quick_viewtransitions)
2387 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition,
true);
2391 currentChanges.removedItems.insert(QQmlChangeSet::MoveKey(), item);
2393 if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
2394 removeResult->changedFirstItem =
true;
2397void QQuickItemViewPrivate::updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
2399 removeResult->sizeChangesBeforeVisiblePos += item->size();
2402void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
2403 qreal prevVisibleItemsFirstPos,
2404 FxViewItem *prevFirstVisible,
2405 ChangeResult *insertionResult,
2406 ChangeResult *removalResult)
2408 const QQmlNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
2411 if (visibleItems.size()) {
2412 if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
2413 resetFirstItemPosition(prevVisibleItemsFirstPos);
2415 if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible
2416 && prevFirstVisible != *visibleItems.constBegin()) {
2419 if (!insertionResult->changedFirstItem)
2420 resetFirstItemPosition(prevVisibleItemsFirstPos);
2422 }
else if (prevViewPos.isValid()) {
2423 qreal moveForwardsBy = 0;
2424 qreal moveBackwardsBy = 0;
2427 const auto pos = visibleItems.constFirst()->position();
2428 if (pos > prevViewPos) {
2429 moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
2430 moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
2431 }
else if (pos < prevViewPos) {
2432 moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
2433 moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
2435 adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->countChangeBeforeVisible - removalResult->countChangeBeforeVisible);
2437 insertionResult->reset();
2438 removalResult->reset();
2442#if QT_CONFIG(quick_viewtransitions)
2443void QQuickItemViewPrivate::createTransitioner()
2445 if (!transitioner) {
2446 transitioner =
new QQuickItemViewTransitioner;
2447 transitioner->setChangeListener(
this);
2451void QQuickItemViewPrivate::prepareVisibleItemTransitions()
2453 Q_Q(QQuickItemView);
2458 QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
2459 for (
int i=0; i<visibleItems.size(); i++)
2460 visibleItems[i]->prepareTransition(transitioner, viewBounds);
2463void QQuickItemViewPrivate::prepareRemoveTransitions(QMultiHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems)
2468 if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
true)
2469 || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition,
false)) {
2470 for (
auto it = removedItems->begin(); it != removedItems->end(); ) {
2471 bool isRemove = it.key().moveId < 0;
2473 FxViewItem *item = *it;
2474 item->trackGeometry(
false);
2475 item->releaseAfterTransition =
true;
2476 releasePendingTransition.append(item);
2477 item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition,
true);
2478 it = removedItems->erase(it);
2486bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item,
const QRectF &viewBounds)
2496 if (item->scheduledTransitionType() == QQuickItemViewTransitioner::MoveTransition)
2497 repositionItemAt(item, item->index, 0);
2499 bool success =
false;
2500 ACTION_IF_DELETED(item, success = item->prepareTransition(transitioner, viewBounds),
return success);
2503 item->releaseAfterTransition =
true;
2509void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
2511 for (
int i=0; i<releasePendingTransition.size(); i++) {
2512 if (releasePendingTransition.at(i)->transitionableItem == item) {
2513 releaseItem(releasePendingTransition.takeAt(i), reusableFlag);
2521
2522
2523
2524
2525FxViewItem *QQuickItemViewPrivate::createItem(
int modelIndex, QQmlIncubator::IncubationMode incubationMode)
2527 Q_Q(QQuickItemView);
2529 if (requestedIndex == modelIndex && incubationMode == QQmlIncubator::Asynchronous)
2532#if QT_CONFIG(quick_viewtransitions)
2533 for (
int i=0; i<releasePendingTransition.size(); i++) {
2534 if (releasePendingTransition.at(i)->index == modelIndex
2535 && !releasePendingTransition.at(i)->isPendingRemoval()) {
2536 releasePendingTransition[i]->releaseAfterTransition =
false;
2537 return releasePendingTransition.takeAt(i);
2546 QObject* object = modelIndex < model->count() ? model->object(modelIndex, incubationMode) :
nullptr;
2547 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
2551 if (requestedIndex == -1 && model->incubationStatus(modelIndex) == QQmlIncubator::Loading) {
2555 requestedIndex = modelIndex;
2558 model->release(object);
2559 if (!delegateValidated) {
2560 delegateValidated =
true;
2561 QObject* delegate = q->delegate();
2562 qmlWarning(delegate ? delegate : q) << QQuickItemView::tr(
"Delegate must be of Item type");
2571 if (qobject_cast<QQmlObjectModel *>(model))
2572 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(
this, itemChangeListenerTypes);
2574 item->setParentItem(q->contentItem());
2575 if (requestedIndex == modelIndex)
2576 requestedIndex = -1;
2577 FxViewItem *viewItem = newViewItem(modelIndex, item);
2579 viewItem->index = modelIndex;
2582 initializeViewItem(viewItem);
2583 unrequestedItems.remove(item);
2590void QQuickItemView::createdItem(
int index, QObject* object)
2592 Q_D(QQuickItemView);
2594 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2595 if (!d->inRequest) {
2596 d->unrequestedItems.insert(item, index);
2597 QQuickItemPrivate::get(item)->updateOrAddItemChangeListener(d, itemChangeListenerTypes);
2598 d->requestedIndex = -1;
2599 if (d->hasPendingChanges())
2603 if (d->unrequestedItems.contains(item))
2604 d->repositionPackageItemAt(item, index);
2605 else if (index == d->currentIndex)
2606 d->updateCurrent(index);
2610void QQuickItemView::initItem(
int, QObject *object)
2612 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2614 if (qFuzzyIsNull(item->z()))
2616 item->setParentItem(contentItem());
2617 QQuickItemPrivate::get(item)->setCulled(
true);
2622void QQuickItemView::destroyingItem(QObject *object)
2624 Q_D(QQuickItemView);
2625 QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
2627 item->setParentItem(
nullptr);
2628 d->unrequestedItems.remove(item);
2629 QQuickItemPrivate::get(item)->removeItemChangeListener(d, itemChangeListenerTypes);
2633void QQuickItemView::onItemPooled(
int modelIndex, QObject *object)
2635 Q_UNUSED(modelIndex);
2637 if (
auto *attached = d_func()->getAttachedObject(object))
2638 emit attached->pooled();
2641void QQuickItemView::onItemReused(
int modelIndex, QObject *object)
2643 Q_UNUSED(modelIndex);
2645 if (
auto *attached = d_func()->getAttachedObject(object))
2646 emit attached->reused();
2649bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::ReusableFlag reusableFlag)
2651 Q_Q(QQuickItemView);
2654 if (trackedItem == item)
2655 trackedItem =
nullptr;
2656 item->trackGeometry(
false);
2658 QQmlInstanceModel::ReleaseFlags flags = {};
2659 bool removeItemChangeListener =
true;
2660 if (QPointer<QQuickItem> quickItem = item->item) {
2662 flags = model->release(quickItem, reusableFlag);
2665 if (quickItem->parentItem() == contentItem) {
2668 QQuickItemPrivate::get(quickItem)->setCulled(
true);
2672 if (!isClearing && !QObjectPrivate::get(quickItem)->deleteLaterCalled) {
2673 unrequestedItems.insert(quickItem, model->indexOf(quickItem, q));
2674 QQuickItemPrivate::get(quickItem)->updateOrAddItemChangeListener(
this, itemChangeListenerTypes);
2675 removeItemChangeListener =
false;
2677 }
else if (flags & QQmlInstanceModel::Destroyed) {
2678 quickItem->setParentItem(
nullptr);
2679 }
else if (flags & QQmlInstanceModel::Pooled) {
2680 item->setVisible(
false);
2684 if (removeItemChangeListener)
2685 QQuickItemPrivate::get(quickItem)->removeItemChangeListener(
this, itemChangeListenerTypes);
2686#if QT_CONFIG(quick_viewtransitions)
2687 delete item->transitionableItem;
2688 item->transitionableItem =
nullptr;
2693 return flags != QQmlInstanceModel::Referenced;
2697
2698
2699
2700
2701
2702
2703
2704
2705void QQuickItemViewPrivate::itemDestroyed(QQuickItem *item)
2709 FxViewItem *visibleFxItem =
nullptr;
2710 const int indexOfItem = -1;
2711 for (
auto *fxItem : std::as_const(visibleItems)) {
2712 if (fxItem->item == item) {
2713 visibleFxItem = fxItem;
2720 if (currentItem && visibleFxItem)
2721 Q_ASSERT(currentItem != visibleFxItem);
2723 if (visibleFxItem) {
2724 qCDebug(lcItemViewDelegateLifecycle) <<
"removing deleted item"
2725 << item << visibleFxItem <<
"at index" << indexOfItem <<
"without running transitions";
2728 const bool removedVisibleFxItem = visibleItems.removeOne(visibleFxItem);
2729 Q_ASSERT(removedVisibleFxItem);
2730 releaseItem(visibleFxItem, QQmlDelegateModel::NotReusable);
2733 if (currentItem && currentItem->item == item) {
2734 releaseItem(currentItem, QQmlDelegateModel::NotReusable);
2735 currentItem =
nullptr;
2738 unrequestedItems.remove(item);
2741 forceLayoutPolish();
2744QQuickItem *QQuickItemViewPrivate::createHighlightItem()
2746 QQuickItem *item =
nullptr;
2749 item = createComponentItem(highlightComponent, 0.0,
true);
2755QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue,
bool createDefault)
const
2757 Q_Q(
const QQuickItemView);
2759 QQuickItem *item =
nullptr;
2761 QQmlContext *context = component->creationContext();
2763 context = qmlContext(q);
2765 if (QObject *nobj = component->beginCreate(context)) {
2766 item = qobject_cast<QQuickItem *>(nobj);
2770 }
else if (createDefault) {
2771 item =
new QQuickItem;
2774 if (qFuzzyIsNull(item->z()))
2776 QQml_setParent_noEvent(item, q->contentItem());
2777 item->setParentItem(q->contentItem());
2779 initializeComponentItem(item);
2782 component->completeCreate();
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796void QQuickItemViewPrivate::initializeComponentItem(QQuickItem *item)
const
2801void QQuickItemViewPrivate::updateTrackedItem()
2803 Q_Q(QQuickItemView);
2804 FxViewItem *item = currentItem;
2806 item = highlight.get();
2810 q->trackedPositionChanged();
2813void QQuickItemViewPrivate::updateUnrequestedIndexes()
2815 Q_Q(QQuickItemView);
2816 for (QHash<QQuickItem*,
int>::iterator it = unrequestedItems.begin(), end = unrequestedItems.end(); it != end; ++it)
2817 *it = model->indexOf(it.key(), q);
2820void QQuickItemViewPrivate::updateUnrequestedPositions()
2822 for (QHash<QQuickItem*,
int>::const_iterator it = unrequestedItems.cbegin(), cend = unrequestedItems.cend(); it != cend; ++it) {
2823 if (it.value() >= 0)
2824 repositionPackageItemAt(it.key(), it.value());
2828void QQuickItemViewPrivate::updateVisibleIndex()
2830 typedef QList<FxViewItem*>::const_iterator FxViewItemListConstIt;
2833 for (FxViewItemListConstIt it = visibleItems.constBegin(), cend = visibleItems.constEnd(); it != cend; ++it) {
2834 if ((*it)->index != -1) {
2835 visibleIndex = (*it)->index;
2841QQmlDelegateModel::DelegateModelAccess QQuickItemView::delegateModelAccess()
const
2843 Q_D(
const QQuickItemView);
2844 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->model))
2845 return dataModel->delegateModelAccess();
2846 return QQmlDelegateModel::Qt5ReadWrite;
2849void QQuickItemView::setDelegateModelAccess(
2850 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
2852 Q_D(QQuickItemView);
2853 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
2854 delegateModel->setDelegateModelAccess(delegateModelAccess);
2855 d->explicitDelegateModelAccess =
true;
2859 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2861 d->explicitDelegateModelAccess =
true;
2865 setExplicitDelegateModelAccess(QQmlDelegateModel::createForView(
this, d));
2870 emit delegateModelAccessChanged();
2874 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
2877 d->explicitDelegateModelAccess =
false;
2878 setExplicitDelegateModelAccess(delegateModel);
2882 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
2883 d->explicitDelegateModelAccess =
true;
2885 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
2886 "non-DelegateModel";
2892#include "moc_qquickitemview_p.cpp"
Combined button and popup list for selecting options.
static FxViewItem * fxViewItemAtPosition(const QList< FxViewItem * > &items, qreal x, qreal y)
#define QML_VIEW_DEFAULTCACHEBUFFER