aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2012-01-18 16:21:50 +1000
committerQt by Nokia <qt-info@nokia.com>2012-01-20 00:30:09 +0100
commitd9fd9ff55d4d8717cb35b7af39f9f5f39f9a3448 (patch)
treeff2f7725482a36506c1b5a34a7a69ff79ec10c67
parentb1da5cb07922e786bd3223317651284b73159e82 (diff)
Fix lockup in views due to endless polish loop.
It was possible to cause an endless polish loop in some rare cases. Eliminate all calls to polish() within existing polish() code paths. Cleanup delegate creation and cancelling in the cacheBuffer area. Adjust first item position correctly when inserting/removing before visibleItems list. Change-Id: I508a2e6de8cb09d904466cbf5fb6b5dfd1e89c49 Reviewed-by: Bea Lam <bea.lam@nokia.com>
-rw-r--r--src/quick/items/qquickgridview.cpp53
-rw-r--r--src/quick/items/qquickitemview.cpp81
-rw-r--r--src/quick/items/qquickitemview_p_p.h18
-rw-r--r--src/quick/items/qquicklistview.cpp48
-rw-r--r--src/quick/items/qquickvisualdatamodel.cpp4
-rw-r--r--tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp64
-rw-r--r--tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp13
7 files changed, 157 insertions, 124 deletions
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index ef79a4de42..8cc9b4248d 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE
#define QML_FLICK_SNAPONETHRESHOLD 30
#endif
+//#define DEBUG_DELEGATE_LIFECYCLE
+
//----------------------------------------------------------------------------
class FxGridItemSG : public FxViewItem
@@ -172,7 +174,7 @@ public:
virtual FxViewItem *newViewItem(int index, QQuickItem *item);
virtual void repositionPackageItemAt(QQuickItem *item, int index);
virtual void resetFirstItemPosition(qreal pos = 0.0);
- virtual void adjustFirstItem(qreal forwards, qreal backwards);
+ virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible);
virtual void createHighlight();
virtual void updateHighlight();
@@ -442,7 +444,9 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
bool changed = false;
while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
-// qDebug() << "refill: append item" << modelIndex << colPos << rowPos;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: append item" << modelIndex << colPos << rowPos;
+#endif
if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex, doBuffer))))
break;
item->setPosition(colPos, rowPos);
@@ -457,6 +461,9 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
changed = true;
}
+ if (doBuffer && requestedIndex != -1) // already waiting for an item
+ return changed;
+
// Find first column
if (visibleItems.count()) {
FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
@@ -473,7 +480,9 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
// Prepend
colPos = colNum * colSize();
while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
-// qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
+#endif
if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1, doBuffer))))
break;
--visibleIndex;
@@ -501,7 +510,9 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
&& item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
if (item->attached->delayRemove())
break;
-// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
+#endif
if (item->index != -1)
visibleIndex++;
visibleItems.removeFirst();
@@ -513,7 +524,9 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
&& item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
if (item->attached->delayRemove())
break;
-// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+#endif
visibleItems.removeLast();
releaseItem(item);
changed = true;
@@ -590,12 +603,15 @@ void QQuickGridViewPrivate::resetFirstItemPosition(qreal pos)
item->setPosition(0, pos);
}
-void QQuickGridViewPrivate::adjustFirstItem(qreal forwards, qreal backwards)
+void QQuickGridViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible)
{
if (!visibleItems.count())
return;
- int moveCount = (forwards / rowSize()) - (backwards / rowSize());
+ int moveCount = (forwards - backwards) / rowSize();
+
+ if (changeBeforeVisible)
+ moveCount += (changeBeforeVisible%columns) - (columns - 1);
FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.first());
gridItem->setPosition(gridItem->colPos(), gridItem->rowPos() + ((moveCount / columns) * rowSize()));
@@ -1419,7 +1435,7 @@ void QQuickGridView::setCellWidth(qreal cellWidth)
d->updateViewport();
emit cellWidthChanged();
d->forceLayout = true;
- d->layout();
+ polish();
}
}
@@ -1437,7 +1453,7 @@ void QQuickGridView::setCellHeight(qreal cellHeight)
d->updateViewport();
emit cellHeightChanged();
d->forceLayout = true;
- d->layout();
+ polish();
}
}
/*!
@@ -1521,14 +1537,6 @@ void QQuickGridView::viewportMoved()
return;
d->inViewportMoved = true;
- // Set visibility of items to eliminate cost of items outside the visible area.
- qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
- qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxGridItemSG *item = static_cast<FxGridItemSG*>(d->visibleItems.at(i));
- item->item->setVisible(item->rowPos() + d->rowSize() >= from && item->rowPos() <= to);
- }
-
if (yflick())
d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferBefore : QQuickItemViewPrivate::BufferAfter;
else if (d->isRightToLeftTopToBottom())
@@ -1537,6 +1545,15 @@ void QQuickGridView::viewportMoved()
d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferBefore : QQuickItemViewPrivate::BufferAfter;
d->refill();
+
+ // Set visibility of items to eliminate cost of items outside the visible area.
+ qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
+ qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(d->visibleItems.at(i));
+ item->item->setVisible(item->rowPos() + d->rowSize() >= from && item->rowPos() <= to);
+ }
+
if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
d->moveReason = QQuickGridViewPrivate::Mouse;
if (d->moveReason != QQuickGridViewPrivate::SetIndex) {
@@ -1817,7 +1834,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
while (i >= 0) {
if (rowPos > from && insertionIdx < visibleIndex) {
// item won't be visible, just note the size for repositioning
- insertResult->sizeChangesBeforeVisiblePos += rowSize();
+ insertResult->changeBeforeVisible++;
} else {
// item is before first visible e.g. in cache buffer
FxViewItem *item = 0;
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 8ff8b8860c..3341402acd 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -775,7 +775,7 @@ void QQuickItemView::destroyRemoved()
// Correct the positioning of the items
d->updateSections();
d->forceLayout = true;
- d->layout();
+ polish();
}
void QQuickItemView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset)
@@ -1114,7 +1114,7 @@ QQuickItemViewPrivate::QQuickItemViewPrivate()
, highlightMoveDuration(150)
, headerComponent(0), header(0), footerComponent(0), footer(0)
, minExtent(0), maxExtent(0)
- , ownModel(false), wrap(false), deferredRelease(false)
+ , ownModel(false), wrap(false)
, inApplyModelChanges(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
, fillCacheBuffer(false), inRequest(false), requestedAsync(false)
@@ -1301,7 +1301,7 @@ void QQuickItemViewPrivate::refill()
refill(position(), position()+s);
}
-void QQuickItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+void QQuickItemViewPrivate::refill(qreal from, qreal to)
{
Q_Q(QQuickItemView);
if (!isValid() || !q->isComponentComplete())
@@ -1315,35 +1315,22 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
qreal bufferTo = to + buffer;
qreal fillFrom = from;
qreal fillTo = to;
- if (doBuffer && (bufferMode & BufferAfter))
- fillTo = bufferTo;
- if (doBuffer && (bufferMode & BufferBefore))
- fillFrom = bufferFrom;
-
- // Item creation and release is staggered in order to avoid
- // creating/releasing multiple items in one frame
- // while flicking (as much as possible).
- bool changed = addVisibleItems(fillFrom, fillTo, doBuffer);
+ bool added = addVisibleItems(fillFrom, fillTo, false);
+ bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
- if (!changed || deferredRelease) { // avoid destroying items in the same frame that we create
- if (removeNonVisibleItems(bufferFrom, bufferTo))
- changed = true;
- deferredRelease = false;
- } else {
- deferredRelease = true;
+ if (buffer && bufferMode != NoBuffer) {
+ if (bufferMode & BufferAfter)
+ fillTo = bufferTo;
+ if (bufferMode & BufferBefore)
+ fillFrom = bufferFrom;
+ added |= addVisibleItems(fillFrom, fillTo, true);
}
- if (changed) {
+ if (added || removed) {
markExtentsDirty();
+ updateBeginningEnd();
visibleItemsChanged();
- } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
- refill(from, to, true);
- }
-
- if (!q->isMoving() && changed) {
- fillCacheBuffer = true;
- q->polish();
}
if (prevCount != itemCount)
@@ -1393,8 +1380,10 @@ void QQuickItemViewPrivate::layout()
}
if (!applyModelChanges() && !forceLayout) {
- if (fillCacheBuffer)
+ if (fillCacheBuffer) {
+ fillCacheBuffer = false;
refill();
+ }
return;
}
forceLayout = false;
@@ -1459,7 +1448,7 @@ bool QQuickItemViewPrivate::applyModelChanges()
// set positions correctly for the next insertion
if (!insertions.isEmpty()) {
- repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, insertionResult, removalResult);
+ repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
layoutVisibleItems(removals.first().index);
}
}
@@ -1476,7 +1465,7 @@ bool QQuickItemViewPrivate::applyModelChanges()
// set positions correctly for the next insertion
if (i < insertions.count() - 1) {
- repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, insertionResult, removalResult);
+ repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
layoutVisibleItems(insertions[i].index);
}
@@ -1487,7 +1476,7 @@ bool QQuickItemViewPrivate::applyModelChanges()
// reposition visibleItems.first() correctly so that the content y doesn't jump
if (removedCount != prevVisibleItemsCount)
- repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, insertionResult, removalResult);
+ 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();
@@ -1567,27 +1556,31 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remo
}
}
}
+
+ if (removal.index + removal.count < visibleIndex)
+ removeResult->changeBeforeVisible -= removal.count;
+
return visibleAffected;
}
void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
qreal prevVisibleItemsFirstPos,
FxViewItem *prevFirstVisible,
- const ChangeResult &insertionResult,
- const ChangeResult &removalResult)
+ ChangeResult *insertionResult,
+ ChangeResult *removalResult)
{
- const QDeclarativeNullableValue<qreal> prevViewPos = insertionResult.visiblePos;
+ 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)
+ 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)
+ if (!insertionResult->changedFirstItem)
resetFirstItemPosition(prevVisibleItemsFirstPos);
} else if (prevViewPos.isValid()) {
@@ -1596,14 +1589,16 @@ void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirs
// shift visibleItems.first() relative to the number of added/removed items
if (visibleItems.first()->position() > prevViewPos) {
- moveForwardsBy = insertionResult.sizeChangesAfterVisiblePos;
- moveBackwardsBy = removalResult.sizeChangesAfterVisiblePos;
+ moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
+ moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
} else if (visibleItems.first()->position() < prevViewPos) {
- moveForwardsBy = removalResult.sizeChangesBeforeVisiblePos;
- moveBackwardsBy = insertionResult.sizeChangesBeforeVisiblePos;
+ moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
+ moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
}
- adjustFirstItem(moveForwardsBy, moveBackwardsBy);
+ adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->changeBeforeVisible + removalResult->changeBeforeVisible);
}
+ insertionResult->reset();
+ removalResult->reset();
}
}
@@ -1619,6 +1614,8 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
return 0;
if (requestedIndex != -1 && requestedIndex != modelIndex) {
+ if (requestedItem && requestedItem->item)
+ requestedItem->item->setParentItem(0);
delete requestedItem;
requestedItem = 0;
}
@@ -1631,7 +1628,6 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
item->setParentItem(q->contentItem());
QDeclarative_setParent_noEvent(item, q->contentItem());
requestedIndex = -1;
- fillCacheBuffer = false;
FxViewItem *viewItem = requestedItem;
if (!viewItem)
viewItem = newViewItem(modelIndex, item); // already in cache, so viewItem not initialized in initItem()
@@ -1665,9 +1661,6 @@ void QQuickItemView::createdItem(int index, QQuickItem *item)
if (index == d->currentIndex)
d->updateCurrent(index);
d->refill();
- } else {
- d->fillCacheBuffer = true;
- polish();
}
}
}
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index a2dd963dd2..52463afaaa 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -104,9 +104,18 @@ public:
qreal sizeChangesBeforeVisiblePos;
qreal sizeChangesAfterVisiblePos;
bool changedFirstItem;
+ int changeBeforeVisible;
ChangeResult(const QDeclarativeNullableValue<qreal> &p)
- : visiblePos(p), sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0), changedFirstItem(false) {}
+ : visiblePos(p), sizeChangesBeforeVisiblePos(0), sizeChangesAfterVisiblePos(0),
+ changedFirstItem(false), changeBeforeVisible(0) {}
+
+ void reset() {
+ sizeChangesBeforeVisiblePos = 0.0;
+ sizeChangesAfterVisiblePos = 0.0;
+ changedFirstItem = false;
+ changeBeforeVisible = 0;
+ }
};
enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
@@ -130,7 +139,7 @@ public:
void regenerate();
void layout();
void refill();
- void refill(qreal from, qreal to, bool doBuffer = false);
+ void refill(qreal from, qreal to);
void mirrorChange();
FxViewItem *createItem(int modelIndex, bool asynchronous = false);
@@ -149,7 +158,7 @@ public:
bool applyModelChanges();
bool applyRemovalChange(const QDeclarativeChangeSet::Remove &removal, ChangeResult *changeResult, int *removedCount);
void repositionFirstItem(FxViewItem *prevVisibleItemsFirst, qreal prevVisibleItemsFirstPos,
- FxViewItem *prevFirstVisible, const ChangeResult &insertionResult, const ChangeResult &removalResult);
+ FxViewItem *prevFirstVisible, ChangeResult *insertionResult, ChangeResult *removalResult);
void checkVisible() const;
@@ -197,7 +206,6 @@ public:
bool ownModel : 1;
bool wrap : 1;
- bool deferredRelease : 1;
bool inApplyModelChanges : 1;
bool inViewportMoved : 1;
bool forceLayout : 1;
@@ -240,7 +248,7 @@ protected:
virtual FxViewItem *newViewItem(int index, QQuickItem *item) = 0;
virtual void repositionPackageItemAt(QQuickItem *item, int index) = 0;
virtual void resetFirstItemPosition(qreal pos = 0.0) = 0;
- virtual void adjustFirstItem(qreal forwards, qreal backwards) = 0;
+ virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) = 0;
virtual void layoutVisibleItems(int fromModelIndex = 0) = 0;
virtual void changedVisibleIndex(int newIndex) = 0;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index f0ced5fc71..62155272c4 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE
#define QML_FLICK_SNAPONETHRESHOLD 30
#endif
+//#define DEBUG_DELEGATE_LIFECYCLE
+
class FxListItemSG;
class QQuickListViewPrivate : public QQuickItemViewPrivate
@@ -94,7 +96,7 @@ public:
virtual void releaseItem(FxViewItem *item);
virtual void repositionPackageItemAt(QQuickItem *item, int index);
virtual void resetFirstItemPosition(qreal pos = 0.0);
- virtual void adjustFirstItem(qreal forwards, qreal backwards);
+ virtual void adjustFirstItem(qreal forwards, qreal backwards, int);
virtual void createHighlight();
virtual void updateHighlight();
@@ -601,7 +603,9 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
FxListItemSG *item = 0;
qreal pos = itemEnd;
while (modelIndex < model->count() && pos <= fillTo) {
-// qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+#endif
if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
break;
item->setPosition(pos);
@@ -611,8 +615,14 @@ bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool d
++modelIndex;
changed = true;
}
+
+ if (doBuffer && requestedIndex != -1) // already waiting for an item
+ return changed;
+
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
-// qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+#endif
if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer))))
break;
--visibleIndex;
@@ -641,8 +651,9 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
if (item->attached->delayRemove())
break;
if (item->size() > 0) {
-// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
-
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
+#endif
// remove this item and all zero-sized items before it
while (item) {
if (item->index != -1)
@@ -662,7 +673,9 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
if (item->attached->delayRemove())
break;
-// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position();
+#ifdef DEBUG_DELEGATE_LIFECYCLE
+ qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position();
+#endif
visibleItems.removeLast();
releaseItem(item);
changed = true;
@@ -741,7 +754,7 @@ void QQuickListViewPrivate::resetFirstItemPosition(qreal pos)
item->setPosition(pos);
}
-void QQuickListViewPrivate::adjustFirstItem(qreal forwards, qreal backwards)
+void QQuickListViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int)
{
if (!visibleItems.count())
return;
@@ -1822,7 +1835,7 @@ void QQuickListView::setSpacing(qreal spacing)
if (spacing != d->spacing) {
d->spacing = spacing;
d->forceLayout = true;
- d->layout();
+ polish();
emit spacingChanged();
}
}
@@ -2188,14 +2201,6 @@ void QQuickListView::viewportMoved()
return;
d->inViewportMoved = true;
- // Set visibility of items to eliminate cost of items outside the visible area.
- qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
- qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
- item->item->setVisible(item->endPosition() >= from && item->position() <= to);
- }
-
if (yflick())
d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
else if (d->isRightToLeft())
@@ -2204,6 +2209,15 @@ void QQuickListView::viewportMoved()
d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
d->refill();
+
+ // Set visibility of items to eliminate cost of items outside the visible area.
+ qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
+ qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
+ item->item->setVisible(item->endPosition() >= from && item->position() <= to);
+ }
+
if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
d->moveReason = QQuickListViewPrivate::Mouse;
if (d->moveReason != QQuickListViewPrivate::SetIndex) {
@@ -2365,7 +2379,7 @@ void QQuickListView::updateSections()
d->updateSections();
if (d->itemCount) {
d->forceLayout = true;
- d->layout();
+ polish();
}
}
}
diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp
index 3de1e91f7f..d52aec0433 100644
--- a/src/quick/items/qquickvisualdatamodel.cpp
+++ b/src/quick/items/qquickvisualdatamodel.cpp
@@ -425,6 +425,10 @@ QQuickVisualDataModel::ReleaseFlags QQuickVisualDataModelPrivate::release(QObjec
if (QQuickItem *item = qobject_cast<QQuickItem *>(object))
emitDestroyingItem(item);
cacheItem->object = 0;
+ if (cacheItem->incubationTask) {
+ releaseIncubator(cacheItem->incubationTask);
+ cacheItem->incubationTask = 0;
+ }
stat |= QQuickVisualModel::Destroyed;
} else {
stat |= QQuickVisualDataModel::Referenced;
diff --git a/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp b/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp
index 132fa5fad3..15abe325fa 100644
--- a/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp
@@ -467,7 +467,7 @@ void tst_QQuickGridView::inserted_more()
// check visibleItems.first() is in correct position
QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item0);
- QCOMPARE(item0->y(), itemsOffsetAfterMove);
+ QCOMPARE(item0->y(), 0.0);
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
int firstVisibleIndex = -1;
@@ -840,6 +840,7 @@ void tst_QQuickGridView::removed_more()
QFETCH(int, removeIndex);
QFETCH(int, removeCount);
QFETCH(qreal, itemsOffsetAfterMove);
+ QFETCH(QString, firstVisible);
QQuickText *name;
QQuickText *number;
@@ -868,22 +869,20 @@ void tst_QQuickGridView::removed_more()
model.removeItems(removeIndex, removeCount);
QTRY_COMPARE(gridview->property("count").toInt(), model.count());
- // check visibleItems.first() is in correct position
- QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
-// qApp->exec();
- QVERIFY(item0);
- QCOMPARE(item0->y(), itemsOffsetAfterMove);
-
+ QString firstName;
int firstVisibleIndex = -1;
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
for (int i=0; i<items.count(); i++) {
if (items[i]->y() >= contentY) {
QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
firstVisibleIndex = e.evaluate().toInt();
+ QDeclarativeExpression en(qmlContext(items[i]), items[i], "name");
+ firstName = en.evaluate().toString();
break;
}
}
QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
+ QCOMPARE(firstName, firstVisible);
// Confirm items positioned correctly and indexes correct
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
@@ -911,21 +910,27 @@ void tst_QQuickGridView::removed_more_data()
QTest::addColumn<int>("removeIndex");
QTest::addColumn<int>("removeCount");
QTest::addColumn<qreal>("itemsOffsetAfterMove");
+ QTest::addColumn<QString>("firstVisible");
QTest::newRow("remove 1, before visible items")
<< 120.0 // show 6-23
<< 3 << 1
- << 0.0;
+ << 0.0 << "Item7";
QTest::newRow("remove multiple, all before visible items")
<< 120.0
<< 1 << 3
- << 60.0; // removed top row, slide down by 1 row
+ << 60.0 << "Item6"; // removed top row, slide down by 1 row
QTest::newRow("remove multiple, all before visible items, remove item 0")
<< 120.0
<< 0 << 4
- << 60.0; // removed top row, slide down by 1 row
+ << 60.0 << "Item7"; // removed top row, slide down by 1 row
+
+ QTest::newRow("remove multiple rows, all before visible items")
+ << 240.0 // show 12-29
+ << 1 << 7
+ << 120.0 << "Item13";
// remove 3,4,5 before the visible pos, first row moves down to just before the visible pos,
@@ -933,80 +938,80 @@ void tst_QQuickGridView::removed_more_data()
QTest::newRow("remove multiple, mix of items from before and within visible items")
<< 120.0
<< 3 << 5
- << 60.0; // adjust for the 1 row removed before the visible
+ << 60.0 << "Item8"; // adjust for the 1 row removed before the visible
QTest::newRow("remove multiple, mix of items from before and within visible items, remove item 0")
<< 120.0
<< 0 << 8
- << 60.0 * 2; // adjust for the 2 rows removed before the visible
+ << 60.0 * 2 << "Item8"; // adjust for the 2 rows removed before the visible
QTest::newRow("remove 1, from start of visible, content at start")
<< 0.0
<< 0 << 1
- << 0.0;
+ << 0.0 << "Item1";
QTest::newRow("remove multiple, from start of visible, content at start")
<< 0.0
<< 0 << 3
- << 0.0;
+ << 0.0 << "Item3";
QTest::newRow("remove 1, from start of visible, content not at start")
<< 120.0 // show 6-23
<< 4 << 1
- << 0.0;
+ << 0.0 << "Item7";
QTest::newRow("remove multiple, from start of visible, content not at start")
<< 120.0 // show 6-23
<< 4 << 3
- << 0.0;
+ << 0.0 << "Item9";
QTest::newRow("remove 1, from middle of visible, content at start")
<< 0.0
<< 10 << 1
- << 0.0;
+ << 0.0 << "Item0";
QTest::newRow("remove multiple, from middle of visible, content at start")
<< 0.0
<< 10 << 5
- << 0.0;
+ << 0.0 << "Item0";
QTest::newRow("remove 1, from middle of visible, content not at start")
<< 120.0 // show 6-23
<< 10 << 1
- << 0.0;
+ << 0.0 << "Item6";
QTest::newRow("remove multiple, from middle of visible, content not at start")
<< 120.0 // show 6-23
<< 10 << 5
- << 0.0;
+ << 0.0 << "Item6";
QTest::newRow("remove 1, after visible, content at start")
<< 0.0
<< 16 << 1
- << 0.0;
+ << 0.0 << "Item0";
QTest::newRow("remove multiple, after visible, content at start")
<< 0.0
<< 16 << 5
- << 0.0;
+ << 0.0 << "Item0";
QTest::newRow("remove 1, after visible, content not at start")
<< 120.0 // show 6-23
<< 16+4 << 1
- << 0.0;
+ << 0.0 << "Item6";
QTest::newRow("remove multiple, after visible, content not at start")
<< 120.0 // show 6-23
<< 16+4 << 5
- << 0.0;
+ << 0.0 << "Item6";
QTest::newRow("remove multiple, mix of items from within and after visible items")
<< 120.0 // show 6-23
<< 20 << 5
- << 0.0;
+ << 0.0 << "Item6";
}
void tst_QQuickGridView::addOrRemoveBeforeVisible()
@@ -1092,7 +1097,7 @@ void tst_QQuickGridView::addOrRemoveBeforeVisible_data()
QTest::addColumn<qreal>("newTopContentY");
QTest::newRow("add") << true << -60.0;
- QTest::newRow("remove") << false << 0.0;
+ QTest::newRow("remove") << false << -60.0;
}
void tst_QQuickGridView::clear()
@@ -1135,11 +1140,6 @@ void tst_QQuickGridView::clear()
void tst_QQuickGridView::moved()
{
- if (QTest::currentDataTag() == QLatin1String("move 1 forwards, from non-visible -> visible")
- || QTest::currentDataTag() == QLatin1String("move 1 forwards, from non-visible -> visible (move first item)")) {
- QSKIP("QTBUG-23455");
- }
-
QFETCH(qreal, contentY);
QFETCH(int, from);
QFETCH(int, to);
@@ -1223,13 +1223,11 @@ void tst_QQuickGridView::moved_data()
<< 1 << 8 << 1
<< 0.0;
- // skipped QTBUG-23455
QTest::newRow("move 1 forwards, from non-visible -> visible")
<< 120.0 // show 6-23
<< 1 << 23 << 1
<< 0.0;
- // skipped QTBUG-23455
QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
<< 120.0 // // show 6-23
<< 0 << 6 << 1
diff --git a/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp b/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp
index 1953cf7e73..bb168e4212 100644
--- a/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp
@@ -1961,8 +1961,8 @@ void tst_QQuickListView::spacing()
QTRY_VERIFY(listview->spacing() == 10);
// Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() == 11);
+ for (int i = 0; i < 11; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
@@ -1972,8 +1972,8 @@ void tst_QQuickListView::spacing()
listview->setSpacing(0);
// Confirm items positioned correctly
- itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
+ QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() >= 16);
+ for (int i = 0; i < 16; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
@@ -2264,7 +2264,7 @@ void tst_QQuickListView::sectionsPositioning()
model.modifyItem(2, "Three", "aaa");
model.modifyItem(3, "Four", "aaa");
model.modifyItem(4, "Five", "aaa");
- QTest::qWait(300);
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
QTRY_COMPARE(listview->currentSection(), QString("aaa"));
@@ -2275,8 +2275,7 @@ void tst_QQuickListView::sectionsPositioning()
QTRY_COMPARE(item->y(), qreal(i*20*6));
}
- topItem = findVisibleChild(contentItem, "sect_aaa"); // section header
- QVERIFY(topItem);
+ QTRY_VERIFY(topItem = findVisibleChild(contentItem, "sect_aaa")); // section header
QCOMPARE(topItem->y(), 10.);
// remove section boundary