diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2018-08-01 22:53:17 +0200 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2018-08-02 15:53:58 +0000 |
commit | fe1a259be66835bc937890f3ed62bb2e8496d0f1 (patch) | |
tree | 12453b09306764e679cb45af9de417c38101f572 /tests/auto | |
parent | e997cd013a665505bd2d33a3e4b76e27752bcb39 (diff) |
QQmlTableInstanceModel: handle model data changes more gracefully
Equal to QQmlDelegateModel, we need to listen for changes done to
existing model items, and notify existing delegate items about it.
Otherwise, they will not stay in sync with the model.
By accident, this sort of worked in QQuickTableView already, since
it would rebuild the whole table for every model update. This
is really slow, and completely unnecessary.
Change-Id: I10750ff387f8b455d0f27c50a17926d9beb6dd03
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/quick/qquicktableview/data/plaintableview.qml | 3 | ||||
-rw-r--r-- | tests/auto/quick/qquicktableview/testmodel.h | 29 | ||||
-rw-r--r-- | tests/auto/quick/qquicktableview/tst_qquicktableview.cpp | 51 |
3 files changed, 73 insertions, 10 deletions
diff --git a/tests/auto/quick/qquicktableview/data/plaintableview.qml b/tests/auto/quick/qquicktableview/data/plaintableview.qml index 36c28525d5..21373e6732 100644 --- a/tests/auto/quick/qquicktableview/data/plaintableview.qml +++ b/tests/auto/quick/qquicktableview/data/plaintableview.qml @@ -71,6 +71,9 @@ Item { implicitHeight: delegateHeight color: "lightgray" border.width: 1 + + property string modelDataBinding: modelData + Text { anchors.centerIn: parent text: modelData diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h index ab18af7871..56d5021cec 100644 --- a/tests/auto/quick/qquicktableview/testmodel.h +++ b/tests/auto/quick/qquicktableview/testmodel.h @@ -57,10 +57,10 @@ public: if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); - int cell = index.row() + (index.column() * m_columns); - if (selectedCells.contains(cell)) - return QStringLiteral("selected"); - return QString("%1").arg(index.row()); + int serializedIndex = index.row() + (index.column() * m_columns); + if (modelData.contains(serializedIndex)) + return modelData.value(serializedIndex); + return QStringLiteral("%1").arg(index.row()); } QHash<int, QByteArray> roleNames() const override @@ -68,12 +68,21 @@ public: return { {Qt::DisplayRole, "display"} }; } - Q_INVOKABLE void selectCell(int row, int column) + Q_INVOKABLE void setModelData(const QPoint &cell, const QSize &span, const QString &prefix) { - int cell = row + (column * m_columns); - selectedCells.insert(cell); - auto index = createIndex(row, column, nullptr); - emit dataChanged(index, index); + for (int c = 0; c < span.width(); ++c) { + for (int r = 0; r < span.height(); ++r) { + const int changedRow = cell.y() + r; + const int changedColumn = cell.x() + c; + const int serializedIndex = changedRow + (changedColumn * m_rows); + const QString string = prefix + QStringLiteral("%1,%2").arg(changedColumn).arg(changedRow); + modelData.insert(serializedIndex, string); + } + } + + const auto topLeftIndex = createIndex(cell.y(), cell.x(), nullptr); + const auto bottomRightIndex = createIndex(cell.y() + span.height() - 1, cell.x() + span.width() - 1, nullptr); + emit dataChanged(topLeftIndex, bottomRightIndex); } bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override @@ -134,7 +143,7 @@ signals: private: int m_rows = 0; int m_columns = 0; - QSet<int> selectedCells; + QHash<int, QString> modelData; }; #define TestModelAsVariant(...) QVariant::fromValue(QSharedPointer<TestModel>(new TestModel(__VA_ARGS__))) diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index 86839b61dc..bc0990862f 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -51,6 +51,7 @@ using namespace QQuickVisualTestUtil; static const char* kTableViewPropName = "tableView"; static const char* kDelegateObjectName = "tableViewDelegate"; static const char *kDelegatesCreatedCountProp = "delegatesCreatedCount"; +static const char *kModelDataBindingProp = "modelDataBinding"; Q_DECLARE_METATYPE(QMarginsF); @@ -113,6 +114,7 @@ private slots: void flickOvershoot(); void checkRowColumnCount(); void modelSignals(); + void dataChangedSignal(); void checkIfDelegatesAreReused_data(); void checkIfDelegatesAreReused(); void checkContextProperties_data(); @@ -1113,6 +1115,55 @@ void tst_QQuickTableView::modelSignals() QCOMPARE(tableView->columns(), 1); } +void tst_QQuickTableView::dataChangedSignal() +{ + // Check that bindings to the model inside a delegate gets updated + // when the model item they bind to changes. + LOAD_TABLEVIEW("plaintableview.qml"); + + const QString prefix(QStringLiteral("changed")); + + TestModel model(10, 10); + tableView->setModel(QVariant::fromValue(&model)); + + WAIT_UNTIL_POLISHED; + + for (auto fxItem : tableViewPrivate->loadedItems) { + const auto item = tableViewPrivate->loadedTableItem(fxItem->cell)->item; + const QString modelDataBindingProperty = item->property(kModelDataBindingProp).toString(); + QString expectedModelData = QString::number(fxItem->cell.y()); + QCOMPARE(modelDataBindingProperty, expectedModelData); + } + + // Change one cell in the model + model.setModelData(QPoint(0, 0), QSize(1, 1), prefix); + + for (auto fxItem : tableViewPrivate->loadedItems) { + const QPoint cell = fxItem->cell; + const auto modelIndex = model.index(cell.y(), cell.x()); + QString expectedModelData = model.data(modelIndex, Qt::DisplayRole).toString(); + + const auto item = tableViewPrivate->loadedTableItem(fxItem->cell)->item; + const QString modelDataBindingProperty = item->property(kModelDataBindingProp).toString(); + + QCOMPARE(modelDataBindingProperty, expectedModelData); + } + + // Change four cells in one go + model.setModelData(QPoint(1, 0), QSize(2, 2), prefix); + + for (auto fxItem : tableViewPrivate->loadedItems) { + const QPoint cell = fxItem->cell; + const auto modelIndex = model.index(cell.y(), cell.x()); + QString expectedModelData = model.data(modelIndex, Qt::DisplayRole).toString(); + + const auto item = tableViewPrivate->loadedTableItem(fxItem->cell)->item; + const QString modelDataBindingProperty = item->property(kModelDataBindingProp).toString(); + + QCOMPARE(modelDataBindingProperty, expectedModelData); + } +} + void tst_QQuickTableView::checkIfDelegatesAreReused_data() { QTest::addColumn<bool>("reuseItems"); |