diff options
author | Andrew den Exter <[email protected]> | 2012-06-14 15:11:54 +1000 |
---|---|---|
committer | Qt by Nokia <[email protected]> | 2012-06-22 12:47:31 +0200 |
commit | 530b773dfcd2dddeb824cb2a2c7fe1778e5c7985 (patch) | |
tree | 6f129e793fb1faa095d19812eff9f2a3834a69c3 /src/quick/items/qquicklistview.cpp | |
parent | 9e686c502be0b68f39836f29027a58466cb517b7 (diff) |
Fix crash when dragging items outside visible area.
If asynchronous item creation finishes while the content area of a
ListView has been dragged full outside the visible area a full refill
is triggered which can overwrite the requested index and potentially
result in a single delegate item being assigned to multiple view items
and later being doubly released. Only create the view item object in
the createItem function to prevent this from happening.
Secondly only reset the visible items if jumping outside the buffer
range rather than just the fill range to prevent churn when the list
only contains buffered items.
Task-number: QTBUG-26232
Change-Id: I5bce845898ef5f699f34afc268594ef38e01d6a3
Reviewed-by: Martin Jones <[email protected]>
Diffstat (limited to 'src/quick/items/qquicklistview.cpp')
-rw-r--r-- | src/quick/items/qquicklistview.cpp | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index eb0d0139cb..d42d1cbc48 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -88,7 +88,7 @@ public: virtual void init(); virtual void clear(); - virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer); + virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer); virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo); virtual void visibleItemsChanged(); @@ -237,8 +237,6 @@ class FxListItemSG : public FxViewItem public: FxListItemSG(QQuickItem *i, QQuickListView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) { attached = static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(item)); - if (attached) - static_cast<QQuickListViewAttached*>(attached)->setView(view); if (trackGeometry) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry); @@ -569,18 +567,18 @@ FxViewItem *QQuickListViewPrivate::newViewItem(int modelIndex, QQuickItem *item) // initialise attached properties if (sectionCriteria) { QString propValue = model->stringValue(modelIndex, sectionCriteria->property()); - listItem->attached->m_section = sectionCriteria->sectionString(propValue); + listItem->attached->setSection(sectionCriteria->sectionString(propValue)); if (modelIndex > 0) { if (FxViewItem *item = itemBefore(modelIndex)) - listItem->attached->m_prevSection = item->attached->section(); + listItem->attached->setPrevSection(item->attached->section()); else - listItem->attached->m_prevSection = sectionAt(modelIndex-1); + listItem->attached->setPrevSection(sectionAt(modelIndex-1)); } if (modelIndex < model->count()-1) { if (FxViewItem *item = visibleItem(modelIndex+1)) - listItem->attached->m_nextSection = static_cast<QQuickListViewAttached*>(item->attached)->section(); + listItem->attached->setNextSection(static_cast<QQuickListViewAttached*>(item->attached)->section()); else - listItem->attached->m_nextSection = sectionAt(modelIndex+1); + listItem->attached->setNextSection(sectionAt(modelIndex+1)); } } @@ -627,7 +625,7 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item) return released; } -bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) +bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) { qreal itemEnd = visiblePos; if (visibleItems.count()) { @@ -639,8 +637,8 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d bool haveValidItems = modelIndex >= 0; modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1; - if (haveValidItems && (fillFrom > itemEnd+averageSize+spacing - || fillTo < visiblePos - averageSize - spacing)) { + if (haveValidItems && (bufferFrom > itemEnd+averageSize+spacing + || bufferTo < visiblePos - averageSize - spacing)) { // We've jumped more than a page. Estimate which items are now // visible and fill from there. int count = (fillFrom - itemEnd) / (averageSize + spacing); @@ -2739,6 +2737,15 @@ void QQuickListView::geometryChanged(const QRectF &newGeometry, const QRectF &ol QQuickItemView::geometryChanged(newGeometry, oldGeometry); } +void QQuickListView::initItem(int index, QQuickItem *item) +{ + QQuickItemView::initItem(index, item); + QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>( + qmlAttachedPropertiesObject<QQuickListView>(item)); + if (attached) + attached->setView(this); +} + /*! \qmlmethod QtQuick2::ListView::incrementCurrentIndex() |