aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-10-21 09:36:50 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-10-27 10:07:20 +0000
commitfa966fb9e59ca3fb1db10abd61068201e8f9ab59 (patch)
treed91fbf1297eb8e8b500d9684cf235842e5cc6958
parent0b8ac76c57ca0efa36cf4db546c25ece6b3a18bb (diff)
QQuickTableView: ensure that column sizes are in sync when using a sync view
When a TableView has a sync child, it will decide the row and column sizes for it, so that the views are kept in sync. It can happen, though, that the geometry of the sync view is smaller than the geometry of the sync child. In that case, the sync child will show more rows and column than the sync view. This caused a bug when a TableView was placed inside a ScrollView with a HorizontalHeaderView on top (as a sibling of the ScrollView). In that case, the HorizontalHeaderView would actually be wider than the TableView, since the latter would be shrinked a bit to make room for a vertical scrollbar. The result would be that the HorizontalHeaderView would end up showing more columns than TableView. But Since TableView doesn't always know the width of a column that has not yet been loaded, the size of the header column would also end up wrong. This patch will make sure that the "virtual" viewport of the sync view is at least as large as the size of the sync children. This will ensure that we end up filling up a TableView with the same amount of rows and columns as any of the connected header views. Fixes: QTBUG-107837 Change-Id: I32926738d48d6bd3b0892e6256a8f8d1ed5f1fa2 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> (cherry picked from commit 32372f8895369bdd149fb90952b8054214a6dfe8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/quick/items/qquicktableview.cpp24
-rw-r--r--tests/auto/quick/qquicktableview/data/syncviewsimple.qml19
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp80
3 files changed, 118 insertions, 5 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 38fe42f9c5..2483b5781b 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -3165,7 +3165,7 @@ void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
void QQuickTableViewPrivate::loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode)
{
const int edgeIndex = nextVisibleEdgeIndexAroundLoadedTable(edge);
- qCDebug(lcTableViewDelegateLifecycle) << edge << edgeIndex;
+ qCDebug(lcTableViewDelegateLifecycle) << edge << edgeIndex << q_func();
const auto &visibleCells = edge & (Qt::LeftEdge | Qt::RightEdge)
? loadedRows.values() : loadedColumns.values();
@@ -4077,10 +4077,26 @@ void QQuickTableViewPrivate::setLocalViewportY(qreal contentY)
void QQuickTableViewPrivate::syncViewportRect()
{
- // Sync viewportRect so that it contains the actual geometry of the viewport
+ // Sync viewportRect so that it contains the actual geometry of the viewport.
+ // Since the column (and row) size of a sync child is decided by the column size
+ // of its sync view, the viewport width of a sync view needs to be the maximum of
+ // the sync views width, and its sync childrens width. This to ensure that no sync
+ // child loads a column which is not yet loaded by the sync view, since then the
+ // implicit column size cannot be resolved.
Q_Q(QQuickTableView);
- viewportRect = QRectF(q->contentX(), q->contentY(), q->width(), q->height());
- qCDebug(lcTableViewDelegateLifecycle) << viewportRect;
+
+ qreal w = q->width();
+ qreal h = q->height();
+
+ for (auto syncChild : std::as_const(syncChildren)) {
+ auto syncChild_d = syncChild->d_func();
+ if (syncChild_d->syncHorizontally)
+ w = qMax(w, syncChild->width());
+ if (syncChild_d->syncHorizontally)
+ h = qMax(h, syncChild->height());
+ }
+
+ viewportRect = QRectF(q->contentX(), q->contentY(), w, h);
}
void QQuickTableViewPrivate::init()
diff --git a/tests/auto/quick/qquicktableview/data/syncviewsimple.qml b/tests/auto/quick/qquicktableview/data/syncviewsimple.qml
index f0534e8440..73c47e859c 100644
--- a/tests/auto/quick/qquicktableview/data/syncviewsimple.qml
+++ b/tests/auto/quick/qquicktableview/data/syncviewsimple.qml
@@ -57,7 +57,7 @@ Item {
height: 100
anchors.margins: 1
clip: true
- delegate: tableViewDelegate
+ delegate: tableViewDelegateMainView
columnSpacing: 1
rowSpacing: 1
@@ -70,6 +70,23 @@ Item {
id: tableViewDelegate
Rectangle {
objectName: "tableViewDelegate"
+ color: "lightblue"
+ border.width: 1
+ implicitWidth: 100
+ implicitHeight: 100
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 10
+ text: parent.TableView.view.objectName + "\n" + column + ", " + row
+ }
+ }
+ }
+
+ Component {
+ id: tableViewDelegateMainView
+ Rectangle {
+ objectName: "tableViewDelegate"
color: "lightgray"
border.width: 1
implicitWidth: 30
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index eeaf95068f..e4325dbdad 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -155,6 +155,7 @@ private slots:
void checkSyncView_childViews_data();
void checkSyncView_childViews();
void checkSyncView_differentSizedModels();
+ void checkSyncView_differentGeometry();
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
void checkSyncView_pageFlicking();
@@ -2680,6 +2681,18 @@ void tst_QQuickTableView::checkSyncView_rootView()
QCOMPARE(tableViewVPrivate->loadedTableOuterRect.left(), 0);
QCOMPARE(tableViewHVPrivate->loadedTableOuterRect, tableViewPrivate->loadedTableOuterRect);
+
+ // Check that the column widths are in sync
+ for (int column = tableView->leftColumn(); column < tableView->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 = tableView->topRow(); row < tableView->bottomRow(); ++row) {
+ QCOMPARE(tableViewV->rowHeight(row), tableView->rowHeight(row));
+ QCOMPARE(tableViewHV->rowHeight(row), tableView->rowHeight(row));
+ }
}
void tst_QQuickTableView::checkSyncView_childViews_data()
@@ -2785,6 +2798,18 @@ void tst_QQuickTableView::checkSyncView_childViews()
QCOMPARE(tableViewHVPrivate->bottomRow(), tableViewPrivate->bottomRow());
QCOMPARE(tableViewHVPrivate->loadedTableOuterRect, tableViewPrivate->loadedTableOuterRect);
}
+
+ // Check that the column widths are in sync
+ for (int column = tableView->leftColumn(); column < tableView->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 = tableView->topRow(); row < tableView->bottomRow(); ++row) {
+ QCOMPARE(tableViewV->rowHeight(row), tableView->rowHeight(row));
+ QCOMPARE(tableViewHV->rowHeight(row), tableView->rowHeight(row));
+ }
}
void tst_QQuickTableView::checkSyncView_differentSizedModels()
@@ -2850,6 +2875,61 @@ void tst_QQuickTableView::checkSyncView_differentSizedModels()
QVERIFY(tableViewHVPrivate->loadedColumns.isEmpty());
}
+void tst_QQuickTableView::checkSyncView_differentGeometry()
+{
+ // 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(40);
+ tableView->setHeight(40);
+
+ 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));
+ QCOMPARE(tableViewHV->rowHeight(row), tableView->rowHeight(row));
+ }
+
+ // 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) {
+ 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));
+ QCOMPARE(tableViewHV->rowHeight(row), tableView->rowHeight(row));
+ }
+}
+
void tst_QQuickTableView::checkSyncView_connect_late_data()
{
QTest::addColumn<qreal>("flickToPos");