diff options
Diffstat (limited to 'src/quick/items/qquickitemview.cpp')
| -rw-r--r-- | src/quick/items/qquickitemview.cpp | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index fea7dba2c3..210759585b 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -10,6 +10,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcItemViewDelegateLifecycle, "qt.quick.itemview.lifecycle") +Q_LOGGING_CATEGORY(lcCount, "qt.quick.itemview.count") // Default cacheBuffer for all views. #ifndef QML_VIEW_DEFAULTCACHEBUFFER @@ -223,7 +224,7 @@ void QQuickItemView::setModel(const QVariant &m) this, SLOT(modelUpdated(QQmlChangeSet,bool))); if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) QObjectPrivate::connect(dataModel, &QQmlDelegateModel::delegateChanged, d, &QQuickItemViewPrivate::applyDelegateChange); - emit countChanged(); + d->emitCountChanged(); } emit modelChanged(); d->moveReason = QQuickItemViewPrivate::Other; @@ -255,7 +256,7 @@ void QQuickItemView::setDelegate(QQmlComponent *delegate) int oldCount = dataModel->count(); dataModel->setDelegate(delegate); if (oldCount != dataModel->count()) - emit countChanged(); + d->emitCountChanged(); } emit delegateChanged(); d->delegateValidated = false; @@ -1086,8 +1087,7 @@ qreal QQuickItemViewPrivate::calculatedMaxExtent() const void QQuickItemViewPrivate::applyDelegateChange() { releaseVisibleItems(QQmlDelegateModel::NotReusable); - releaseItem(currentItem, QQmlDelegateModel::NotReusable); - currentItem = nullptr; + releaseCurrentItem(QQmlDelegateModel::NotReusable); updateSectionCriteria(); refill(); moveReason = QQuickItemViewPrivate::SetIndex; @@ -1126,6 +1126,14 @@ void QQuickItemViewPrivate::showVisibleItems() const } } +// Simplifies debugging of count. +void QQuickItemViewPrivate::emitCountChanged() +{ + Q_Q(QQuickItemView); + qCDebug(lcCount).nospace() << "about to emit countChanged for " << q << "; count changed to " << q->count(); + emit q->countChanged(); +} + void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) { @@ -1225,7 +1233,7 @@ void QQuickItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) d->updateTrackedItem(); } d->moveReason = QQuickItemViewPrivate::Other; - emit countChanged(); + d->emitCountChanged(); #if QT_CONFIG(quick_viewtransitions) if (d->transitioner && d->transitioner->populateTransition) d->forceLayoutPolish(); @@ -1486,7 +1494,7 @@ void QQuickItemView::componentComplete() d->fixupPosition(); } if (d->model && d->model->count()) - emit countChanged(); + d->emitCountChanged(); } @@ -1653,8 +1661,7 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex) if (currentItem) { if (currentItem->attached) currentItem->attached->setIsCurrentItem(false); - releaseItem(currentItem, reusableFlag); - currentItem = nullptr; + releaseCurrentItem(reusableFlag); currentIndex = modelIndex; emit q->currentIndexChanged(); emit q->currentItemChanged(); @@ -1715,10 +1722,9 @@ void QQuickItemViewPrivate::clear(bool onDestruction) releasePendingTransition.clear(); #endif - auto oldCurrentItem = currentItem; - releaseItem(currentItem, QQmlDelegateModel::NotReusable); - currentItem = nullptr; - if (oldCurrentItem) + const bool hadCurrentItem = currentItem != nullptr; + releaseCurrentItem(QQmlDelegateModel::NotReusable); + if (hadCurrentItem) emit q->currentItemChanged(); createHighlight(onDestruction); trackedItem = nullptr; @@ -1763,7 +1769,7 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to) Q_Q(QQuickItemView); if (!model || !model->isValid() || !q->isComponentComplete()) return; - if (q->size().isEmpty() && visibleItems.isEmpty()) + if (q->size().isNull() && visibleItems.isEmpty()) return; if (!model->count()) { updateHeader(); @@ -1814,7 +1820,7 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to) } if (prevCount != itemCount) - emit q->countChanged(); + emitCountChanged(); } while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()); storeFirstVisibleItemPosition(); } @@ -1861,7 +1867,20 @@ void QQuickItemViewPrivate::layout() // viewBounds contains bounds before any add/remove/move operation to the view QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height()); - if (!isValid() && !visibleItems.size()) { + // We use isNull for the size check, because isEmpty returns true + // if either dimension is negative, but apparently we support negative-sized + // views (see tst_QQuickListView::resizeView). + if ((!isValid() && !visibleItems.size()) || q->size().isNull()) { + if (q->size().isNull() && hasPendingChanges()) { + // count() refers to the number of items in the model, not in the view + // (which is why we don't emit for the !visibleItems.size() case). + // If there are pending model changes, emit countChanged in order to + // support the use case of QTBUG-129165, where visible is bound to count > 0 + // and the ListView is in a layout with Layout.preferredHeight bound to + // contentHeight. This ensures that a hidden ListView will become visible. + emitCountChanged(); + } + clear(); setPosition(contentStartOffset()); updateViewport(); @@ -2121,10 +2140,9 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult if (currentChanges.currentRemoved && currentItem) { if (currentItem->item && currentItem->attached) currentItem->attached->setIsCurrentItem(false); - auto oldCurrentItem = currentItem; - releaseItem(currentItem, reusableFlag); - currentItem = nullptr; - if (oldCurrentItem) + const bool hadCurrentItem = currentItem != nullptr; + releaseCurrentItem(reusableFlag); + if (hadCurrentItem) emit q->currentItemChanged(); } if (!currentIndexCleared) @@ -2137,7 +2155,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult updateSections(); if (prevItemCount != itemCount) - emit q->countChanged(); + emitCountChanged(); if (!visibleAffected && viewportChanged) updateViewport(); @@ -2491,9 +2509,15 @@ bool QQuickItemViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::Reu return flags != QQmlInstanceModel::Referenced; } -QQuickItem *QQuickItemViewPrivate::createHighlightItem() const +QQuickItem *QQuickItemViewPrivate::createHighlightItem() { - return createComponentItem(highlightComponent, 0.0, true); + QQuickItem *item = nullptr; + if (!inRequest) { + inRequest = true; + item = createComponentItem(highlightComponent, 0.0, true); + inRequest = false; + } + return item; } QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault) const |
