QQuickTableView: add support for hiding rows and columns

This patch will add support for hiding rows and columns to TableView.
You can now hide a column by returning 0 width for it from the
columnWidthProvider. The same can be done to hide a row (by using the
rowHeightProvider). If you return NaN or negative number, TableView
will fall back to calculate the size of the column/row by looking at
the delegate items, like before. This to make it possible to hide
some rows/columns, without having to calculate and return the heights
and widths of the other rows and columns.

[ChangeLog][QtQuick][TableView] Added support for hiding rows and columns
by setting their size to 0 from the columnsWidthProvider/rowHeightProvider.

Change-Id: If9e1a8db91e257d36cb2787bab4856e6201456ac
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
This commit is contained in:
Richard Moe Gustavsen 2019-01-08 11:10:13 +01:00
parent e04e5db13d
commit 0068575602
6 changed files with 841 additions and 385 deletions

File diff suppressed because it is too large Load Diff

View File

@ -88,54 +88,52 @@ public:
public:
void begin(const QPoint &cell, const QPointF &pos, QQmlIncubator::IncubationMode incubationMode)
{
Q_ASSERT(!active);
active = true;
tableEdge = Qt::Edge(0);
tableCells = QLine(cell, cell);
mode = incubationMode;
cellCount = 1;
currentIndex = 0;
startPos = pos;
Q_ASSERT(!m_active);
m_active = true;
m_edge = Qt::Edge(0);
m_mode = incubationMode;
m_edgeIndex = cell.x();
m_visibleCellsInEdge.clear();
m_visibleCellsInEdge.append(cell.y());
m_currentIndex = 0;
m_startPos = pos;
qCDebug(lcTableViewDelegateLifecycle()) << "begin top-left:" << toString();
}
void begin(const QLine cellsToLoad, Qt::Edge edgeToLoad, QQmlIncubator::IncubationMode incubationMode)
void begin(Qt::Edge edgeToLoad, int edgeIndex, const QList<int> visibleCellsInEdge, QQmlIncubator::IncubationMode incubationMode)
{
Q_ASSERT(!active);
active = true;
tableEdge = edgeToLoad;
tableCells = cellsToLoad;
mode = incubationMode;
cellCount = tableCells.x2() - tableCells.x1() + tableCells.y2() - tableCells.y1() + 1;
currentIndex = 0;
Q_ASSERT(!m_active);
m_active = true;
m_edge = edgeToLoad;
m_edgeIndex = edgeIndex;
m_visibleCellsInEdge = visibleCellsInEdge;
m_mode = incubationMode;
m_currentIndex = 0;
qCDebug(lcTableViewDelegateLifecycle()) << "begin:" << toString();
}
inline void markAsDone() { active = false; }
inline bool isActive() { return active; }
inline void markAsDone() { m_active = false; }
inline bool isActive() { return m_active; }
inline QPoint firstCell() { return tableCells.p1(); }
inline QPoint lastCell() { return tableCells.p2(); }
inline QPoint currentCell() { return cellAt(currentIndex); }
inline QPoint previousCell() { return cellAt(currentIndex - 1); }
inline QPoint currentCell() { return cellAt(m_currentIndex); }
inline bool hasCurrentCell() { return m_currentIndex < m_visibleCellsInEdge.count(); }
inline void moveToNextCell() { ++m_currentIndex; }
inline bool atBeginning() { return currentIndex == 0; }
inline bool hasCurrentCell() { return currentIndex < cellCount; }
inline void moveToNextCell() { ++currentIndex; }
inline Qt::Edge edge() { return m_edge; }
inline int row() { return cellAt(0).y(); }
inline int column() { return cellAt(0).x(); }
inline QQmlIncubator::IncubationMode incubationMode() { return m_mode; }
inline Qt::Edge edge() { return tableEdge; }
inline QQmlIncubator::IncubationMode incubationMode() { return mode; }
inline QPointF startPosition() { return startPos; }
inline QPointF startPosition() { return m_startPos; }
QString toString()
{
QString str;
QDebug dbg(&str);
dbg.nospace() << "TableSectionLoadRequest(" << "edge:"
<< tableEdge << " cells:" << tableCells << " incubation:";
<< m_edge << ", edgeIndex:" << m_edgeIndex << ", incubation:";
switch (mode) {
switch (m_mode) {
case QQmlIncubator::Asynchronous:
dbg << "Asynchronous";
break;
@ -151,22 +149,31 @@ public:
}
private:
Qt::Edge tableEdge = Qt::Edge(0);
QLine tableCells;
int currentIndex = 0;
int cellCount = 0;
bool active = false;
QQmlIncubator::IncubationMode mode = QQmlIncubator::AsynchronousIfNested;
QPointF startPos;
Qt::Edge m_edge = Qt::Edge(0);
QList<int> m_visibleCellsInEdge;
int m_edgeIndex = 0;
int m_currentIndex = 0;
bool m_active = false;
QQmlIncubator::IncubationMode m_mode = QQmlIncubator::AsynchronousIfNested;
QPointF m_startPos;
QPoint cellAt(int index)
{
int x = tableCells.p1().x() + (tableCells.dx() ? index : 0);
int y = tableCells.p1().y() + (tableCells.dy() ? index : 0);
return QPoint(x, y);
inline QPoint cellAt(int index) {
return !m_edge || (m_edge & (Qt::LeftEdge | Qt::RightEdge))
? QPoint(m_edgeIndex, m_visibleCellsInEdge[index])
: QPoint(m_visibleCellsInEdge[index], m_edgeIndex);
}
};
class EdgeRange {
public:
EdgeRange();
bool containsIndex(Qt::Edge edge, int index);
int startIndex;
int endIndex;
qreal size;
};
enum class RebuildState {
Begin = 0,
LoadInitalTable,
@ -234,7 +241,6 @@ public:
TableEdgeLoadRequest loadRequest;
QPoint contentSizeBenchMarkPoint = QPoint(-1, -1);
QSizeF cellSpacing = QSizeF(0, 0);
QQmlTableInstanceModel::ReusableFlag reusableFlag = QQmlTableInstanceModel::Reusable;
@ -248,6 +254,10 @@ public:
QJSValue rowHeightProvider;
QJSValue columnWidthProvider;
EdgeRange cachedNextVisibleEdgeIndex[4];
EdgeRange cachedColumnWidth;
EdgeRange cachedRowHeight;
// TableView uses contentWidth/height to report the size of the table (this
// will e.g make scrollbars written for Flickable work out of the box). This
// value is continuously calculated, and will change/improve as more columns
@ -281,8 +291,13 @@ public:
qreal sizeHintForRow(int row);
void calculateTableSize();
qreal resolveColumnWidth(int column);
qreal resolveRowHeight(int row);
inline bool isColumnHidden(int column);
inline bool isRowHidden(int row);
qreal getColumnLayoutWidth(int column);
qreal getRowLayoutHeight(int row);
qreal getColumnWidth(int column);
qreal getRowHeight(int row);
inline int topRow() const { return loadedRows.firstKey(); }
inline int bottomRow() const { return loadedRows.lastKey(); }
@ -300,12 +315,16 @@ public:
void updateContentWidth();
void updateContentHeight();
void updateAverageEdgeSize();
void forceLayout();
void enforceTableAtOrigin();
void syncLoadedTableRectFromLoadedTable();
void syncLoadedTableFromLoadRequest();
int nextVisibleEdgeIndex(Qt::Edge edge, int startIndex);
int nextVisibleEdgeIndexAroundLoadedTable(Qt::Edge edge);
inline int edgeToArrayIndex(Qt::Edge edge);
void clearEdgeSizeCache();
bool canLoadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
bool canUnloadTableEdge(Qt::Edge tableEdge, const QRectF fillRect) const;
@ -316,7 +335,6 @@ public:
qreal cellHeight(const QPoint &cell);
FxTableItem *loadedTableItem(const QPoint &cell) const;
FxTableItem *itemNextTo(const FxTableItem *fxTableItem, const QPoint &direction) const;
FxTableItem *createFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode);
FxTableItem *loadFxTableItem(const QPoint &cell, QQmlIncubator::IncubationMode incubationMode);
@ -324,18 +342,17 @@ public:
void releaseLoadedItems(QQmlTableInstanceModel::ReusableFlag reusableFlag);
void unloadItem(const QPoint &cell);
void unloadItems(const QLine &items);
void loadInitialTopLeftItem(const QPoint &cell, const QPointF &pos);
void loadEdge(Qt::Edge edge, QQmlIncubator::IncubationMode incubationMode);
void unloadEdge(Qt::Edge edge);
void loadAndUnloadVisibleEdges();
void drainReusePoolAfterLoadRequest();
void cancelLoadRequest();
void processLoadRequest();
void processRebuildTable();
bool moveToNextRebuildState();
QPoint calculateNewTopLeft();
void calculateTopLeft(QPoint &topLeft, QPointF &topLeftPos);
void beginRebuildTable();
void layoutAfterLoadingInitialTable();

View File

@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2019 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
Item {
width: 640
height: 450
property alias tableView: tableView
property var rowsToHide
property var columnsToHide
TableView {
id: tableView
width: 600
height: 400
anchors.margins: 1
clip: true
delegate: tableViewDelegate
columnSpacing: 1
rowSpacing: 1
columnWidthProvider: function(column) {
if (columnsToHide.includes(column))
return 0;
}
rowHeightProvider: function(row) {
if (rowsToHide.includes(row))
return 0;
}
}
Component {
id: tableViewDelegate
Rectangle {
objectName: "tableViewDelegate"
color: "lightgray"
border.width: 1
implicitWidth: 50
implicitHeight: 50
Text {
anchors.centerIn: parent
text: column + "," + row
}
}
}
}

View File

@ -56,16 +56,14 @@ Item {
delegate: tableViewDelegate
columnSpacing: 1
rowSpacing: 1
columnWidthProvider: function(column) { }
rowHeightProvider: function(row) { return 0 }
columnWidthProvider: function(column) { return "notAValidValue" }
rowHeightProvider: function(row) { return "notAValidValue" }
}
Component {
id: tableViewDelegate
Rectangle {
objectName: "tableViewDelegate"
implicitWidth: 20
implicitHeight: 20
color: "lightgray"
border.width: 1
Text {

View File

@ -46,6 +46,8 @@ Item {
property alias tableView: tableView
property Component delegate: tableViewDelegate
property bool returnNegativeColumnWidth: false
property bool returnNegativeRowHeight: false
TableView {
id: tableView
@ -56,8 +58,16 @@ Item {
delegate: tableViewDelegate
columnSpacing: 1
rowSpacing: 1
columnWidthProvider: function(column) { return column + 10 }
rowHeightProvider: function(row) { return row + 10 }
columnWidthProvider: function(column) {
if (returnNegativeColumnWidth)
return -1
return column + 10
}
rowHeightProvider: function(row) {
if (returnNegativeRowHeight)
return -1
return row + 10
}
}
Component {

View File

@ -111,10 +111,12 @@ private slots:
void checkDelegateWithAnchors();
void checkColumnWidthProvider();
void checkColumnWidthProviderInvalidReturnValues();
void checkColumnWidthProviderNegativeReturnValue();
void checkColumnWidthProviderNotCallable();
void checkRowHeightWithoutProvider();
void checkRowHeightProvider();
void checkRowHeightProviderInvalidReturnValues();
void checkRowHeightProviderNegativeReturnValue();
void checkRowHeightProviderNotCallable();
void checkForceLayoutFunction();
void checkContentWidthAndHeight();
@ -157,6 +159,8 @@ private slots:
void checkRebuildViewportOnly();
void useDelegateChooserWithoutDefault();
void checkTableviewInsideAsyncLoader();
void hideRowsAndColumns_data();
void hideRowsAndColumns();
};
tst_QQuickTableView::tst_QQuickTableView()
@ -373,7 +377,7 @@ void tst_QQuickTableView::checkColumnWidthProviderInvalidReturnValues()
tableView->setModel(model);
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*Provider.*valid"));
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicitHeight.*zero"));
WAIT_UNTIL_POLISHED;
@ -381,6 +385,23 @@ void tst_QQuickTableView::checkColumnWidthProviderInvalidReturnValues()
QCOMPARE(fxItem->item->width(), kDefaultColumnWidth);
}
void tst_QQuickTableView::checkColumnWidthProviderNegativeReturnValue()
{
// Check that we fall back to use the implicit width of the delegate
// items if the columnWidthProvider return a negative number.
LOAD_TABLEVIEW("userowcolumnprovider.qml");
auto model = TestModelAsVariant(10, 10);
view->rootObject()->setProperty("returnNegativeColumnWidth", true);
tableView->setModel(model);
WAIT_UNTIL_POLISHED;
for (auto fxItem : tableViewPrivate->loadedItems)
QCOMPARE(fxItem->item->width(), 20);
}
void tst_QQuickTableView::checkColumnWidthProviderNotCallable()
{
// Check that we fall back to use default columns widths, if you
@ -453,7 +474,7 @@ void tst_QQuickTableView::checkRowHeightProviderInvalidReturnValues()
tableView->setModel(model);
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*Provider.*valid"));
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*implicitHeight.*zero"));
WAIT_UNTIL_POLISHED;
@ -461,6 +482,23 @@ void tst_QQuickTableView::checkRowHeightProviderInvalidReturnValues()
QCOMPARE(fxItem->item->height(), kDefaultRowHeight);
}
void tst_QQuickTableView::checkRowHeightProviderNegativeReturnValue()
{
// Check that we fall back to use the implicit height of the delegate
// items if the rowHeightProvider return a negative number.
LOAD_TABLEVIEW("userowcolumnprovider.qml");
auto model = TestModelAsVariant(10, 10);
view->rootObject()->setProperty("returnNegativeRowHeight", true);
tableView->setModel(model);
WAIT_UNTIL_POLISHED;
for (auto fxItem : tableViewPrivate->loadedItems)
QCOMPARE(fxItem->item->height(), 20);
}
void tst_QQuickTableView::checkRowHeightProviderNotCallable()
{
// Check that we fall back to use default row heights, if you
@ -538,6 +576,8 @@ void tst_QQuickTableView::checkContentWidthAndHeight()
const qreal expectedSizeInit = (tableSize * cellSizeSmall) + ((tableSize - 1) * spacing);
QCOMPARE(tableView->contentWidth(), expectedSizeInit);
QCOMPARE(tableView->contentHeight(), expectedSizeInit);
QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellSizeSmall);
QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellSizeSmall);
// 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
@ -548,6 +588,8 @@ void tst_QQuickTableView::checkContentWidthAndHeight()
QCOMPARE(tableView->contentWidth(), expectedSizeInit);
QCOMPARE(tableView->contentHeight(), expectedSizeInit);
QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellSizeSmall);
QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellSizeSmall);
// Flick to row and column 20 (smallCellCount), since there the row and
// column sizes increases with 100. Check that TableView then adjusts
@ -562,6 +604,11 @@ void tst_QQuickTableView::checkContentWidthAndHeight()
QVERIFY(tableViewPrivate->rebuildScheduled);
WAIT_UNTIL_POLISHED;
// Check that the average cell size is now matching the
// large cells since they fill up the whole view.
QCOMPARE(tableViewPrivate->averageEdgeSize.width(), cellSizeLarge);
QCOMPARE(tableViewPrivate->averageEdgeSize.height(), cellSizeLarge);
const int largeSizeCellCountInView = qCeil(tableView->width() / cellSizeLarge);
const int columnCount = smallCellCount + largeSizeCellCountInView;
QCOMPARE(tableViewPrivate->leftColumn(), smallCellCount);
@ -571,41 +618,47 @@ void tst_QQuickTableView::checkContentWidthAndHeight()
const qreal secondHalfOneScreenLength = largeSizeCellCountInView * cellSizeLarge;
const qreal lengthAfterFlick = firstHalfLength + secondHalfOneScreenLength;
const qreal averageCellSize = lengthAfterFlick / columnCount;
const qreal expectedSizeHalf = (tableSize * averageCellSize) + accumulatedSpacing;
// Check that loadedTableOuterRect has been calculated correct thus far
const qreal spacingAfterFlick = (smallCellCount + largeSizeCellCountInView - 1) * spacing;
QCOMPARE(tableViewPrivate->loadedTableOuterRect.left(), flickTo + spacing);
QCOMPARE(tableViewPrivate->loadedTableOuterRect.right(), lengthAfterFlick + spacingAfterFlick);
QCOMPARE(tableViewPrivate->loadedTableOuterRect.top(), flickTo + spacing);
QCOMPARE(tableViewPrivate->loadedTableOuterRect.bottom(), lengthAfterFlick + spacingAfterFlick);
QCOMPARE(tableView->contentWidth(), expectedSizeHalf);
QCOMPARE(tableView->contentHeight(), expectedSizeHalf);
// At this point, we should have the exact content width/height set, because
// TableView knows where the large cells start in the viewport, and how many
// columns that remain in the model. It will assume that the rest of the the
// columns have the same average size as the ones currently inside the viewport.
const qreal expectedContentSize = (smallCellCount * cellSizeSmall) + (largeCellCount * cellSizeLarge) + accumulatedSpacing;
QCOMPARE(tableView->contentWidth(), expectedContentSize);
QCOMPARE(tableView->contentHeight(), expectedContentSize);
// 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) + accumulatedSpacing;
// If we flick more than one page at a time, tableview will jump to the new
// position and rebuild the table without loading the edges in-between. Which
// row and column that ends up as new top-left is then based on a prediction, and
// therefore unreliable. To avoid this to happen (which will also affect the
// reported size of the table), we flick to the end position in smaller chuncks.
QVERIFY(!tableViewPrivate->polishScheduled);
QVERIFY(!tableViewPrivate->rebuildScheduled);
int pages = qCeil((expectedFullSize - tableView->contentX()) / tableView->width());
for (int i = 0; i < pages; i++) {
tableView->setContentX(tableView->contentX() + tableView->width() - 1);
tableView->setContentY(tableView->contentY() + tableView->height() - 1);
QVERIFY(!tableViewPrivate->rebuildScheduled);
}
const qreal overshoot = 100;
const qreal endPosX = expectedFullSize - tableView->width() + overshoot;
const qreal endPosY = expectedFullSize - tableView->height() + overshoot;
tableView->setContentX(endPosX);
tableView->setContentY(endPosY);
QCOMPARE(tableView->contentWidth(), expectedFullSize);
QCOMPARE(tableView->contentHeight(), expectedFullSize);
// Flick back to start. Since we know the actual table
// size, contentWidth/Height shouldn't change.
// Flick back to start
tableView->setContentX(0);
tableView->setContentY(0);
QCOMPARE(tableView->contentWidth(), expectedFullSize);
QCOMPARE(tableView->contentHeight(), expectedFullSize);
// Since we move the viewport more than a page, tableview
// will jump to the new position and do a rebuild.
QVERIFY(tableViewPrivate->polishScheduled);
QVERIFY(tableViewPrivate->rebuildScheduled);
WAIT_UNTIL_POLISHED;
// We should now have the same content width/height as when we started
QCOMPARE(tableView->contentWidth(), expectedSizeInit);
QCOMPARE(tableView->contentHeight(), expectedSizeInit);
}
void tst_QQuickTableView::checkPageFlicking()
@ -2001,6 +2054,92 @@ void tst_QQuickTableView::checkTableviewInsideAsyncLoader()
QVERIFY(height > 0);
};
#define INT_LIST(indices) QVariant::fromValue(QList<int>() << indices)
void tst_QQuickTableView::hideRowsAndColumns_data()
{
QTest::addColumn<QVariant>("rowsToHide");
QTest::addColumn<QVariant>("columnsToHide");
const auto emptyList = QVariant::fromValue(QList<int>());
// Hide rows
QTest::newRow("first") << INT_LIST(0) << emptyList;
QTest::newRow("middle 1") << INT_LIST(1) << emptyList;
QTest::newRow("middle 3") << INT_LIST(3) << emptyList;
QTest::newRow("last") << INT_LIST(4) << emptyList;
QTest::newRow("subsequent 0,1") << INT_LIST(0 << 1) << emptyList;
QTest::newRow("subsequent 1,2") << INT_LIST(1 << 2) << emptyList;
QTest::newRow("subsequent 3,4") << INT_LIST(3 << 4) << emptyList;
QTest::newRow("all but first") << INT_LIST(1 << 2 << 3 << 4) << emptyList;
QTest::newRow("all but last") << INT_LIST(0 << 1 << 2 << 3) << emptyList;
QTest::newRow("all but middle") << INT_LIST(0 << 1 << 3 << 4) << emptyList;
// Hide columns
QTest::newRow("first") << emptyList << INT_LIST(0);
QTest::newRow("middle 1") << emptyList << INT_LIST(1);
QTest::newRow("middle 3") << emptyList << INT_LIST(3);
QTest::newRow("last") << emptyList << INT_LIST(4);
QTest::newRow("subsequent 0,1") << emptyList << INT_LIST(0 << 1);
QTest::newRow("subsequent 1,2") << emptyList << INT_LIST(1 << 2);
QTest::newRow("subsequent 3,4") << emptyList << INT_LIST(3 << 4);
QTest::newRow("all but first") << emptyList << INT_LIST(1 << 2 << 3 << 4);
QTest::newRow("all but last") << emptyList << INT_LIST(0 << 1 << 2 << 3);
QTest::newRow("all but middle") << emptyList << INT_LIST(0 << 1 << 3 << 4);
// Hide both rows and columns at the same time
QTest::newRow("first") << INT_LIST(0) << INT_LIST(0);
QTest::newRow("middle 1") << INT_LIST(1) << INT_LIST(1);
QTest::newRow("middle 3") << INT_LIST(3) << INT_LIST(3);
QTest::newRow("last") << INT_LIST(4) << INT_LIST(4);
QTest::newRow("subsequent 0,1") << INT_LIST(0 << 1) << INT_LIST(0 << 1);
QTest::newRow("subsequent 1,2") << INT_LIST(1 << 2) << INT_LIST(1 << 2);
QTest::newRow("subsequent 3,4") << INT_LIST(3 << 4) << INT_LIST(3 << 4);
QTest::newRow("all but first") << INT_LIST(1 << 2 << 3 << 4) << INT_LIST(1 << 2 << 3 << 4);
QTest::newRow("all but last") << INT_LIST(0 << 1 << 2 << 3) << INT_LIST(0 << 1 << 2 << 3);
QTest::newRow("all but middle") << INT_LIST(0 << 1 << 3 << 4) << INT_LIST(0 << 1 << 3 << 4);
// Hide all rows and columns
QTest::newRow("all") << INT_LIST(0 << 1 << 2 << 3 << 4) << INT_LIST(0 << 1 << 2 << 3 << 4);
}
void tst_QQuickTableView::hideRowsAndColumns()
{
// Check that you can hide the first row (corner case)
// and that we load the other columns as expected.
QFETCH(QVariant, rowsToHide);
QFETCH(QVariant, columnsToHide);
LOAD_TABLEVIEW("hiderowsandcolumns.qml");
const QList<int> rowsToHideList = qvariant_cast<QList<int>>(rowsToHide);
const QList<int> columnsToHideList = qvariant_cast<QList<int>>(columnsToHide);
const int modelSize = 5;
auto model = TestModelAsVariant(modelSize, modelSize);
view->rootObject()->setProperty("rowsToHide", rowsToHide);
view->rootObject()->setProperty("columnsToHide", columnsToHide);
tableView->setModel(model);
WAIT_UNTIL_POLISHED;
const int expectedRowCount = modelSize - rowsToHideList.count();
const int expectedColumnCount = modelSize - columnsToHideList.count();
QCOMPARE(tableViewPrivate->loadedRows.count(), expectedRowCount);
QCOMPARE(tableViewPrivate->loadedColumns.count(), expectedColumnCount);
for (const int row : tableViewPrivate->loadedRows.keys())
QVERIFY(!rowsToHideList.contains(row));
for (const int column : tableViewPrivate->loadedColumns.keys())
QVERIFY(!columnsToHideList.contains(column));
}
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"