aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickitemview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickitemview.cpp')
-rw-r--r--src/quick/items/qquickitemview.cpp114
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