diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2018-08-09 09:14:03 +0200 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2018-08-09 12:11:21 +0000 |
commit | 889686505f9f13e69035b44d0c6dae86fd1bcf03 (patch) | |
tree | 4a63f9e57716707c414c39b08eda9af907cb9d22 | |
parent | 77b4923c999fb0149e440500096662cbb7c8a4c8 (diff) |
QQuickTableView: change how we calculate content size
The current calculations where a bit off. Change it to be
precise, and add an auto test to verify the contentWidth/Height
ends up correct as the flickable is flicked towards the end of
the table.
Change-Id: I784a1bba2ea8fddd09cee8ecda7e2089c8b5c74f
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r-- | src/quick/items/qquicktableview.cpp | 34 | ||||
-rw-r--r-- | tests/auto/quick/qquicktableview/data/contentwidthheight.qml | 82 | ||||
-rw-r--r-- | tests/auto/quick/qquicktableview/tst_qquicktableview.cpp | 81 |
3 files changed, 180 insertions, 17 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index e93544c37a..23f6e79049 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -174,14 +174,14 @@ void QQuickTableViewPrivate::updateContentWidth() if (currentRightColumn > contentSizeBenchMarkPoint.x()) { contentSizeBenchMarkPoint.setX(currentRightColumn); - qreal currentWidth = loadedTableOuterRect.right(); - qreal averageCellSize = currentWidth / (currentRightColumn + 1); - qreal averageSize = averageCellSize + cellSpacing.width(); - qreal estimatedWith = (tableSize.width() * averageSize) - cellSpacing.width(); + const qreal spacing = currentRightColumn * cellSpacing.width(); + const qreal margins = tableMargins.left() + tableMargins.right(); + qreal currentWidth = loadedTableOuterRect.right() - tableMargins.left(); + const qreal averageCellWidth = (currentWidth - spacing) / (currentRightColumn + 1); + qreal estimatedWidth = (tableSize.width() * (averageCellWidth + cellSpacing.width())) - cellSpacing.width(); - // loadedTableOuterRect has already been adjusted for left margin - currentWidth += tableMargins.right(); - estimatedWith += tableMargins.right(); + currentWidth += margins; + estimatedWidth += margins; if (currentRightColumn >= tableSize.width() - 1) { // We are at the last column, and can set the exact width @@ -189,12 +189,12 @@ void QQuickTableViewPrivate::updateContentWidth() q->setContentWidth(currentWidth); } else if (currentWidth >= q->implicitWidth()) { // We are at the estimated width, but there are still more columns - q->setContentWidth(estimatedWith); + q->setContentWidth(estimatedWidth); } else { // Only set a new width if the new estimate is substantially different - qreal diff = 1 - (estimatedWith / q->implicitWidth()); + qreal diff = 1 - (estimatedWidth / q->implicitWidth()); if (qAbs(diff) > thresholdBeforeAdjust) - q->setContentWidth(estimatedWith); + q->setContentWidth(estimatedWidth); } } } @@ -209,14 +209,14 @@ void QQuickTableViewPrivate::updateContentHeight() if (currentBottomRow > contentSizeBenchMarkPoint.y()) { contentSizeBenchMarkPoint.setY(currentBottomRow); - qreal currentHeight = loadedTableOuterRect.bottom(); - qreal averageCellSize = currentHeight / (currentBottomRow + 1); - qreal averageSize = averageCellSize + cellSpacing.height(); - qreal estimatedHeight = (tableSize.height() * averageSize) - cellSpacing.height(); + const qreal spacing = currentBottomRow * cellSpacing.height(); + const qreal margins = tableMargins.top() + tableMargins.bottom(); + qreal currentHeight = loadedTableOuterRect.bottom() - tableMargins.top(); + const qreal averageCellHeight = (currentHeight - spacing) / (currentBottomRow + 1); + qreal estimatedHeight = (tableSize.height() * (averageCellHeight + cellSpacing.height())) - cellSpacing.height(); - // loadedTableOuterRect has already been adjusted for top margin - currentHeight += tableMargins.bottom(); - estimatedHeight += tableMargins.bottom(); + currentHeight += margins; + estimatedHeight += margins; if (currentBottomRow >= tableSize.height() - 1) { // We are at the last row, and can set the exact height diff --git a/tests/auto/quick/qquicktableview/data/contentwidthheight.qml b/tests/auto/quick/qquicktableview/data/contentwidthheight.qml new file mode 100644 index 0000000000..2c9d64c20e --- /dev/null +++ b/tests/auto/quick/qquicktableview/data/contentwidthheight.qml @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Window 2.3 +import Qt.labs.tableview 1.0 + +Item { + width: 640 + height: 450 + + property alias tableView: tableView + property Component delegate: tableViewDelegate + + TableView { + id: tableView + width: 500 + height: 500 + anchors.margins: 1 + clip: true + delegate: tableViewDelegate + cacheBuffer: 0 + columnSpacing: 1 + rowSpacing: 1 + leftMargin: 10 + rightMargin: 10 + topMargin: 10 + bottomMargin: 10 + columnWidthProvider: function(column) { return column < 20 ? 100 : 200 } + rowHeightProvider: function(row) { return row < 20 ? 100 : 200 } + } + + Component { + id: tableViewDelegate + Rectangle { + objectName: "tableViewDelegate" + color: "lightgray" + border.width: 1 + Text { + anchors.centerIn: parent + text: column + } + } + } + +} diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp index 7418189ee1..94d3a356fe 100644 --- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp +++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp @@ -95,6 +95,7 @@ private slots: void checkRowHeightProvider(); void checkRowHeightProviderInvalidReturnValues(); void checkRowHeightProviderNotCallable(); + void checkContentWidthAndHeight(); void noDelegate(); void countDelegateItems_data(); void countDelegateItems(); @@ -400,6 +401,86 @@ void tst_QQuickTableView::checkRowHeightProviderNotCallable() QCOMPARE(fxItem->item->height(), kDefaultRowHeight); } +void tst_QQuickTableView::checkContentWidthAndHeight() +{ + // Check that contentWidth/Height reports the correct size of the the + // table, based on knowledge of the rows and columns that has been loaded. + LOAD_TABLEVIEW("contentwidthheight.qml"); + + // Vertical and horizontal properties should be mirrored, so we only have + // to do the calculations once, and use them for both axis, below. + QCOMPARE(tableView->width(), tableView->height()); + QCOMPARE(tableView->rowSpacing(), tableView->columnSpacing()); + QCOMPARE(tableView->leftMargin(), tableView->rightMargin()); + QCOMPARE(tableView->topMargin(), tableView->bottomMargin()); + + const int tableSize = 100; + const int cellSizeSmall = 100; + const int cellSizeLarge = 200; + const int spacing = 1; + const int margin = 10; + const int smallCellCount = 20; + const int largeCellCount = tableSize - smallCellCount; + const qreal spacingAndMargins = ((tableSize - 1) * spacing) + (margin * 2); + auto model = TestModelAsVariant(tableSize, tableSize); + + tableView->setModel(model); + + WAIT_UNTIL_POLISHED; + + const qreal expectedSizeInit = (tableSize * cellSizeSmall) + ((tableSize - 1) * spacing) + (margin * 2); + QCOMPARE(tableView->contentWidth(), expectedSizeInit); + QCOMPARE(tableView->contentHeight(), expectedSizeInit); + + // Flick in 5 more rows and columns, but not so far that we start loading in + // the ones that are bigger. Loading in more rows and columns of the same + // size as the initial ones should not change the first prediction. + qreal flickTo = ((cellSizeSmall + spacing) * 5) + margin; + tableView->setContentX(flickTo); + tableView->setContentY(flickTo); + + QCOMPARE(tableView->contentWidth(), expectedSizeInit); + QCOMPARE(tableView->contentHeight(), expectedSizeInit); + + // Flick to row and column 20 (smallCellCount), since there the row and + // column sizes increases with 100. Check that TableView then adjusts + // contentWidth and contentHeight accordingly. + flickTo = ((cellSizeSmall + spacing) * smallCellCount) + margin - spacing; + tableView->setContentX(flickTo); + tableView->setContentY(flickTo); + + const int largeSizeCellCountInView = qCeil(tableView->width() / cellSizeLarge); + const int bottomRow = smallCellCount + largeSizeCellCountInView - 1; + QCOMPARE(tableViewPrivate->loadedTable.right(), bottomRow); + + const qreal firstHalfLength = smallCellCount * cellSizeSmall; + const qreal secondHalfOneScreenLength = largeSizeCellCountInView * cellSizeLarge; + const qreal lengthAfterFlick = firstHalfLength + secondHalfOneScreenLength; + const qreal averageCellSize = lengthAfterFlick / (smallCellCount + largeSizeCellCountInView); + const qreal expectedSizeHalf = (tableSize * averageCellSize) + spacingAndMargins; + + QCOMPARE(tableView->contentWidth(), expectedSizeHalf); + QCOMPARE(tableView->contentHeight(), expectedSizeHalf); + + // Flick to the end (row/column 100, and overshoot a bit), and + // check that we then end up with the exact content width/height. + const qreal secondHalfLength = largeCellCount * cellSizeLarge; + const qreal expectedFullSize = (firstHalfLength + secondHalfLength) + spacingAndMargins; + tableView->setContentX(expectedFullSize); + tableView->setContentY(expectedFullSize); + + QCOMPARE(tableView->contentWidth(), expectedFullSize); + QCOMPARE(tableView->contentHeight(), expectedFullSize); + + // Flick back to start. Since we know the actual table + // size, contentWidth/Height shouldn't change. + tableView->setContentX(0); + tableView->setContentY(0); + + QCOMPARE(tableView->contentWidth(), expectedFullSize); + QCOMPARE(tableView->contentHeight(), expectedFullSize); +} + void tst_QQuickTableView::noDelegate() { // Check that you can skip setting a delegate without |