diff options
author | Liang Qi <liang.qi@qt.io> | 2019-11-21 11:34:57 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-11-22 09:50:11 +0100 |
commit | aa3813366a8e772cd58c9253461cf2dc50b97a9d (patch) | |
tree | e306a60fa9b2d1f7dd2e6b245fdf05214c7c55df /tests/auto/quick/qquicktableview | |
parent | 4241bb4d26ef69eb212e0274bad0926ec71bead9 (diff) | |
parent | acb6ed0815f92588c3ff875a568e9561fe61218c (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts:
src/qml/qml/qqmlextensionplugin.cpp
tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
Change-Id: Ic58d36a8532015bae30f2690063db9829b3bf372
Diffstat (limited to 'tests/auto/quick/qquicktableview')
4 files changed, 120 insertions, 3 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/qquicktableview.pro b/tests/auto/quick/qquicktableview/qquicktableview.pro index da0c0b01d0..735c728fc6 100644 --- a/tests/auto/quick/qquicktableview/qquicktableview.pro +++ b/tests/auto/quick/qquicktableview/qquicktableview.pro @@ -13,3 +13,5 @@ TESTDATA = data/* QT += core-private gui-private qml-private quick-private testlib qmlmodels-private +DISTFILES += + diff --git a/tests/auto/quick/qquicktableview/testmodel.h b/tests/auto/quick/qquicktableview/testmodel.h index 50f434019e..2697b1e801 100644 --- a/tests/auto/quick/qquicktableview/testmodel.h +++ b/tests/auto/quick/qquicktableview/testmodel.h @@ -46,6 +46,13 @@ public: , m_columns(columns) {} + TestModel(int rows, int columns, bool dataCanBeFetched, QObject *parent = nullptr) + : QAbstractTableModel(parent) + , m_rows(rows) + , m_columns(columns) + , m_dataCanBeFetched(dataCanBeFetched) + {} + int rowCount(const QModelIndex & = QModelIndex()) const override { return m_rows; } void setRowCount(int count) { beginResetModel(); m_rows = count; emit rowCountChanged(); endResetModel(); } @@ -63,6 +70,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 +116,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; } @@ -128,6 +148,12 @@ public: return true; } + bool canFetchMore(const QModelIndex &parent) const override + { + Q_UNUSED(parent) + return m_dataCanBeFetched; + } + void swapRows(int row1, int row2) { layoutAboutToBeChanged(); @@ -139,6 +165,12 @@ public: layoutChanged(); } + void fetchMore(const QModelIndex &parent) override + { + Q_UNUSED(parent) + addRow(m_rows - 1); + } + void clear() { beginResetModel(); m_rows = 0; @@ -159,6 +191,7 @@ signals: private: int m_rows = 0; int m_columns = 0; + bool m_dataCanBeFetched = false; QHash<int, QString> modelData; }; diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index 230dcc9446..6ae095a7d6 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -60,7 +60,7 @@ Q_DECLARE_METATYPE(QMarginsF); auto PROPNAME = view->rootObject()->property(#PROPNAME).value<QQuickTableView *>(); \ QVERIFY(PROPNAME); \ auto PROPNAME ## Private = QQuickTableViewPrivate::get(PROPNAME); \ - Q_UNUSED(PROPNAME ## Private) + Q_UNUSED(PROPNAME ## Private) void() #define LOAD_TABLEVIEW(fileName) \ view->setSource(testFileUrl(fileName)); \ @@ -120,6 +120,7 @@ private slots: void checkRowHeightProviderNotCallable(); void checkForceLayoutFunction(); void checkForceLayoutEndUpDoingALayout(); + void checkForceLayoutDuringModelChange(); void checkContentWidthAndHeight(); void checkPageFlicking(); void checkExplicitContentWidthAndHeight(); @@ -159,6 +160,7 @@ private slots: void checkContextPropertiesQQmlListProperyModel_data(); void checkContextPropertiesQQmlListProperyModel(); void checkRowAndColumnChangedButNotIndex(); + void checkThatWeAlwaysEmitChangedUponItemReused(); void checkChangingModelFromDelegate(); void checkRebuildViewportOnly(); void useDelegateChooserWithoutDefault(); @@ -174,6 +176,7 @@ private slots: void checkSyncView_connect_late_data(); void checkSyncView_connect_late(); void delegateWithRequiredProperties(); + void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable(); }; tst_QQuickTableView::tst_QQuickTableView() @@ -588,6 +591,29 @@ void tst_QQuickTableView::checkForceLayoutEndUpDoingALayout() QCOMPARE(fxItem->item->height(), newDelegateSize); } +void tst_QQuickTableView::checkForceLayoutDuringModelChange() +{ + // Check that TableView doesn't assert if we call + // forceLayout() in the middle of a model change. + LOAD_TABLEVIEW("plaintableview.qml"); + + const int initialRowCount = 10; + TestModel model(initialRowCount, 10); + tableView->setModel(QVariant::fromValue(&model)); + + connect(&model, &QAbstractItemModel::rowsInserted, [=](){ + QCOMPARE(tableView->rows(), initialRowCount); + tableView->forceLayout(); + QCOMPARE(tableView->rows(), initialRowCount + 1); + }); + + WAIT_UNTIL_POLISHED; + + QCOMPARE(tableView->rows(), initialRowCount); + model.addRow(0); + QCOMPARE(tableView->rows(), initialRowCount + 1); +} + void tst_QQuickTableView::checkContentWidthAndHeight() { // Check that contentWidth/Height reports the correct size of the @@ -2060,6 +2086,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 @@ -2617,7 +2678,27 @@ void tst_QQuickTableView::checkSyncView_connect_late() QCOMPARE(tableViewVPrivate->loadedTableOuterRect.left(), 0); QCOMPARE(tableViewHVPrivate->loadedTableOuterRect, tableViewPrivate->loadedTableOuterRect); +} + +void tst_QQuickTableView::checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable() +{ + LOAD_TABLEVIEW("plaintableview.qml"); + + auto model = TestModelAsVariant(5, 5, true); + tableView->setModel(model); + WAIT_UNTIL_POLISHED; + + QCOMPARE(tableView->rows(), 5); + QCOMPARE(tableView->columns(), 5); + + // Flick table out of view on top + tableView->setContentX(0); + tableView->setContentY(-tableView->height() - 10); + tableView->polish(); + WAIT_UNTIL_POLISHED; + QCOMPARE(tableView->rows(), 6); + QCOMPARE(tableView->columns(), 5); } void tst_QQuickTableView::delegateWithRequiredProperties() @@ -2648,7 +2729,7 @@ void tst_QQuickTableView::delegateWithRequiredProperties() auto model = QVariant::fromValue(QSharedPointer<MyTable>(new MyTable)); { QTest::ignoreMessage(QtMsgType::QtInfoMsg, "success"); - LOAD_TABLEVIEW("delegateWithRequired.qml") + LOAD_TABLEVIEW("delegateWithRequired.qml"); QVERIFY(tableView); tableView->setModel(model); WAIT_UNTIL_POLISHED; @@ -2656,7 +2737,7 @@ void tst_QQuickTableView::delegateWithRequiredProperties() } { QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(R"|(TableView: failed loading index: \d)|")); - LOAD_TABLEVIEW("delegatewithRequiredUnset.qml") + LOAD_TABLEVIEW("delegatewithRequiredUnset.qml"); QVERIFY(tableView); tableView->setModel(model); WAIT_UNTIL_POLISHED; |