diff options
Diffstat (limited to 'src/quick/items/qquickitemview.cpp')
-rw-r--r-- | src/quick/items/qquickitemview.cpp | 114 |
1 files changed, 70 insertions, 44 deletions
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index bfba88afe9..8ff8b8860c 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1436,12 +1436,16 @@ bool QQuickItemViewPrivate::applyModelChanges() || !currentChanges.pendingChanges.inserts().isEmpty(); FxViewItem *prevFirstVisible = firstVisibleItem(); - QDeclarativeNullableValue<qreal> prevFirstVisiblePos; + QDeclarativeNullableValue<qreal> prevViewPos; if (prevFirstVisible) - prevFirstVisiblePos = prevFirstVisible->position(); + prevViewPos = prevFirstVisible->position(); + qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.first()->position() : 0.0; const QVector<QDeclarativeChangeSet::Remove> &removals = currentChanges.pendingChanges.removes(); - ChangeResult removalResult(prevFirstVisiblePos); + const QVector<QDeclarativeChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts(); + ChangeResult removalResult(prevViewPos); + ChangeResult insertionResult(prevViewPos); + int removedCount = 0; for (int i=0; i<removals.count(); i++) { itemCount -= removals[i].count; @@ -1450,53 +1454,40 @@ bool QQuickItemViewPrivate::applyModelChanges() if (!visibleAffected && needsRefillForAddedOrRemovedIndex(removals[i].index)) visibleAffected = true; } - if (!removals.isEmpty()) + if (!removals.isEmpty()) { updateVisibleIndex(); - const QVector<QDeclarativeChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts(); - ChangeResult insertionResult(prevFirstVisiblePos); - bool newVisibleItemsFirst = false; + // set positions correctly for the next insertion + if (!insertions.isEmpty()) { + repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, insertionResult, removalResult); + layoutVisibleItems(removals.first().index); + } + } + QList<FxViewItem *> newItems; for (int i=0; i<insertions.count(); i++) { bool wasEmpty = visibleItems.isEmpty(); - if (applyInsertionChange(insertions[i], &insertionResult, &newVisibleItemsFirst, &newItems)) + if (applyInsertionChange(insertions[i], &insertionResult, &newItems)) visibleAffected = true; if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index)) visibleAffected = true; if (wasEmpty && !visibleItems.isEmpty()) resetFirstItemPosition(); + + // set positions correctly for the next insertion + if (i < insertions.count() - 1) { + repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, insertionResult, removalResult); + layoutVisibleItems(insertions[i].index); + } + itemCount += insertions[i].count; } for (int i=0; i<newItems.count(); i++) newItems.at(i)->attached->emitAdd(); // reposition visibleItems.first() correctly so that the content y doesn't jump - if (visibleItems.count() && removedCount != prevVisibleItemsCount) { - if (newVisibleItemsFirst && prevVisibleItemsFirst) - resetItemPosition(visibleItems.first(), prevVisibleItemsFirst); - - if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible - && prevFirstVisible != visibleItems.first()) { - // the previous visibleItems.first() was also the first visible item, and it has been - // moved/removed, so move the new visibleItems.first() to the pos of the previous one - if (!newVisibleItemsFirst) - resetItemPosition(visibleItems.first(), prevFirstVisible); - - } else if (prevFirstVisiblePos.isValid()) { - qreal moveForwardsBy = 0; - qreal moveBackwardsBy = 0; - - // shift visibleItems.first() relative to the number of added/removed items - if (visibleItems.first()->position() > prevFirstVisiblePos) { - moveForwardsBy = insertionResult.sizeChangesAfterVisiblePos; - moveBackwardsBy = removalResult.sizeChangesAfterVisiblePos; - } else if (visibleItems.first()->position() < prevFirstVisiblePos) { - moveForwardsBy = removalResult.sizeChangesBeforeVisiblePos; - moveBackwardsBy = insertionResult.sizeChangesBeforeVisiblePos; - } - adjustFirstItem(moveForwardsBy, moveBackwardsBy); - } - } + if (removedCount != prevVisibleItemsCount) + repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, insertionResult, removalResult); // Whatever removed/moved items remain are no longer visible items. for (QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin(); @@ -1529,7 +1520,7 @@ bool QQuickItemViewPrivate::applyModelChanges() return visibleAffected; } -bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remove &removal, ChangeResult *insertResult, int *removedCount) +bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remove &removal, ChangeResult *removeResult, int *removedCount) { Q_Q(QQuickItemView); bool visibleAffected = false; @@ -1557,15 +1548,11 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection); ++it; } else { - if (insertResult->visiblePos.isValid()) { - if (item->position() < insertResult->visiblePos) { - // sizeRemovedBeforeFirstVisible measures the size between the visibleItems.first() - // and the firstVisible, so don't count it if removing visibleItems.first() - if (item != visibleItems.first()) - insertResult->sizeChangesBeforeVisiblePos += item->size(); - } else { - insertResult->sizeChangesAfterVisiblePos += item->size(); - } + if (removeResult->visiblePos.isValid()) { + if (item->position() < removeResult->visiblePos) + removeResult->sizeChangesBeforeVisiblePos += item->size(); + else + removeResult->sizeChangesAfterVisiblePos += item->size(); } if (removal.isMove()) { currentChanges.removedItems.insert(removal.moveKey(item->index), item); @@ -1574,6 +1561,8 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item); (*removedCount)++; } + if (!removeResult->changedFirstItem && item == visibleItems.first()) + removeResult->changedFirstItem = true; it = visibleItems.erase(it); } } @@ -1581,6 +1570,43 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo return visibleAffected; } +void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst, + qreal prevVisibleItemsFirstPos, + FxViewItem *prevFirstVisible, + const ChangeResult &insertionResult, + const ChangeResult &removalResult) +{ + const QDeclarativeNullableValue<qreal> prevViewPos = insertionResult.visiblePos; + + // reposition visibleItems.first() correctly so that the content y doesn't jump + if (visibleItems.count()) { + if (prevVisibleItemsFirst && insertionResult.changedFirstItem) + resetFirstItemPosition(prevVisibleItemsFirstPos); + + if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible + && prevFirstVisible != *visibleItems.constBegin()) { + // the previous visibleItems.first() was also the first visible item, and it has been + // moved/removed, so move the new visibleItems.first() to the pos of the previous one + if (!insertionResult.changedFirstItem) + resetFirstItemPosition(prevVisibleItemsFirstPos); + + } else if (prevViewPos.isValid()) { + qreal moveForwardsBy = 0; + qreal moveBackwardsBy = 0; + + // shift visibleItems.first() relative to the number of added/removed items + if (visibleItems.first()->position() > prevViewPos) { + moveForwardsBy = insertionResult.sizeChangesAfterVisiblePos; + moveBackwardsBy = removalResult.sizeChangesAfterVisiblePos; + } else if (visibleItems.first()->position() < prevViewPos) { + moveForwardsBy = removalResult.sizeChangesBeforeVisiblePos; + moveBackwardsBy = insertionResult.sizeChangesBeforeVisiblePos; + } + adjustFirstItem(moveForwardsBy, moveBackwardsBy); + } + } +} + /* This may return 0 if the item is being created asynchronously. When the item becomes available, refill() will be called and the item |