aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquicktableview
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-11-21 11:34:57 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-11-22 09:50:11 +0100
commitaa3813366a8e772cd58c9253461cf2dc50b97a9d (patch)
treee306a60fa9b2d1f7dd2e6b245fdf05214c7c55df /tests/auto/quick/qquicktableview
parent4241bb4d26ef69eb212e0274bad0926ec71bead9 (diff)
parentacb6ed0815f92588c3ff875a568e9561fe61218c (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')
-rw-r--r--tests/auto/quick/qquicktableview/data/plaintableview.qml1
-rw-r--r--tests/auto/quick/qquicktableview/qquicktableview.pro2
-rw-r--r--tests/auto/quick/qquicktableview/testmodel.h33
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp87
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;