aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickgridview.cpp10
-rw-r--r--src/quick/items/qquickitemview.cpp5
-rw-r--r--src/quick/items/qquicklistview.cpp16
-rw-r--r--tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml47
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp71
-rw-r--r--tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml46
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp71
7 files changed, 258 insertions, 8 deletions
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 3cc0a28b87..e3f216b3a2 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -267,9 +267,13 @@ qreal QQuickGridViewPrivate::originPosition() const
qreal QQuickGridViewPrivate::lastPosition() const
{
qreal pos = 0;
- if (model && model->count()) {
- // get end position of last item
- pos = (rowPosAt(model->count() - 1) + rowSize());
+ if (model && (model->count() || !visibleItems.isEmpty())) {
+ qreal lastRowPos = model->count() ? rowPosAt(model->count() - 1) : 0;
+ if (!visibleItems.isEmpty()) {
+ // If there are items in delayRemove state, they may be after any items linked to the model
+ lastRowPos = qMax(lastRowPos, static_cast<FxGridItemSG*>(visibleItems.last())->rowPos());
+ }
+ pos = lastRowPos + rowSize();
}
return pos;
}
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index ce4d9b6313..af47aa837b 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1344,7 +1344,7 @@ void QQuickItemView::geometryChanged(const QRectF &newGeometry, const QRectF &ol
{
Q_D(QQuickItemView);
d->markExtentsDirty();
- if (isComponentComplete() && d->isValid())
+ if (isComponentComplete() && (d->isValid() || !d->visibleItems.isEmpty()))
d->forceLayoutPolish();
QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
}
@@ -1808,7 +1808,7 @@ void QQuickItemViewPrivate::updateViewport()
{
Q_Q(QQuickItemView);
qreal extra = headerSize() + footerSize();
- qreal contentSize = isValid() ? (endPosition() - startPosition()) : 0.0;
+ qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
if (layoutOrientation() == Qt::Vertical)
q->setContentHeight(contentSize + extra);
else
@@ -1826,6 +1826,7 @@ void QQuickItemViewPrivate::layout()
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartOffset());
+ updateViewport();
if (transitioner)
transitioner->setPopulateTransitionEnabled(false);
inLayout = false;
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index ab8e9a7854..eec36b59c8 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -427,14 +427,24 @@ qreal QQuickListViewPrivate::lastPosition() const
{
qreal pos = 0;
if (!visibleItems.isEmpty()) {
- int invisibleCount = visibleItems.count() - visibleIndex;
+ int invisibleCount = INT_MIN;
+ int delayRemovedCount = 0;
for (int i = visibleItems.count()-1; i >= 0; --i) {
if (visibleItems.at(i)->index != -1) {
- invisibleCount = model->count() - visibleItems.at(i)->index - 1;
+ // Find the invisible count after the last visible item with known index
+ invisibleCount = model->count() - (visibleItems.at(i)->index + 1 + delayRemovedCount);
break;
+ } else if (visibleItems.at(i)->attached->delayRemove()) {
+ ++delayRemovedCount;
}
}
- pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+ if (invisibleCount == INT_MIN) {
+ // All visible items are in delayRemove state
+ invisibleCount = model->count();
+ }
+ pos = (*(--visibleItems.constEnd()))->endPosition();
+ if (invisibleCount > 0)
+ pos += invisibleCount * (averageSize + spacing);
} else if (model && model->count()) {
pos = (model->count() * averageSize + (model->count()-1) * spacing);
}
diff --git a/tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml b/tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml
new file mode 100644
index 0000000000..3f8246bafc
--- /dev/null
+++ b/tests/auto/quick/qquickgridview/data/contentHeightWithDelayRemove.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.1
+
+Item {
+ width: 400
+ height: 600
+ function takeOne()
+ {
+ gridView.model.remove(2)
+ }
+ function takeThree()
+ {
+ gridView.model.remove(4)
+ gridView.model.remove(2)
+ gridView.model.remove(0)
+ }
+ function takeAll()
+ {
+ gridView.model.clear()
+ }
+
+ GridView {
+ id: gridView
+
+ property bool useDelayRemove
+
+ height: parent.height
+ width: 400
+ cellWidth: width/2
+ model: ListModel {
+ ListElement { name: "A" }
+ ListElement { name: "B" }
+ ListElement { name: "C" }
+ ListElement { name: "D" }
+ ListElement { name: "E" }
+ }
+ delegate: Text {
+ id: wrapper
+ height: 100
+ text: index + gridView.count
+ GridView.delayRemove: gridView.useDelayRemove
+ GridView.onRemove: SequentialAnimation {
+ PauseAnimation { duration: wrapper.GridView.delayRemove ? 100 : 0 }
+ PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index f9262fb074..d53ee00b45 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -206,6 +206,9 @@ private slots:
void jsArrayChange();
+ void contentHeightWithDelayRemove_data();
+ void contentHeightWithDelayRemove();
+
private:
QList<int> toIntList(const QVariantList &list);
void matchIndexLists(const QVariantList &indexLists, const QList<int> &expectedIndexes);
@@ -6471,6 +6474,74 @@ void tst_QQuickGridView::jsArrayChange()
QCOMPARE(spy.count(), 1);
}
+void tst_QQuickGridView::contentHeightWithDelayRemove_data()
+{
+ QTest::addColumn<bool>("useDelayRemove");
+ QTest::addColumn<QByteArray>("removeFunc");
+ QTest::addColumn<int>("countDelta");
+ QTest::addColumn<qreal>("contentHeightDelta");
+
+ QTest::newRow("remove without delayRemove")
+ << false
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with delayRemove")
+ << true
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with multiple delayRemove")
+ << true
+ << QByteArray("takeThree")
+ << -3
+ << qreal(-2 * 100.0);
+
+ QTest::newRow("clear with delayRemove")
+ << true
+ << QByteArray("takeAll")
+ << -5
+ << qreal(-3 * 100.0);
+}
+
+void tst_QQuickGridView::contentHeightWithDelayRemove()
+{
+ QFETCH(bool, useDelayRemove);
+ QFETCH(QByteArray, removeFunc);
+ QFETCH(int, countDelta);
+ QFETCH(qreal, contentHeightDelta);
+
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("contentHeightWithDelayRemove.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickGridView *gridview = window->rootObject()->findChild<QQuickGridView*>();
+ QTRY_VERIFY(gridview != 0);
+
+ const int initialCount(gridview->count());
+ const int eventualCount(initialCount + countDelta);
+
+ const qreal initialContentHeight(gridview->contentHeight());
+ const int eventualContentHeight(qRound(initialContentHeight + contentHeightDelta));
+
+ gridview->setProperty("useDelayRemove", useDelayRemove);
+ QMetaObject::invokeMethod(window->rootObject(), removeFunc.constData());
+ QTest::qWait(50);
+ QCOMPARE(gridview->count(), eventualCount);
+
+ if (useDelayRemove) {
+ QCOMPARE(qRound(gridview->contentHeight()), qRound(initialContentHeight));
+ QTRY_COMPARE(qRound(gridview->contentHeight()), eventualContentHeight);
+ } else {
+ QCOMPARE(qRound(gridview->contentHeight()), eventualContentHeight);
+ }
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickGridView)
#include "tst_qquickgridview.moc"
diff --git a/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml b/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml
new file mode 100644
index 0000000000..06011519b2
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml
@@ -0,0 +1,46 @@
+import QtQuick 2.1
+
+Item {
+ width: 400
+ height: 600
+ function takeOne()
+ {
+ listView.model.remove(2)
+ }
+ function takeThree()
+ {
+ listView.model.remove(4)
+ listView.model.remove(2)
+ listView.model.remove(0)
+ }
+ function takeAll()
+ {
+ listView.model.clear()
+ }
+
+ ListView {
+ id: listView
+
+ property bool useDelayRemove
+
+ height: parent.height
+ width: 400
+ model: ListModel {
+ ListElement { name: "A" }
+ ListElement { name: "B" }
+ ListElement { name: "C" }
+ ListElement { name: "D" }
+ ListElement { name: "E" }
+ }
+ delegate: Text {
+ id: wrapper
+ height: 100
+ text: index + listView.count
+ ListView.delayRemove: listView.useDelayRemove
+ ListView.onRemove: SequentialAnimation {
+ PauseAnimation { duration: wrapper.ListView.delayRemove ? 100 : 0 }
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 28025c3090..b25fc5402b 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -242,6 +242,9 @@ private slots:
void jsArrayChange();
void objectModel();
+ void contentHeightWithDelayRemove();
+ void contentHeightWithDelayRemove_data();
+
private:
template <class T> void items(const QUrl &source);
template <class T> void changed(const QUrl &source);
@@ -8063,6 +8066,74 @@ void tst_QQuickListView::objectModel()
delete listview;
}
+void tst_QQuickListView::contentHeightWithDelayRemove_data()
+{
+ QTest::addColumn<bool>("useDelayRemove");
+ QTest::addColumn<QByteArray>("removeFunc");
+ QTest::addColumn<int>("countDelta");
+ QTest::addColumn<qreal>("contentHeightDelta");
+
+ QTest::newRow("remove without delayRemove")
+ << false
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with delayRemove")
+ << true
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with multiple delayRemove")
+ << true
+ << QByteArray("takeThree")
+ << -3
+ << qreal(-3 * 100.0);
+
+ QTest::newRow("clear with delayRemove")
+ << true
+ << QByteArray("takeAll")
+ << -5
+ << qreal(-5 * 100.0);
+}
+
+void tst_QQuickListView::contentHeightWithDelayRemove()
+{
+ QFETCH(bool, useDelayRemove);
+ QFETCH(QByteArray, removeFunc);
+ QFETCH(int, countDelta);
+ QFETCH(qreal, contentHeightDelta);
+
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("contentHeightWithDelayRemove.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QTRY_VERIFY(listview != 0);
+
+ const int initialCount(listview->count());
+ const int eventualCount(initialCount + countDelta);
+
+ const qreal initialContentHeight(listview->contentHeight());
+ const int eventualContentHeight(qRound(initialContentHeight + contentHeightDelta));
+
+ listview->setProperty("useDelayRemove", useDelayRemove);
+ QMetaObject::invokeMethod(window->rootObject(), removeFunc.constData());
+ QTest::qWait(50);
+ QCOMPARE(listview->count(), eventualCount);
+
+ if (useDelayRemove) {
+ QCOMPARE(qRound(listview->contentHeight()), qRound(initialContentHeight));
+ QTRY_COMPARE(qRound(listview->contentHeight()), eventualContentHeight);
+ } else {
+ QCOMPARE(qRound(listview->contentHeight()), eventualContentHeight);
+ }
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"