aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2019-10-14 15:06:17 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2019-11-14 11:19:26 +0100
commit35fdf3a7b77a79806d0b5d9632b5066e3618adf5 (patch)
tree34dff9cf397da2da7ac71cff82b30b7b6675e546 /tests
parent1619b7d207f7a84810e4790766ac33a3ac9aaa1a (diff)
QQmlTableInstanceModel: always emit index changed when an item is reused
When reusing a delegate item, it can sometimes happen that the item ends up being reused at the same location in the table as it had before it was pooled. And in that case, we don't emit changes to index, row and column since they technically didn't change. The problem is that the model might have changed in-between, e.g if a row has been removed. And in that case, row and column will, even when unchanged, point to other parts of the model. So all bindings needs to be reevaluated to ensure that the values they use are refreshed. This patch will therefore ensure that we always emit changes to the mentioned properties when an item is reused, regardless if they change or not. Fixes: QTBUG-79209 Change-Id: Icec201a43a30b9f677303fbf652baf6487621deb Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/quick/qquicktableview/data/plaintableview.qml1
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h13
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp36
3 files changed, 50 insertions, 0 deletions
diff --git a/tests/auto/quick/qquicktableview/data/plaintableview.qml b/tests/auto/quick/qquicktableview/data/plaintableview.qml
index 90271eda71..33db6f6d02 100644
--- a/tests/auto/quick/qquicktableview/data/plaintableview.qml
+++ b/tests/auto/quick/qquicktableview/data/plaintableview.qml
@@ -70,6 +70,7 @@ Item {
color: "lightgray"
border.width: 1
+ property string modelDataFromIndex: tableView.model.dataFromSerializedIndex(index)
property string modelDataBinding: modelData
Text {
diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h
index 50f434019e..0243158bda 100644
--- a/tests/auto/quick/qquicktableview/testmodel.h
+++ b/tests/auto/quick/qquicktableview/testmodel.h
@@ -63,6 +63,13 @@ public:
return QStringLiteral("%1").arg(index.row());
}
+ Q_INVOKABLE QVariant dataFromSerializedIndex(int index) const
+ {
+ if (modelData.contains(index))
+ return modelData.value(index);
+ return QString();
+ }
+
QHash<int, QByteArray> roleNames() const override
{
return { {Qt::DisplayRole, "display"} };
@@ -102,6 +109,12 @@ public:
beginRemoveRows(parent, row, row + count - 1);
m_rows -= count;
+ for (int c = 0; c < m_columns; ++c) {
+ for (int r = 0; r < count; ++r) {
+ const int serializedIndex = (row + r) + (c * m_rows);
+ modelData.remove(serializedIndex);
+ }
+ }
endRemoveRows();
return true;
}
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 1b6ecc0b71..0117267429 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -160,6 +160,7 @@ private slots:
void checkContextPropertiesQQmlListProperyModel_data();
void checkContextPropertiesQQmlListProperyModel();
void checkRowAndColumnChangedButNotIndex();
+ void checkThatWeAlwaysEmitChangedUponItemReused();
void checkChangingModelFromDelegate();
void checkRebuildViewportOnly();
void useDelegateChooserWithoutDefault();
@@ -2083,6 +2084,41 @@ void tst_QQuickTableView::checkRowAndColumnChangedButNotIndex()
QCOMPARE(contextColumn, 1);
}
+void tst_QQuickTableView::checkThatWeAlwaysEmitChangedUponItemReused()
+{
+ // Check that we always emit changes to index when we reuse an item, even
+ // if it doesn't change. This is needed since the model can have changed
+ // row or column count while the item was in the pool, which means that
+ // any data referred to by the index property inside the delegate
+ // will change too. So we need to refresh any bindings to index.
+ // QTBUG-79209
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ TestModel model(1, 1);
+ tableView->setModel(QVariant::fromValue(&model));
+ model.setModelData(QPoint(0, 0), QSize(1, 1), "old value");
+
+ WAIT_UNTIL_POLISHED;
+
+ const auto reuseItem = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item;
+ const auto context = qmlContext(reuseItem.data());
+
+ // Remove the cell/row that has "old value" as model data, and
+ // add a new one right after. The new cell will have the same
+ // index, but with no model data assigned.
+ // This change will not be detected by items in the pool. But since
+ // we emit indexChanged when the item is reused, it will be updated then.
+ model.removeRow(0);
+ model.insertRow(0);
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(context->contextProperty("index").toInt(), 0);
+ QCOMPARE(context->contextProperty("row").toInt(), 0);
+ QCOMPARE(context->contextProperty("column").toInt(), 0);
+ QCOMPARE(context->contextProperty("modelDataFromIndex").toString(), "");
+}
+
void tst_QQuickTableView::checkChangingModelFromDelegate()
{
// Check that we don't restart a rebuild of the table