diff options
Diffstat (limited to 'tests/auto/quick/qquicktableview/tst_qquicktableview.cpp')
| -rw-r--r-- | tests/auto/quick/qquicktableview/tst_qquicktableview.cpp | 213 |
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" |
