aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/qquicktableview/tst_qquicktableview.cpp')
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp213
1 files changed, 190 insertions, 23 deletions
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 96137877cb..7482367057 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -162,12 +162,16 @@ private slots:
void checkSyncView_childViews_data();
void checkSyncView_childViews();
void checkSyncView_differentSizedModels();
- void checkSyncView_differentGeometry();
+ void checkSyncView_differentGeometry_vertical();
+ void checkSyncView_differentGeometry_horizontal();
+ void checkSyncView_differentGeometry_both_directions();
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
void checkSyncView_pageFlicking();
void checkSyncView_emptyModel();
void checkSyncView_topLeftChanged();
+ void checkSyncView_dontRelayoutWhileFlicking();
+ void checkSyncView_detectTopLeftPositionChanged();
void delegateWithRequiredProperties();
void checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable();
void replaceModel();
@@ -278,6 +282,7 @@ private slots:
void checkScroll_data();
void checkScroll();
void checkRebuildJsModel();
+ void invalidateTableInstanceModelContextObject();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -3070,7 +3075,7 @@ void tst_QQuickTableView::checkSyncView_differentSizedModels()
QVERIFY(tableViewHVPrivate->loadedColumns.isEmpty());
}
-void tst_QQuickTableView::checkSyncView_differentGeometry()
+void tst_QQuickTableView::checkSyncView_differentGeometry_vertical()
{
// Check that you can have two tables in a syncView relation, where
// the sync "child" is larger than the sync view. This means that the
@@ -3083,46 +3088,106 @@ void tst_QQuickTableView::checkSyncView_differentGeometry()
GET_QML_TABLEVIEW(tableViewV);
GET_QML_TABLEVIEW(tableViewHV);
- tableView->setWidth(40);
- tableView->setHeight(40);
+ tableView->setHeight(90);
+ tableViewH->setSyncView(nullptr);
+ tableViewHV->setSyncView(nullptr);
auto tableViewModel = TestModelAsVariant(100, 100);
tableView->setModel(tableViewModel);
- tableViewH->setModel(tableViewModel);
tableViewV->setModel(tableViewModel);
- tableViewHV->setModel(tableViewModel);
WAIT_UNTIL_POLISHED;
- // Check that the column widths are in sync
- for (int column = tableViewH->leftColumn(); column < tableViewH->rightColumn(); ++column) {
- QCOMPARE(tableViewH->columnWidth(column), tableView->columnWidth(column));
- QCOMPARE(tableViewHV->columnWidth(column), tableView->columnWidth(column));
- }
+ // Check that the row heights are in sync
+ for (int row = tableViewV->topRow(); row < tableViewV->bottomRow(); ++row)
+ QCOMPARE(tableViewV->rowHeight(row), tableView->rowHeight(row));
+
+ // Flick in a new row
+ tableView->setContentY(20);
// Check that the row heights are in sync
- for (int row = tableViewV->topRow(); row < tableViewV->bottomRow(); ++row) {
+ for (int row = tableViewV->topRow(); row <= tableViewV->bottomRow(); ++row)
QCOMPARE(tableViewV->rowHeight(row), tableView->rowHeight(row));
- QCOMPARE(tableViewHV->rowHeight(row), tableView->rowHeight(row));
- }
+}
+
+void tst_QQuickTableView::checkSyncView_differentGeometry_horizontal()
+{
+ // Check that you can have two tables in a syncView relation, where
+ // the sync "child" is larger than the sync view. This means that the
+ // child will display more rows and columns than the parent.
+ // In that case, the sync view will anyway need to load the same rows
+ // and columns as the child, otherwise the column and row sizes
+ // cannot be determined for the child.
+ LOAD_TABLEVIEW("syncviewsimple.qml");
+ GET_QML_TABLEVIEW(tableViewH);
+ GET_QML_TABLEVIEW(tableViewV);
+ GET_QML_TABLEVIEW(tableViewHV);
+
+ tableView->setWidth(90);
+ tableViewV->setSyncView(nullptr);
+ tableViewHV->setSyncView(nullptr);
+
+ auto tableViewModel = TestModelAsVariant(100, 100);
+
+ tableView->setModel(tableViewModel);
+ tableViewH->setModel(tableViewModel);
- // Flick a bit, and do the same test again
- tableView->setContentX(200);
- tableView->setContentY(200);
WAIT_UNTIL_POLISHED;
// Check that the column widths are in sync
- for (int column = tableViewH->leftColumn(); column < tableViewH->rightColumn(); ++column) {
+ for (int column = tableViewH->leftColumn(); column < tableViewH->rightColumn(); ++column)
QCOMPARE(tableViewH->columnWidth(column), tableView->columnWidth(column));
- QCOMPARE(tableViewHV->columnWidth(column), tableView->columnWidth(column));
- }
+
+ // Flick in a new column
+ tableView->setContentX(20);
+
+ // Check that the column widths are in sync
+ for (int column = tableViewH->leftColumn(); column < tableViewH->rightColumn(); ++column)
+ QCOMPARE(tableViewH->columnWidth(column), tableView->columnWidth(column));
+}
+
+void tst_QQuickTableView::checkSyncView_differentGeometry_both_directions() {
+ // Check that you can have two tables in a syncView relation, where
+ // the sync "child" is larger than the sync view. This means that the
+ // child will display more rows and columns than the parent.
+ // In that case, the sync view will anyway need to load the same rows
+ // and columns as the child, otherwise the column and row sizes
+ // cannot be determined for the child.
+ LOAD_TABLEVIEW("syncviewsimple.qml");
+ GET_QML_TABLEVIEW(tableViewH);
+ GET_QML_TABLEVIEW(tableViewV);
+ GET_QML_TABLEVIEW(tableViewHV);
+
+ tableView->setWidth(90);
+ tableView->setHeight(90);
+ tableViewHV->setSyncView(nullptr);
+
+ auto tableViewModel = TestModelAsVariant(100, 100);
+
+ tableView->setModel(tableViewModel);
+ tableViewH->setModel(tableViewModel);
+ tableViewV->setModel(tableViewModel);
+
+ WAIT_UNTIL_POLISHED;
// Check that the row heights are in sync
- for (int row = tableViewV->topRow(); row < tableViewV->bottomRow(); ++row) {
+ for (int row = tableViewV->topRow(); row < tableViewV->bottomRow(); ++row)
QCOMPARE(tableViewV->rowHeight(row), tableView->rowHeight(row));
- QCOMPARE(tableViewHV->rowHeight(row), tableView->rowHeight(row));
- }
+ // Check that the column widths are in sync
+ for (int column = tableViewH->leftColumn(); column < tableViewH->rightColumn(); ++column)
+ QCOMPARE(tableViewH->columnWidth(column), tableView->columnWidth(column));
+
+ // Flick in a new row
+ tableView->setContentX(20);
+ tableView->setContentY(20);
+
+ // Check that the row heights are in sync
+ for (int row = tableViewV->topRow(); row <= tableViewV->bottomRow(); ++row)
+ QCOMPARE(tableViewV->rowHeight(row), tableView->rowHeight(row));
+ // Check that the column widths are in sync
+ for (int column = tableViewH->leftColumn(); column < tableViewH->rightColumn(); ++column)
+ QCOMPARE(tableViewH->columnWidth(column), tableView->columnWidth(column));
}
void tst_QQuickTableView::checkSyncView_connect_late_data()
@@ -3328,6 +3393,85 @@ void tst_QQuickTableView::checkSyncView_topLeftChanged()
QCOMPARE(tableViewV->topRow(), tableView->topRow());
}
+void tst_QQuickTableView::checkSyncView_dontRelayoutWhileFlicking()
+{
+ // Check that we don't do a full relayout in a sync child when
+ // a new row or column is flicked into the view. Normal load
+ // and unload of edges should suffice, equal to how the main
+ // TableView (syncView) does it.
+ LOAD_TABLEVIEW("syncviewsimple.qml");
+ GET_QML_TABLEVIEW(tableViewHV);
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ tableViewHV->setModel(model);
+
+ tableView->setColumnWidthProvider(QJSValue());
+ tableView->setRowHeightProvider(QJSValue());
+ view->rootObject()->setProperty("delegateWidth", 50);
+ view->rootObject()->setProperty("delegateHeight", 50);
+
+ WAIT_UNTIL_POLISHED;
+
+ // To check that we don't do a relayout when flicking horizontally, we use a "trick"
+ // where we check the rebuildOptions when we receive the rightColumnChanged
+ // signal. If this signal is emitted as a part of a relayout, rebuildOptions
+ // would still be different from RebuildOption::None at that point.
+ bool columnFlickedIn = false;
+ connect(tableViewHV, &QQuickTableView::rightColumnChanged, [&] {
+ columnFlickedIn = true;
+ QCOMPARE(tableViewHVPrivate->rebuildOptions, QQuickTableViewPrivate::RebuildOption::None);
+ });
+
+ // We do the same for vertical flicking
+ bool rowFlickedIn = false;
+ connect(tableViewHV, &QQuickTableView::bottomRowChanged, [&] {
+ rowFlickedIn = true;
+ QCOMPARE(tableViewHVPrivate->rebuildOptions, QQuickTableViewPrivate::RebuildOption::None);
+ });
+
+ // Move the main tableview so that a new column is flicked in
+ tableView->setContentX(60);
+ QTRY_VERIFY(columnFlickedIn);
+
+ // Move the main tableview so that a new row is flicked in
+ tableView->setContentY(60);
+ QTRY_VERIFY(rowFlickedIn);
+}
+
+void tst_QQuickTableView::checkSyncView_detectTopLeftPositionChanged()
+{
+ // It can happen that, during a resize of columns or rows from using a float-based
+ // slider, that the position of the top-left delegate item is shifted a bit left or
+ // right because of rounding issues. And this again can over time, as you flick, make
+ // the loadedTableOuterRect get slightly out of sync in the sync child compared to the
+ // sync view. TableView will detect if this happens (in syncSyncView), and correct for
+ // it. And this test will test that it works.
+ LOAD_TABLEVIEW("syncviewsimple.qml");
+ GET_QML_TABLEVIEW(tableViewHV);
+
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+ tableViewHV->setModel(model);
+
+ WAIT_UNTIL_POLISHED;
+
+ // Writing an auto test to trigger this rounding issue is very hard. So to keep it
+ // simple, we cheat by just moving the loadedTableOuterRect directly, and
+ // check that the syncView child detects it, and corrects it, upon doing a
+ // forceLayout()
+ tableViewPrivate->loadedTableOuterRect.moveLeft(20);
+ tableViewPrivate->loadedTableOuterRect.moveTop(30);
+ tableViewPrivate->relayoutTableItems();
+ tableViewHV->forceLayout();
+
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.left(), 20);
+ QCOMPARE(tableViewHVPrivate->loadedTableOuterRect.left(), 20);
+
+ QCOMPARE(tableViewPrivate->loadedTableOuterRect.top(), 30);
+ QCOMPARE(tableViewHVPrivate->loadedTableOuterRect.top(), 30);
+}
+
void tst_QQuickTableView::checkThatFetchMoreIsCalledWhenScrolledToTheEndOfTable()
{
LOAD_TABLEVIEW("plaintableview.qml");
@@ -7523,6 +7667,29 @@ void tst_QQuickTableView::checkRebuildJsModel()
QCOMPARE(tableView->property(modelUpdated).toInt(), 1);
}
+void tst_QQuickTableView::invalidateTableInstanceModelContextObject()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("invalidateModelContextObject.qml"));
+
+ std::unique_ptr<QQuickWindow> window(qobject_cast<QQuickWindow*>(component.create()));
+ QVERIFY(window);
+
+ auto tableView = window->property("tableView").value<QQuickTableView *>();
+ QVERIFY(tableView);
+
+ const int modelData = window->property("modelData").toInt();
+ QTRY_COMPARE(tableView->rows(), modelData);
+
+ bool tableViewDestroyed = false;
+ connect(tableView, &QObject::destroyed, [&] {
+ tableViewDestroyed = true;
+ });
+
+ window.reset();
+ QTRY_COMPARE(tableViewDestroyed, true);
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"