3dfeb5c7b0
1 OBS-URL: https://build.opensuse.org/request/show/359195 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libqt5-qtdeclarative?expand=0&rev=28
142 lines
6.8 KiB
Diff
142 lines
6.8 KiB
Diff
From be1ef858f44e1523ba264520a0361981cf9b37c6 Mon Sep 17 00:00:00 2001
|
|
From: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>
|
|
Date: Wed, 25 Nov 2015 12:14:52 -0800
|
|
Subject: [PATCH] ListView: Sanitize visibleItems list after model insertions
|
|
|
|
In QQuickListViewPrivate::applyInsertionChange(), we update the
|
|
visibleItems list by first shifting the currently visible items
|
|
and then we add as many items as the model was added and at the
|
|
right position. We do this in such a way that we won't create
|
|
items that will not be visible right away (and may be deleted
|
|
right after by removeNonVisibleItems()). However, this may leave
|
|
gaps in the item index sequence, and QQuickListView doesn't always
|
|
recover gracefully from it.
|
|
|
|
The purpose of this patch is to make sure those gaps are cleared
|
|
right after inserting the new items. Since the insertions can happen
|
|
in two different places (either before or after the first visible
|
|
item) we need to update the visibleItems list accordingly. The way
|
|
we sanitize visibleItems is by removing those items that lie beyond
|
|
a possible index gap. If insertion happens before the first visible
|
|
item, we'll remove all those items before the insertion point. If
|
|
the insertion happens after the first visible item, we'll remove the
|
|
items after the insertion point.
|
|
|
|
Besides that, the logic for inserting before the visible position was
|
|
wrong. As items are inserted bottom-up in that case, the insertion
|
|
would start by just accounting for the item's size until the condition
|
|
|
|
pos > from && insertionIdx < visibleIndex
|
|
|
|
would become false only because 'pos' would be small enough. After
|
|
that, the next loop run would start adding items before the 'from'
|
|
position, which is wrong. Our fix is to move the condition outside
|
|
the loop if the insertion index will be before the visible index
|
|
and just account for the items' size in that case. Otherwise, the
|
|
insertion happens as usual until pos < from.
|
|
|
|
Change-Id: I35767cf6e9737bea1fe7677e580245fc7172710c
|
|
Task-number: QTBUG-48870
|
|
---
|
|
src/quick/items/qquicklistview.cpp | 59 ++++++++++++++++++----
|
|
1 files changed, 59 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
|
|
index c7df855..9f53586 100644
|
|
--- a/src/quick/items/qquicklistview.cpp
|
|
+++ b/src/quick/items/qquicklistview.cpp
|
|
@@ -3097,12 +3097,13 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
|
|
int i = 0;
|
|
qreal from = tempPos - displayMarginBeginning - buffer;
|
|
|
|
- for (i = count-1; i >= 0; --i) {
|
|
- if (pos > from && insertionIdx < visibleIndex) {
|
|
- // item won't be visible, just note the size for repositioning
|
|
- insertResult->sizeChangesBeforeVisiblePos += averageSize + spacing;
|
|
- pos -= averageSize + spacing;
|
|
- } else {
|
|
+ if (insertionIdx < visibleIndex) {
|
|
+ if (pos >= from) {
|
|
+ // items won't be visible, just note the size for repositioning
|
|
+ insertResult->sizeChangesBeforeVisiblePos += count * (averageSize + spacing);
|
|
+ }
|
|
+ } else {
|
|
+ for (i = count-1; i >= 0 && pos >= from; --i) {
|
|
// item is before first visible e.g. in cache buffer
|
|
FxViewItem *item = 0;
|
|
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
|
|
@@ -3117,17 +3118,33 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
|
|
insertResult->changedFirstItem = true;
|
|
if (!change.isMove()) {
|
|
addedItems->append(item);
|
|
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
|
|
+ if (transitioner)
|
|
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
|
|
+ else
|
|
+ static_cast<FxListItemSG *>(item)->setPosition(pos, true);
|
|
}
|
|
insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
|
|
pos -= item->size() + spacing;
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int firstOkIdx = -1;
|
|
+ for (int i = 0; i <= insertionIdx && i < visibleItems.count() - 1; i++) {
|
|
+ if (visibleItems.at(i)->index + 1 != visibleItems.at(i + 1)->index) {
|
|
+ firstOkIdx = i + 1;
|
|
+ break;
|
|
}
|
|
- index++;
|
|
}
|
|
+ for (int i = 0; i < firstOkIdx; i++) {
|
|
+ FxViewItem *nvItem = visibleItems.takeFirst();
|
|
+ addedItems->removeOne(nvItem);
|
|
+ removeItem(nvItem);
|
|
+ }
|
|
+
|
|
} else {
|
|
- int i = 0;
|
|
qreal to = buffer + displayMarginEnd + tempPos + size();
|
|
- for (i = 0; i < count && pos <= to; ++i) {
|
|
+ for (int i = 0; i < count && pos <= to; ++i) {
|
|
FxViewItem *item = 0;
|
|
if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
|
|
item->index = modelIndex + i;
|
|
@@ -3147,12 +3164,32 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
|
|
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
|
|
} else {
|
|
addedItems->append(item);
|
|
- item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
|
|
+ if (transitioner)
|
|
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
|
|
+ else
|
|
+ static_cast<FxListItemSG *>(item)->setPosition(pos, true);
|
|
}
|
|
insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
|
|
pos += item->size() + spacing;
|
|
++index;
|
|
}
|
|
+
|
|
+ if (0 < index && index < visibleItems.count()) {
|
|
+ FxViewItem *prevItem = visibleItems.at(index - 1);
|
|
+ FxViewItem *item = visibleItems.at(index);
|
|
+ if (prevItem->index != item->index - 1) {
|
|
+ int i = index;
|
|
+ qreal prevPos = prevItem->position();
|
|
+ while (i < visibleItems.count()) {
|
|
+ FxListItemSG *nvItem = static_cast<FxListItemSG *>(visibleItems.takeLast());
|
|
+ insertResult->sizeChangesAfterVisiblePos -= nvItem->size() + spacing;
|
|
+ addedItems->removeOne(nvItem);
|
|
+ if (nvItem->transitionScheduledOrRunning())
|
|
+ nvItem->setPosition(prevPos + (nvItem->index - prevItem->index) * averageSize);
|
|
+ removeItem(nvItem);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
updateVisibleIndex();
|
|
--
|
|
2.6.2.2.g1b5ffa3
|