aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickgridview.cpp16
-rw-r--r--src/quick/items/qquickitemsmodule.cpp3
-rw-r--r--src/quick/items/qquickitemview.cpp13
-rw-r--r--src/quick/items/qquickitemview_p.h1
-rw-r--r--src/quick/items/qquicklistview.cpp15
-rw-r--r--tests/auto/qmltest/listview/tst_listview.qml3
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp37
-rw-r--r--tests/auto/quick/qquicklistview/data/delayedChanges.qml39
-rw-r--r--tests/auto/quick/qquicklistview/data/emptymodel.qml4
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp106
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp7
11 files changed, 198 insertions, 46 deletions
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index e40d21b498..f4e34da318 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -2564,6 +2564,22 @@ bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) co
\b Note: methods should only be called after the Component has completed.
*/
+
+/*!
+ \qmlmethod QtQuick2::GridView::forceLayout()
+
+ Responding to changes in the model is usually batched to happen only once
+ per frame. This means that inside script blocks it is possible for the
+ underlying model to have changed, but the GridView has not caught up yet.
+
+ This method forces the GridView to immediately respond to any outstanding
+ changes in the model.
+
+ \since 5.1
+
+ \b Note: methods should only be called after the Component has completed.
+*/
+
QQuickGridViewAttached *QQuickGridView::qmlAttachedProperties(QObject *obj)
{
return new QQuickGridViewAttached(obj);
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 741583a95d..f5bcf3596f 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -230,6 +230,9 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickItem, 1>(uri, 2, 1,"Item");
qmlRegisterType<QQuickGrid, 1>(uri, 2, 1, "Grid");
+ qmlRegisterUncreatableType<QQuickItemView, 1>(uri, 2, 1, "ItemView", QQuickItemView::tr("ItemView is an abstract base class"));
+ qmlRegisterType<QQuickListView, 1>(uri, 2, 1, "ListView");
+ qmlRegisterType<QQuickGridView, 1>(uri, 2, 1, "GridView");
qmlRegisterType<QQuickTextEdit, 1>(uri, 2, 1, "TextEdit");
}
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 03e16f2ebf..d774091ef5 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -249,7 +249,6 @@ QQuickItemView::~QQuickItemView()
QQuickItem *QQuickItemView::currentItem() const
{
Q_D(const QQuickItemView);
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->currentItem ? d->currentItem->item : 0;
}
@@ -379,14 +378,12 @@ int QQuickItemView::count() const
Q_D(const QQuickItemView);
if (!d->model)
return 0;
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->model->count();
}
int QQuickItemView::currentIndex() const
{
Q_D(const QQuickItemView);
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->currentIndex;
}
@@ -496,7 +493,6 @@ QQmlComponent *QQuickItemView::header() const
QQuickItem *QQuickItemView::headerItem() const
{
Q_D(const QQuickItemView);
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->header ? d->header->item : 0;
}
@@ -532,7 +528,6 @@ QQmlComponent *QQuickItemView::footer() const
QQuickItem *QQuickItemView::footerItem() const
{
Q_D(const QQuickItemView);
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->footer ? d->footer->item : 0;
}
@@ -559,7 +554,6 @@ void QQuickItemView::setFooter(QQmlComponent *footerComponent)
QQmlComponent *QQuickItemView::highlight() const
{
Q_D(const QQuickItemView);
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->highlightComponent;
}
@@ -579,7 +573,6 @@ void QQuickItemView::setHighlight(QQmlComponent *highlightComponent)
QQuickItem *QQuickItemView::highlightItem() const
{
Q_D(const QQuickItemView);
- const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
return d->highlight ? d->highlight->item : 0;
}
@@ -965,6 +958,12 @@ QQuickItem *QQuickItemView::itemAt(qreal x, qreal y) const
return 0;
}
+void QQuickItemView::forceLayout()
+{
+ Q_D(QQuickItemView);
+ d->applyPendingChanges();
+}
+
void QQuickItemViewPrivate::applyPendingChanges()
{
Q_Q(QQuickItemView);
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index b0f910680a..d7812bcdad 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -202,6 +202,7 @@ public:
Q_INVOKABLE QQuickItem *itemAt(qreal x, qreal y) const;
Q_INVOKABLE void positionViewAtBeginning();
Q_INVOKABLE void positionViewAtEnd();
+ Q_REVISION(1) Q_INVOKABLE void forceLayout();
virtual void setContentX(qreal pos);
virtual void setContentY(qreal pos);
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 53dc715469..b99fba4e4c 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -3108,6 +3108,21 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
\b Note: methods should only be called after the Component has completed.
*/
+/*!
+ \qmlmethod QtQuick2::ListView::forceLayout()
+
+ Responding to changes in the model is usually batched to happen only once
+ per frame. This means that inside script blocks it is possible for the
+ underlying model to have changed, but the ListView has not caught up yet.
+
+ This method forces the ListView to immediately respond to any outstanding
+ changes in the model.
+
+ \since 5.1
+
+ \b Note: methods should only be called after the Component has completed.
+*/
+
QQuickListViewAttached *QQuickListView::qmlAttachedProperties(QObject *obj)
{
return new QQuickListViewAttached(obj);
diff --git a/tests/auto/qmltest/listview/tst_listview.qml b/tests/auto/qmltest/listview/tst_listview.qml
index cbace624c3..52384fe242 100644
--- a/tests/auto/qmltest/listview/tst_listview.qml
+++ b/tests/auto/qmltest/listview/tst_listview.qml
@@ -38,7 +38,7 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.1
import QtTest 1.0
Item {
@@ -168,6 +168,7 @@ Item {
modelalter.currentIndex = 1;
compare(modelalter.currentItem.text, "AlterModelElement1")
altermodel.clear()
+ modelalter.forceLayout()
tryCompare(modelalter.count, 0)
compare(modelalter.currentItem, null)
}
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index 0c9788ab8e..d0ffba9435 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -532,6 +532,7 @@ void tst_QQuickGridView::inserted_defaultLayout(QQuickGridView::Flow flow,
for (int i=0; i<insertCount; i++)
newData << qMakePair(QString("value %1").arg(i), QString::number(i));
model.insertItems(insertIndex, newData);
+ gridview->forceLayout();
QTRY_COMPARE(gridview->property("count").toInt(), model.count());
// check visibleItems.first() is in correct position
@@ -728,6 +729,7 @@ void tst_QQuickGridView::insertBeforeVisible()
for (int i=0; i<insertCount; i++)
newData << qMakePair(QString("value %1").arg(i), QString::number(i));
model.insertItems(insertIndex, newData);
+ gridview->forceLayout();
QTRY_COMPARE(gridview->property("count").toInt(), model.count());
// now, moving to the top of the view should position the inserted items correctly
@@ -958,6 +960,7 @@ void tst_QQuickGridView::removed_defaultLayout(QQuickGridView::Flow flow,
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
model.removeItems(removeIndex, removeCount);
+ gridview->forceLayout();
QTRY_COMPARE(gridview->property("count").toInt(), model.count());
QString firstName;
@@ -1245,6 +1248,7 @@ void tst_QQuickGridView::clear()
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
model.clear();
+ gridview->forceLayout();
QVERIFY(gridview->count() == 0);
QVERIFY(gridview->currentItem() == 0);
@@ -1254,6 +1258,7 @@ void tst_QQuickGridView::clear()
// confirm sanity when adding an item to cleared list
model.addItem("New", "1");
+ gridview->forceLayout();
QTRY_COMPARE(gridview->count(), 1);
QVERIFY(gridview->currentItem() != 0);
QVERIFY(gridview->currentIndex() == 0);
@@ -3483,6 +3488,7 @@ void tst_QQuickGridView::extents()
QCOMPARE(gridview->originY(), origin_empty.y());
for (int i=0; i<30; i++)
model.addItem("Item" + QString::number(i), "");
+ gridview->forceLayout();
QTRY_COMPARE(gridview->count(), model.count());
QCOMPARE(gridview->originX(), origin_nonEmpty.x());
QCOMPARE(gridview->originY(), origin_nonEmpty.y());
@@ -3942,9 +3948,9 @@ void tst_QQuickGridView::onAdd()
ctxt->setContextProperty("delegateHeight", delegateHeight);
window->setSource(testFileUrl("attachedSignals.qml"));
- QObject *object = window->rootObject();
- object->setProperty("width", window->width());
- object->setProperty("height", window->height());
+ QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
+ gridview->setProperty("width", window->width());
+ gridview->setProperty("height", window->height());
qApp->processEvents();
QList<QPair<QString, QString> > items;
@@ -3952,10 +3958,11 @@ void tst_QQuickGridView::onAdd()
items << qMakePair(QString("value %1").arg(i), QString::number(i));
model.addItems(items);
- QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(window->rootObject())->count());
+ gridview->forceLayout();
+ QTRY_COMPARE(model.count(), gridview->count());
qApp->processEvents();
- QVariantList result = object->property("addedDelegates").toList();
+ QVariantList result = gridview->property("addedDelegates").toList();
QTRY_COMPARE(result.count(), items.count());
for (int i=0; i<items.count(); i++)
QCOMPARE(result[i].toString(), items[i].first);
@@ -3999,11 +4006,12 @@ void tst_QQuickGridView::onRemove()
ctxt->setContextProperty("delegateWidth", delegateWidth);
ctxt->setContextProperty("delegateHeight", delegateHeight);
window->setSource(testFileUrl("attachedSignals.qml"));
- QObject *object = window->rootObject();
+ QQuickGridView *gridview = qobject_cast<QQuickGridView*>(window->rootObject());
model.removeItems(indexToRemove, removeCount);
- QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(window->rootObject())->count());
- QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
+ gridview->forceLayout();
+ QTRY_COMPARE(model.count(), gridview->count());
+ QCOMPARE(gridview->property("removedDelegateCount"), QVariant(removeCount));
releaseView(window);
}
@@ -4151,6 +4159,7 @@ void tst_QQuickGridView::margins()
gridview->setContentX(-400);
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
model.removeItems(0, 4);
+ gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
gridview->setContentX(-240+50);
gridview->returnToBounds();
@@ -4458,6 +4467,7 @@ void tst_QQuickGridView::unaligned()
// removing
model.removeItems(7, 10);
+ gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
for (int i = 0; i < 18; ++i) {
QQuickItem *item = 0;
@@ -4663,6 +4673,7 @@ void tst_QQuickGridView::addTransitions()
// start animation
if (!newData.isEmpty()) {
model.insertItems(insertionIndex, newData);
+ gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
}
@@ -4866,6 +4877,7 @@ void tst_QQuickGridView::moveTransitions()
// start animation
model.moveItems(moveFrom, moveTo, moveCount);
+ gridview->forceLayout();
QTRY_COMPARE(gridview->property("targetTransitionsDone").toInt(), expectedTargetData.count());
QTRY_COMPARE(gridview->property("displaceTransitionsDone").toInt(),
@@ -5114,6 +5126,7 @@ void tst_QQuickGridView::removeTransitions()
// start animation
model.removeItems(removalIndex, removalCount);
+ gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
if (shouldAnimateTargets || expectedDisplacedIndexes.isValid()) {
@@ -5327,6 +5340,7 @@ void tst_QQuickGridView::displacedTransitions()
case ListChange::Polish:
break;
}
+ gridview->forceLayout();
QVariantList resultTargetIndexes = gridview->property("displacedTargetIndexes").toList();
QVariantList resultTargetItems = gridview->property("displacedTargetItems").toList();
@@ -5534,6 +5548,7 @@ void tst_QQuickGridView::multipleTransitions()
for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
targetItems << qMakePair(QString("new item %1").arg(j), QString::number(j));
model.insertItems(changes[i].index, targetItems);
+ gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
if (i == changes.count() - 1) {
QTRY_VERIFY(!gridview->property("runningAddTargets").toBool());
@@ -5545,6 +5560,7 @@ void tst_QQuickGridView::multipleTransitions()
}
case ListChange::Removed:
model.removeItems(changes[i].index, changes[i].count);
+ gridview->forceLayout();
QTRY_COMPARE(model.count(), gridview->count());
if (i == changes.count() - 1) {
QTRY_VERIFY(!gridview->property("runningRemoveTargets").toBool());
@@ -5555,6 +5571,7 @@ void tst_QQuickGridView::multipleTransitions()
break;
case ListChange::Moved:
model.moveItems(changes[i].index, changes[i].to, changes[i].count);
+ gridview->forceLayout();
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
if (i == changes.count() - 1) {
QTRY_VERIFY(!gridview->property("runningMoveTargets").toBool());
@@ -5566,16 +5583,17 @@ void tst_QQuickGridView::multipleTransitions()
case ListChange::SetCurrent:
gridview->setCurrentIndex(changes[i].index);
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ gridview->forceLayout();
break;
case ListChange::SetContentY:
gridview->setContentY(changes[i].pos);
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ gridview->forceLayout();
break;
case ListChange::Polish:
break;
}
}
- QCOMPARE(gridview->count(), model.count());
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
int firstVisibleIndex = -1;
@@ -5586,6 +5604,7 @@ void tst_QQuickGridView::multipleTransitions()
break;
}
}
+ QTRY_COMPARE(gridview->count(), model.count());
QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
// verify all items moved to the correct final positions
diff --git a/tests/auto/quick/qquicklistview/data/delayedChanges.qml b/tests/auto/quick/qquicklistview/data/delayedChanges.qml
new file mode 100644
index 0000000000..590af39c02
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/delayedChanges.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.1
+
+Item {
+ width: 400
+ height: 400
+ function takeTwo()
+ {
+ listView.model.remove(0);
+ listView.model.remove(0);
+ }
+ function takeTwo_sync()
+ {
+ listView.model.remove(0);
+ listView.forceLayout();
+ listView.model.remove(0);
+ listView.forceLayout();
+ }
+
+ ListView {
+ id: listView
+ height: parent.height
+ width: 400
+ model: ListModel {
+ ListElement { name: "A" }
+ ListElement { name: "B" }
+ ListElement { name: "C" }
+ ListElement { name: "D" }
+ ListElement { name: "E" }
+ ListElement { name: "F" }
+ ListElement { name: "G" }
+ ListElement { name: "H" }
+ ListElement { name: "I" }
+ ListElement { name: "J" }
+ }
+ delegate: Text {
+ text: index + listView.count
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/emptymodel.qml b/tests/auto/quick/qquicklistview/data/emptymodel.qml
index 16bcd3f9ae..3feec691cf 100644
--- a/tests/auto/quick/qquicklistview/data/emptymodel.qml
+++ b/tests/auto/quick/qquicklistview/data/emptymodel.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.1
Rectangle {
ListModel {
id: model
@@ -12,11 +12,13 @@ Rectangle {
}
function remove() {
model.remove(0)
+ list.forceLayout()
isCurrentItemNull = list.currentItem === null //check no seg fault
}
function add() {
model.append({name: "hello"})
+ list.forceLayout()
isCurrentItemNull = list.currentItem === null
}
property bool isCurrentItemNull
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index f8c7de6635..bec61eaccb 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -208,10 +208,11 @@ private slots:
void parentBinding();
void defaultHighlightMoveDuration();
void accessEmptyCurrentItem_QTBUG_30227();
+ void delayedChanges_QTBUG_30555();
private:
- template <class T> void items(const QUrl &source, bool forceLayout);
- template <class T> void changed(const QUrl &source, bool forceLayout);
+ template <class T> void items(const QUrl &source);
+ template <class T> void changed(const QUrl &source);
template <class T> void inserted(const QUrl &source);
template <class T> void inserted_more(QQuickItemView::VerticalLayoutDirection verticalLayoutDirection = QQuickItemView::TopToBottom);
template <class T> void removed(const QUrl &source, bool animated);
@@ -329,7 +330,7 @@ void tst_QQuickListView::cleanupTestCase()
}
template <class T>
-void tst_QQuickListView::items(const QUrl &source, bool forceLayout)
+void tst_QQuickListView::items(const QUrl &source)
{
QQuickView *window = createView();
@@ -349,6 +350,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout)
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != 0);
+ listview->forceLayout();
QQuickItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
@@ -359,6 +361,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout)
QTRY_VERIFY(listview->highlightItem() != 0);
QTRY_COMPARE(listview->count(), model.count());
QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
+ listview->forceLayout();
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
// current item should be first item
@@ -398,8 +401,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout)
ctxt->setContextProperty("testModel", &model2);
// Force a layout, necessary if ListView is completed before VisualDataModel.
- if (forceLayout)
- QCOMPARE(listview->property("count").toInt(), 0);
+ listview->forceLayout();
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
QTRY_VERIFY(itemCount == 0);
@@ -413,7 +415,7 @@ void tst_QQuickListView::items(const QUrl &source, bool forceLayout)
template <class T>
-void tst_QQuickListView::changed(const QUrl &source, bool forceLayout)
+void tst_QQuickListView::changed(const QUrl &source)
{
QQuickView *window = createView();
@@ -431,15 +433,15 @@ void tst_QQuickListView::changed(const QUrl &source, bool forceLayout)
window->setSource(source);
qApp->processEvents();
- QQuickFlickable *listview = findItem<QQuickFlickable>(window->rootObject(), "list");
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != 0);
+ listview->forceLayout();
QQuickItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
// Force a layout, necessary if ListView is completed before VisualDataModel.
- if (forceLayout)
- QCOMPARE(listview->property("count").toInt(), model.count());
+ listview->forceLayout();
model.modifyItem(1, "Will", "9876");
QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
@@ -579,22 +581,24 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
QQuickItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
- bool waitForPolish = (contentY != 0);
if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
listview->setVerticalLayoutDirection(verticalLayoutDirection);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
contentY = -listview->height() - contentY;
}
listview->setContentY(contentY);
- if (waitForPolish)
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
QList<QPair<QString, QString> > newData;
for (int i=0; i<insertCount; i++)
newData << qMakePair(QString("value %1").arg(i), QString::number(i));
model.insertItems(insertIndex, newData);
+
+ //Wait for polish (updates list to the model changes)
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
QTRY_COMPARE(listview->property("count").toInt(), model.count());
+
// check visibleItems.first() is in correct position
QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item0);
@@ -1019,17 +1023,17 @@ void tst_QQuickListView::removed_more(const QUrl &source, QQuickItemView::Vertic
QQuickItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
- bool waitForPolish = (contentY != 0);
if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
listview->setVerticalLayoutDirection(verticalLayoutDirection);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
contentY = -listview->height() - contentY;
}
listview->setContentY(contentY);
- if (waitForPolish)
- QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
model.removeItems(removeIndex, removeCount);
+ //Wait for polish (updates list to the model changes)
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
QTRY_COMPARE(listview->property("count").toInt(), model.count());
// check visibleItems.first() is in correct position
@@ -1219,6 +1223,7 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
// confirm sanity when adding an item to cleared list
model.addItem("New", "1");
+ listview->forceLayout();
QTRY_VERIFY(listview->count() == 1);
QVERIFY(listview->currentItem() != 0);
QVERIFY(listview->currentIndex() == 0);
@@ -1945,6 +1950,7 @@ void tst_QQuickListView::sections(const QUrl &source)
// Remove section boundary
model.removeItem(5);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
// New section header created
@@ -1953,6 +1959,7 @@ void tst_QQuickListView::sections(const QUrl &source)
QTRY_COMPARE(item->height(), 40.0);
model.insertItem(3, "New Item", "0");
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
// Section header moved
@@ -1966,6 +1973,7 @@ void tst_QQuickListView::sections(const QUrl &source)
// insert item which will become a section header
model.insertItem(6, "Replace header", "1");
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
item = findItem<QQuickItem>(contentItem, "wrapper", 6);
@@ -2061,6 +2069,7 @@ void tst_QQuickListView::sectionsDelegate()
// remove section boundary
model.removeItem(5);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
for (int i = 0; i < 3; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem,
@@ -2288,6 +2297,7 @@ void tst_QQuickListView::sectionsPositioning()
listview->setContentY(120);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
model.removeItem(5);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
for (int i = 1; i < 3; ++i) {
QQuickItem *item = findVisibleChild(contentItem,
@@ -2485,7 +2495,8 @@ void tst_QQuickListView::currentIndex_delayedItemCreation()
QTRY_VERIFY(contentItem != 0);
QSignalSpy spy(listview, SIGNAL(currentItemChanged()));
- QCOMPARE(listview->currentIndex(), 0);
+ //QCOMPARE(listview->currentIndex(), 0);
+ listview->forceLayout();
QTRY_COMPARE(spy.count(), 1);
releaseView(window);
@@ -2536,6 +2547,7 @@ void tst_QQuickListView::currentIndex()
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));
ctxt->setContextProperty("testModel", &model);
+ listview->forceLayout();
QCOMPARE(listview->currentIndex(), 0);
QCOMPARE(listview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
@@ -2679,6 +2691,7 @@ void tst_QQuickListView::keyNavigation()
QTRY_COMPARE(listview->currentIndex(), i+1);
}
QTest::keyRelease(window, forwardsKey);
+ listview->forceLayout();
QTRY_COMPARE(listview->currentIndex(), model.count()-1);
QTRY_COMPARE(listview->contentX(), contentPosAtLastItem.x());
QTRY_COMPARE(listview->contentY(), contentPosAtLastItem.y());
@@ -2689,6 +2702,7 @@ void tst_QQuickListView::keyNavigation()
QTRY_COMPARE(listview->currentIndex(), i-1);
}
QTest::keyRelease(window, backwardsKey);
+ listview->forceLayout();
QTRY_COMPARE(listview->currentIndex(), 0);
QTRY_COMPARE(listview->contentX(), contentPosAtFirstItem.x());
QTRY_COMPARE(listview->contentY(), contentPosAtFirstItem.y());
@@ -3123,6 +3137,7 @@ void tst_QQuickListView::resetModel()
strings << "four" << "five" << "six" << "seven";
model.setStringList(strings);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.rowCount());
for (int i = 0; i < model.rowCount(); ++i) {
@@ -3470,6 +3485,7 @@ void tst_QQuickListView::header()
QCOMPARE(item->position(), firstDelegatePos);
model.clear();
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
QCOMPARE(header->position(), initialHeaderPos); // header should stay where it is
if (orientation == QQuickListView::Vertical)
@@ -3865,6 +3881,7 @@ void tst_QQuickListView::extents()
QCOMPARE(listview->originY(), origin_empty.y());
for (int i=0; i<30; i++)
model.addItem("Item" + QString::number(i), "");
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
QCOMPARE(listview->originX(), origin_nonEmpty.x());
QCOMPARE(listview->originY(), origin_nonEmpty.y());
@@ -4262,6 +4279,7 @@ void tst_QQuickListView::resizeFirstDelegate()
for (int i = 0; i < 10; i++)
model.addItem("Item" + QString::number(i), "");
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
item = findItem<QQuickItem>(contentItem, "wrapper", 1);
@@ -4461,6 +4479,7 @@ void tst_QQuickListView::indexAt_itemAt()
void tst_QQuickListView::incrementalModel()
{
QQuickView *window = createView();
+ QSKIP("QTBUG-30716");
IncrementalModel model;
QQmlContext *ctxt = window->rootContext();
@@ -4471,14 +4490,17 @@ void tst_QQuickListView::incrementalModel()
QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != 0);
+ listview->forceLayout();
QQuickItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), 20);
listview->positionViewAtIndex(10, QQuickListView::Beginning);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), 25);
delete window;
@@ -4503,18 +4525,19 @@ void tst_QQuickListView::onAdd()
ctxt->setContextProperty("delegateHeight", delegateHeight);
window->setSource(testFileUrl("attachedSignals.qml"));
- QObject *object = window->rootObject();
- object->setProperty("width", window->width());
- object->setProperty("height", window->height());
+ QQuickListView* listview = qobject_cast<QQuickListView*>(window->rootObject());
+ listview->setProperty("width", window->width());
+ listview->setProperty("height", window->height());
qApp->processEvents();
QList<QPair<QString, QString> > items;
for (int i=0; i<itemsToAdd; i++)
items << qMakePair(QString("value %1").arg(i), QString::number(i));
model.addItems(items);
- QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
+ listview->forceLayout();
+ QTRY_COMPARE(listview->property("count").toInt(), model.count());
- QVariantList result = object->property("addedDelegates").toList();
+ QVariantList result = listview->property("addedDelegates").toList();
QCOMPARE(result.count(), items.count());
for (int i=0; i<items.count(); i++)
QCOMPARE(result[i].toString(), items[i].first);
@@ -4557,12 +4580,13 @@ void tst_QQuickListView::onRemove()
ctxt->setContextProperty("delegateHeight", delegateHeight);
window->setSource(testFileUrl("attachedSignals.qml"));
- QObject *object = window->rootObject();
+ QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
model.removeItems(indexToRemove, removeCount);
- QTRY_COMPARE(window->rootObject()->property("count").toInt(), model.count());
+ listview->forceLayout();
+ QTRY_COMPARE(listview->property("count").toInt(), model.count());
- QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
+ QCOMPARE(listview->property("removedDelegateCount"), QVariant(removeCount));
releaseView(window);
}
@@ -4741,6 +4765,7 @@ void tst_QQuickListView::margins()
// and originY is updated
listview->setContentY(100);
model.removeItem(1);
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), model.count());
listview->setContentY(-50);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
@@ -4979,22 +5004,22 @@ void tst_QQuickListView::snapToItem()
void tst_QQuickListView::qAbstractItemModel_package_items()
{
- items<QaimModel>(testFileUrl("listviewtest-package.qml"), true);
+ items<QaimModel>(testFileUrl("listviewtest-package.qml"));
}
void tst_QQuickListView::qAbstractItemModel_items()
{
- items<QaimModel>(testFileUrl("listviewtest.qml"), false);
+ items<QaimModel>(testFileUrl("listviewtest.qml"));
}
void tst_QQuickListView::qAbstractItemModel_package_changed()
{
- changed<QaimModel>(testFileUrl("listviewtest-package.qml"), true);
+ changed<QaimModel>(testFileUrl("listviewtest-package.qml"));
}
void tst_QQuickListView::qAbstractItemModel_changed()
{
- changed<QaimModel>(testFileUrl("listviewtest.qml"), false);
+ changed<QaimModel>(testFileUrl("listviewtest.qml"));
}
void tst_QQuickListView::qAbstractItemModel_package_inserted()
@@ -5555,6 +5580,7 @@ void tst_QQuickListView::populateTransitions()
// clear the model
window->rootContext()->setContextProperty("testModel", QVariant());
+ listview->forceLayout();
QTRY_COMPARE(listview->count(), 0);
QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 0);
listview->setProperty("countPopulateTransitions", 0);
@@ -5683,6 +5709,7 @@ void tst_QQuickListView::addTransitions()
if (!newData.isEmpty()) {
model.insertItems(insertionIndex, newData);
QTRY_COMPARE(model.count(), listview->count());
+ listview->forceLayout();
}
QList<QQuickItem *> targetItems = findItems<QQuickItem>(contentItem, "wrapper", targetIndexes);
@@ -6291,6 +6318,7 @@ void tst_QQuickListView::displacedTransitions()
case ListChange::Polish:
break;
}
+ listview->forceLayout();
QVariantList resultTargetIndexes = listview->property("displacedTargetIndexes").toList();
QVariantList resultTargetItems = listview->property("displacedTargetItems").toList();
@@ -6539,6 +6567,7 @@ void tst_QQuickListView::multipleTransitions()
break;
}
}
+ listview->forceLayout();
QCOMPARE(listview->count(), model.count());
// verify all items moved to the correct final positions
@@ -6822,6 +6851,7 @@ void tst_QQuickListView::accessEmptyCurrentItem_QTBUG_30227()
QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
QTRY_VERIFY(listview != 0);
+ listview->forceLayout();
QMetaObject::invokeMethod(window->rootObject(), "remove");
QVERIFY(window->rootObject()->property("isCurrentItemNull").toBool());
@@ -6830,6 +6860,26 @@ void tst_QQuickListView::accessEmptyCurrentItem_QTBUG_30227()
QVERIFY(!window->rootObject()->property("isCurrentItemNull").toBool());
}
+void tst_QQuickListView::delayedChanges_QTBUG_30555()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("delayedChanges.qml"));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QTRY_VERIFY(listview != 0);
+
+ QCOMPARE(listview->count(), 10);
+
+ //Takes two just like in the bug report
+ QMetaObject::invokeMethod(window->rootObject(), "takeTwo");
+ QTRY_COMPARE(listview->count(), 8);
+
+ QMetaObject::invokeMethod(window->rootObject(), "takeTwo_sync");
+ QCOMPARE(listview->count(), 6);
+
+ delete window;
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index d16bf81d88..d374d71280 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -615,6 +615,7 @@ void tst_qquickvisualdatamodel::childChanged()
vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
QCOMPARE(listview->count(), 1);
+ listview->forceLayout();
QQuickText *name = findItem<QQuickText>(contentItem, "display", 0);
QVERIFY(name);
QCOMPARE(name->text(), QString("Row 2 Child Item"));
@@ -628,6 +629,7 @@ void tst_qquickvisualdatamodel::childChanged()
model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
QCOMPARE(listview->count(), 2);
+ listview->forceLayout();
name = findItem<QQuickText>(contentItem, "display", 1);
QVERIFY(name != 0);
QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
@@ -638,6 +640,8 @@ void tst_qquickvisualdatamodel::childChanged()
vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
QCOMPARE(listview->count(), 3);
+
+ listview->forceLayout();
name = findItem<QQuickText>(contentItem, "display", 0);
QVERIFY(name);
QCOMPARE(name->text(), QString("Row 1 Item"));
@@ -989,6 +993,8 @@ void tst_qquickvisualdatamodel::packagesDestroyed()
QQuickItem *rightContent = rightview->contentItem();
QTRY_VERIFY(rightContent != 0);
+ leftview->forceLayout();
+ rightview->forceLayout();
QCOMPARE(leftview->currentIndex(), 0);
QCOMPARE(rightview->currentIndex(), 0);
@@ -3548,6 +3554,7 @@ void tst_qquickvisualdatamodel::resolve()
evaluate<void>(visualModel, setupExpression);
QCOMPARE(evaluate<int>(listView, "count"), unresolvedCount);
+ listView->forceLayout();
evaluate<void>(visualModel, resolveExpression);
QCOMPARE(evaluate<int>(listView, "count"), inItems ? visualCount : modelCount);