summaryrefslogtreecommitdiffstats
path: root/src/declarative/graphicsitems/qmlgraphicslistview.cpp
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2009-12-04 06:44:33 (GMT)
committerMartin Jones <martin.jones@nokia.com>2009-12-04 06:44:33 (GMT)
commit510a85d350d4a5a538818af0f6b00c17cf081ea2 (patch)
tree84decc7839aa04a999a3bbe36f3ada2ff59e0678 /src/declarative/graphicsitems/qmlgraphicslistview.cpp
parent5d3db0fbfa96964b9448705d9edd4c0cd9e65816 (diff)
downloadQt-510a85d350d4a5a538818af0f6b00c17cf081ea2.zip
Qt-510a85d350d4a5a538818af0f6b00c17cf081ea2.tar.gz
Qt-510a85d350d4a5a538818af0f6b00c17cf081ea2.tar.bz2
Fix item insertion/deletion before first visible item.
Also avoid destroying items in the same frame as adding items.
Diffstat (limited to 'src/declarative/graphicsitems/qmlgraphicslistview.cpp')
-rw-r--r--src/declarative/graphicsitems/qmlgraphicslistview.cpp149
1 files changed, 104 insertions, 45 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
index 2711059..5c78b7b 100644
--- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp
+++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp
@@ -182,7 +182,7 @@ public:
, snapMode(QmlGraphicsListView::NoSnap), overshootDist(0.0)
, footerComponent(0), footer(0), headerComponent(0), header(0)
, ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false)
- , correctFlick(true)
+ , correctFlick(true), lazyRelease(false)
{}
void init();
@@ -208,7 +208,7 @@ public:
if (item->index != -1 && item->endPosition() > pos)
return item;
}
- return 0;
+ return visibleItems.count() ? visibleItems.first() : 0;
}
FxListItem *nextVisibleItem() const {
@@ -483,6 +483,7 @@ public:
bool autoHighlight : 1;
bool haveHighlightRange : 1;
bool correctFlick : 1;
+ bool lazyRelease : 1;
static int itemResizedIdx;
};
@@ -616,23 +617,27 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to)
changed = true;
}
- while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < from) {
- if (item->attached->delayRemove())
- break;
- //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
- if (item->index != -1)
- visibleIndex++;
- visibleItems.removeFirst();
- releaseItem(item);
- changed = true;
- }
- while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > to) {
- if (item->attached->delayRemove())
- break;
- //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
- visibleItems.removeLast();
- releaseItem(item);
- changed = true;
+ if (!lazyRelease || !changed) { // avoid destroying items in the same frame that we create
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < from) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > to) {
+ if (item->attached->delayRemove())
+ break;
+ //qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
+ }
+ } else {
+ qDebug() << "lazyRelease" << lazyRelease << "changed";
}
if (changed) {
if (visibleItems.count())
@@ -646,6 +651,7 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to)
updateFooter();
updateViewport();
}
+ lazyRelease = false;
}
void QmlGraphicsListViewPrivate::layout()
@@ -1892,6 +1898,7 @@ void QmlGraphicsListView::viewportMoved()
{
Q_D(QmlGraphicsListView);
QmlGraphicsFlickable::viewportMoved();
+ d->lazyRelease = true;
refill();
if (isFlicking() || d->moving)
d->moveReason = QmlGraphicsListViewPrivate::Mouse;
@@ -2230,42 +2237,75 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count)
// At least some of the added items will be visible
int index = modelIndex - d->visibleIndex;
- int to = d->buffer+d->position()+d->size()-1;
// index can be the next item past the end of the visible items list (i.e. appended)
int pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
: d->visibleItems.at(index-1)->endPosition()+d->spacing+1;
int initialPos = pos;
+ int diff = 0;
QList<FxListItem*> added;
- for (int i = 0; i < count && pos <= to; ++i) {
- FxListItem *item = d->createItem(modelIndex + i);
- d->visibleItems.insert(index, item);
- item->setPosition(pos);
- added.append(item);
- pos += item->size() + d->spacing;
- ++index;
+ FxListItem *firstVisible = d->firstVisibleItem();
+ if (firstVisible && pos < firstVisible->position()) {
+ // Insert items before the visible item.
+ int insertionIdx = index;
+ int i = 0;
+ int from = d->position() - d->buffer;
+ for (i = count-1; i >= 0 && pos > from; --i) {
+ FxListItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(insertionIdx, item);
+ pos -= item->size() + d->spacing;
+ item->setPosition(pos);
+ index++;
+ }
+ if (i >= 0) {
+ // If we didn't insert all our new items - anything
+ // before the current index is not visible - remove it.
+ while (insertionIdx--) {
+ FxListItem *item = d->visibleItems.takeFirst();
+ if (item->index != -1)
+ d->visibleIndex++;
+ d->releaseItem(item);
+ }
+ } else {
+ // adjust pos of items before inserted items.
+ for (int i = insertionIdx-1; i >= 0; i--) {
+ FxListItem *listItem = d->visibleItems.at(i);
+ listItem->setPosition(listItem->position() - (initialPos - pos));
+ }
+ }
+ } else {
+ int i = 0;
+ int to = d->buffer+d->position()+d->size()-1;
+ for (i = 0; i < count && pos <= to; ++i) {
+ FxListItem *item = d->createItem(modelIndex + i);
+ d->visibleItems.insert(index, item);
+ item->setPosition(pos);
+ added.append(item);
+ pos += item->size() + d->spacing;
+ ++index;
+ }
+ if (i != count) {
+ // We didn't insert all our new items, which means anything
+ // beyond the current index is not visible - remove it.
+ while (d->visibleItems.count() > index)
+ d->releaseItem(d->visibleItems.takeLast());
+ }
+ diff = pos - initialPos;
}
if (d->currentIndex >= modelIndex) {
// adjust current item index
d->currentIndex += count;
if (d->currentItem) {
d->currentItem->index = d->currentIndex;
- d->currentItem->setPosition(d->currentItem->position() + (pos - initialPos));
+ d->currentItem->setPosition(d->currentItem->position() + diff);
}
}
- if (pos > to) {
- // We didn't insert all our new items, which means anything
- // beyond the current index is not visible - remove it.
- while (d->visibleItems.count() > index)
- d->releaseItem(d->visibleItems.takeLast());
- } else {
- // Update the indexes of the following visible items.
- for (; index < d->visibleItems.count(); ++index) {
- FxListItem *listItem = d->visibleItems.at(index);
- if (listItem->item != d->currentItem->item)
- listItem->setPosition(listItem->position() + (pos - initialPos));
- if (listItem->index != -1)
- listItem->index += count;
- }
+ // Update the indexes of the following visible items.
+ for (; index < d->visibleItems.count(); ++index) {
+ FxListItem *listItem = d->visibleItems.at(index);
+ if (listItem->item != d->currentItem->item)
+ listItem->setPosition(listItem->position() + diff);
+ if (listItem->index != -1)
+ listItem->index += count;
}
// everything is in order now - emit add() signal
for (int j = 0; j < added.count(); ++j)
@@ -2310,6 +2350,8 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count)
return;
}
+ FxListItem *firstVisible = d->firstVisibleItem();
+ int preRemovedSize = 0;
// Remove the items from the visible list, skipping anything already marked for removal
QList<FxListItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
@@ -2329,12 +2371,19 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count)
connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
++it;
} else {
+ if (item == firstVisible)
+ firstVisible = 0;
+ if (firstVisible && item->position() < firstVisible->position())
+ preRemovedSize += item->size();
it = d->visibleItems.erase(it);
d->releaseItem(item);
}
}
}
+ if (firstVisible && d->visibleItems.first() != firstVisible)
+ d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + preRemovedSize);
+
// fix current
if (d->currentIndex >= modelIndex + count) {
d->currentIndex -= count;
@@ -2396,7 +2445,14 @@ void QmlGraphicsListView::destroyRemoved()
void QmlGraphicsListView::itemsMoved(int from, int to, int count)
{
Q_D(QmlGraphicsListView);
- qreal firstItemPos = d->visibleItems.first()->position();
+
+ if (d->visibleItems.isEmpty()) {
+ refill();
+ return;
+ }
+
+ FxListItem *firstVisible = d->firstVisibleItem();
+ qreal firstItemPos = firstVisible->position();
QHash<int,FxListItem*> moved;
int moveBy = 0;
@@ -2407,7 +2463,8 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count)
// take the items that are moving
item->index += (to-from);
moved.insert(item->index, item);
- moveBy += item->size();
+ if (item->position() < firstItemPos)
+ moveBy += item->size();
it = d->visibleItems.erase(it);
} else {
// move everything after the moved items.
@@ -2427,6 +2484,8 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count)
FxListItem *movedItem = moved.take(item->index);
if (!movedItem)
movedItem = d->createItem(item->index);
+ if (item->index < firstVisible->index)
+ moveBy -= movedItem->size();
it = d->visibleItems.insert(it, movedItem);
++it;
--remaining;
@@ -2454,7 +2513,7 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count)
d->releaseItem(moved.take(moved.begin().key()));
// Ensure we don't cause an ugly list scroll.
- d->visibleItems.first()->setPosition(firstItemPos);
+ d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy);
d->layout();
d->updateSections();