2022-05-13 13:12:05 +00:00
|
|
|
// Copyright (C) 2021 The Qt Company Ltd.
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
2021-11-19 15:58:36 +00:00
|
|
|
|
|
|
|
#include <QtTest/QtTest>
|
|
|
|
#include <QtQuickTest/quicktest.h>
|
|
|
|
|
|
|
|
#include <QtQuick/qquickview.h>
|
|
|
|
#include <QtQuick/private/qquicktreeview_p.h>
|
|
|
|
#include <QtQuick/private/qquicktreeview_p_p.h>
|
|
|
|
|
|
|
|
#include <QtQml/qqmlengine.h>
|
|
|
|
#include <QtQml/qqmlcontext.h>
|
|
|
|
#include <QtQml/qqmlexpression.h>
|
|
|
|
#include <QtQml/qqmlincubator.h>
|
|
|
|
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
|
|
|
|
#include <QtQmlModels/private/qqmllistmodel_p.h>
|
|
|
|
|
|
|
|
#include "testmodel.h"
|
|
|
|
|
|
|
|
#include <QtQuickTestUtils/private/qmlutils_p.h>
|
|
|
|
#include <QtQuickTestUtils/private/viewtestutils_p.h>
|
|
|
|
#include <QtQuickTestUtils/private/visualtestutils_p.h>
|
|
|
|
|
|
|
|
using namespace QQuickViewTestUtils;
|
|
|
|
using namespace QQuickVisualTestUtils;
|
|
|
|
|
2022-11-09 15:51:38 +00:00
|
|
|
using namespace Qt::StringLiterals;
|
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
#define LOAD_TREEVIEW(fileName) \
|
|
|
|
view->setSource(testFileUrl(fileName)); \
|
|
|
|
view->show(); \
|
2022-11-30 13:56:37 +00:00
|
|
|
view->requestActivate(); \
|
2021-11-19 15:58:36 +00:00
|
|
|
QVERIFY(QTest::qWaitForWindowActive(view)); \
|
|
|
|
auto treeView = view->rootObject()->property("treeView").value<QQuickTreeView *>(); \
|
|
|
|
QVERIFY(treeView); \
|
|
|
|
auto treeViewPrivate = QQuickTreeViewPrivate::get(treeView); \
|
|
|
|
Q_UNUSED(treeViewPrivate) \
|
|
|
|
auto model = treeView->model().value<TestModel *>(); \
|
|
|
|
Q_UNUSED(model)
|
|
|
|
|
|
|
|
#define WAIT_UNTIL_POLISHED_ARG(item) \
|
|
|
|
QVERIFY(QQuickTest::qIsPolishScheduled(item)); \
|
2021-06-19 09:30:54 +00:00
|
|
|
QVERIFY(QQuickTest::qWaitForPolish(item))
|
2021-11-19 15:58:36 +00:00
|
|
|
#define WAIT_UNTIL_POLISHED WAIT_UNTIL_POLISHED_ARG(treeView)
|
|
|
|
|
|
|
|
// ########################################################
|
|
|
|
|
|
|
|
class tst_qquicktreeview : public QQmlDataTest
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
tst_qquicktreeview();
|
|
|
|
|
|
|
|
private:
|
|
|
|
QQuickView *view = nullptr;
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void initTestCase() override;
|
|
|
|
void showTreeView();
|
2022-01-21 15:01:53 +00:00
|
|
|
void invalidArguments();
|
2021-11-19 15:58:36 +00:00
|
|
|
void expandAndCollapseRoot();
|
|
|
|
void toggleExpanded();
|
|
|
|
void expandAndCollapseChildren();
|
2022-01-17 16:02:06 +00:00
|
|
|
void expandChildPendingToBeVisible();
|
2022-01-21 15:01:53 +00:00
|
|
|
void expandRecursivelyRoot_data();
|
|
|
|
void expandRecursivelyRoot();
|
|
|
|
void expandRecursivelyChild_data();
|
|
|
|
void expandRecursivelyChild();
|
|
|
|
void expandRecursivelyWholeTree();
|
2022-02-01 13:51:30 +00:00
|
|
|
void collapseRecursivelyRoot();
|
|
|
|
void collapseRecursivelyChild();
|
|
|
|
void collapseRecursivelyWholeTree();
|
2022-02-07 10:00:21 +00:00
|
|
|
void expandToIndex();
|
2021-11-19 15:58:36 +00:00
|
|
|
void requiredPropertiesRoot();
|
|
|
|
void requiredPropertiesChildren();
|
|
|
|
void emptyModel();
|
|
|
|
void updatedModifiedModel();
|
|
|
|
void insertRows();
|
2022-04-07 08:07:28 +00:00
|
|
|
void toggleExpandedUsingArrowKeys();
|
2022-11-30 13:56:37 +00:00
|
|
|
void expandAndCollapsUsingDoubleClick();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
void selectionBehaviorCells_data();
|
|
|
|
void selectionBehaviorCells();
|
|
|
|
void selectionBehaviorRows();
|
|
|
|
void selectionBehaviorColumns();
|
|
|
|
void selectionBehaviorDisabled();
|
2022-10-17 12:11:48 +00:00
|
|
|
void sortTreeModel_data();
|
|
|
|
void sortTreeModel();
|
|
|
|
void sortTreeModelDynamic_data();
|
|
|
|
void sortTreeModelDynamic();
|
2021-11-19 15:58:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
tst_qquicktreeview::tst_qquicktreeview()
|
|
|
|
: QQmlDataTest(QT_QMLTEST_DATADIR)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::initTestCase()
|
|
|
|
{
|
|
|
|
QQmlDataTest::initTestCase();
|
|
|
|
qmlRegisterType<TestModel>("TestModel", 1, 0, "TestModel");
|
|
|
|
view = createView();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::showTreeView()
|
|
|
|
{
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
// Check that the view is showing the root of the tree
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
}
|
|
|
|
|
2022-01-21 15:01:53 +00:00
|
|
|
|
|
|
|
void tst_qquicktreeview::invalidArguments()
|
|
|
|
{
|
|
|
|
// Check that we handle gracefully invalid arguments
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
treeView->expand(-2);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
treeView->expandRecursively(200);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
treeView->expandRecursively(-2);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
treeView->expandRecursively(200);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
2022-02-01 13:51:30 +00:00
|
|
|
|
|
|
|
treeView->collapse(-2);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
treeView->collapseRecursively(200);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
treeView->collapseRecursively(-2);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
treeView->collapseRecursively(200);
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
}
|
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
void tst_qquicktreeview::expandAndCollapseRoot()
|
|
|
|
{
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
// Check that the view only has one row loaded so far (the root of the tree)
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
|
2022-01-21 15:01:53 +00:00
|
|
|
QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int, int)));
|
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
// Expand the root
|
|
|
|
treeView->expand(0);
|
2022-01-21 15:01:53 +00:00
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(expandedSpy.size(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
auto signalArgs = expandedSpy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == 0);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == 1);
|
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We now expect 5 rows, the root pluss it's 4 children
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
|
|
|
|
treeView->collapse(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// Check that the view only has one row loaded again (the root of the tree)
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::toggleExpanded()
|
|
|
|
{
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
// Check that the view only has one row loaded so far (the root of the tree)
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
|
|
|
|
// Expand the root
|
|
|
|
treeView->toggleExpanded(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We now expect 5 rows, the root pluss it's 4 children
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
|
|
|
|
treeView->toggleExpanded(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// Check that the view only has one row loaded again (the root of the tree)
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::expandAndCollapseChildren()
|
|
|
|
{
|
|
|
|
// Check that we can expand and collapse children, and that
|
|
|
|
// the tree ends up with the expected rows
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
const int childCount = 4;
|
2022-01-21 15:01:53 +00:00
|
|
|
QSignalSpy expandedSpy(treeView, SIGNAL(expanded(int, int)));
|
2021-11-19 15:58:36 +00:00
|
|
|
|
|
|
|
// Expand the last child of a parent recursively four times
|
|
|
|
for (int level = 0; level < 4; ++level) {
|
|
|
|
const int nodeToExpand = level * childCount;
|
|
|
|
const int firstChildRow = nodeToExpand + 1; // (+ 1 for the root)
|
|
|
|
const int lastChildRow = firstChildRow + 4;
|
2022-01-21 15:01:53 +00:00
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
treeView->expand(nodeToExpand);
|
2022-01-21 15:01:53 +00:00
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(expandedSpy.size(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
auto signalArgs = expandedSpy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == nodeToExpand);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == 1);
|
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
WAIT_UNTIL_POLISHED;
|
2022-01-21 15:01:53 +00:00
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
QCOMPARE(treeView->rows(), lastChildRow);
|
|
|
|
|
|
|
|
auto childItem1 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow))->item;
|
|
|
|
QCOMPARE(childItem1->property("text").toString(), "0, 0");
|
|
|
|
auto childItem2 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow + 1))->item;
|
|
|
|
QCOMPARE(childItem2->property("text").toString(), "1, 0");
|
|
|
|
auto childItem3 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow + 2))->item;
|
|
|
|
QCOMPARE(childItem3->property("text").toString(), "2, 0");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collapse down from level 2 (deliberatly not mirroring the expansion by
|
|
|
|
// instead collapsing both level 3 and 4 in one go)
|
|
|
|
for (int level = 2; level > 0; --level) {
|
|
|
|
const int nodeToCollapse = level * childCount;
|
|
|
|
const int firstChildRow = nodeToCollapse - childCount + 1;
|
|
|
|
const int lastChildRow = nodeToCollapse + 1; // (+ 1 for the root)
|
|
|
|
|
|
|
|
treeView->collapse(nodeToCollapse);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
QCOMPARE(treeView->rows(), lastChildRow);
|
|
|
|
|
|
|
|
auto childItem1 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow))->item;
|
|
|
|
QCOMPARE(childItem1->property("text").toString(), "0, 0");
|
|
|
|
auto childItem2 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow + 1))->item;
|
|
|
|
QCOMPARE(childItem2->property("text").toString(), "1, 0");
|
|
|
|
auto childItem3 = treeViewPrivate->loadedTableItem(QPoint(0, firstChildRow + 2))->item;
|
|
|
|
QCOMPARE(childItem3->property("text").toString(), "2, 0");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Collapse the root
|
|
|
|
treeView->collapse(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::requiredPropertiesRoot()
|
|
|
|
{
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
|
|
|
|
const auto rootFxItem = treeViewPrivate->loadedTableItem(QPoint(0, 0));
|
|
|
|
QVERIFY(rootFxItem);
|
|
|
|
const auto rootItem = rootFxItem->item;
|
|
|
|
QVERIFY(rootItem);
|
|
|
|
|
|
|
|
const auto context = qmlContext(rootItem.data());
|
|
|
|
const auto viewProp = context->contextProperty("treeView").value<QQuickTreeView *>();
|
|
|
|
const auto isTreeNode = context->contextProperty("isTreeNode").toBool();
|
|
|
|
const auto expanded = context->contextProperty("expanded").toBool();
|
|
|
|
const auto hasChildren = context->contextProperty("hasChildren").toBool();
|
|
|
|
const auto depth = context->contextProperty("depth").toInt();
|
|
|
|
|
|
|
|
QCOMPARE(viewProp, treeView);
|
|
|
|
QCOMPARE(isTreeNode, true);
|
|
|
|
QCOMPARE(expanded, false);
|
|
|
|
QCOMPARE(hasChildren, true);
|
|
|
|
QCOMPARE(depth, 0);
|
|
|
|
|
|
|
|
treeView->expand(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
const auto isExpandedAfterExpand = context->contextProperty("expanded").toBool();
|
|
|
|
QCOMPARE(isExpandedAfterExpand, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::requiredPropertiesChildren()
|
|
|
|
{
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->expand(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We now expect 5 rows, the root pluss it's 4 children
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
|
|
|
|
// The last child has it's own children, so expand that one as well
|
|
|
|
const auto rootIndex = model->index(0, 0);
|
|
|
|
const int childCount = model->rowCount(rootIndex);
|
|
|
|
QCOMPARE(childCount, 4);
|
|
|
|
const auto lastChildIndex = model->index(childCount - 1, 0, rootIndex);
|
|
|
|
QVERIFY(lastChildIndex.isValid());
|
|
|
|
QCOMPARE(model->hasChildren(lastChildIndex), true);
|
|
|
|
|
|
|
|
treeView->expand(4);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We now expect root + 4 children + 4 children = 9 rows
|
|
|
|
const int rowCount = treeViewPrivate->loadedRows.count();
|
|
|
|
QCOMPARE(rowCount, 9);
|
|
|
|
|
|
|
|
// Go through all rows in the view, except the root
|
|
|
|
for (int row = 1; row < rowCount; ++row) {
|
|
|
|
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
|
|
|
|
QVERIFY(childFxItem);
|
|
|
|
const auto childItem = childFxItem->item;
|
|
|
|
QVERIFY(childItem);
|
|
|
|
|
|
|
|
const auto context = qmlContext(childItem.data());
|
|
|
|
const auto viewProp = context->contextProperty("treeView").value<QQuickTreeView *>();
|
|
|
|
const auto isTreeNode = context->contextProperty("isTreeNode").toBool();
|
|
|
|
const auto expanded = context->contextProperty("expanded").toBool();
|
|
|
|
const auto hasChildren = context->contextProperty("hasChildren").toBool();
|
|
|
|
const auto depth = context->contextProperty("depth").toInt();
|
|
|
|
|
|
|
|
QCOMPARE(viewProp, treeView);
|
|
|
|
QCOMPARE(isTreeNode, true);
|
|
|
|
QCOMPARE(expanded, row == 4);
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
QCOMPARE(hasChildren, model->hasChildren(treeView->index(row, 0)));
|
2021-11-19 15:58:36 +00:00
|
|
|
QCOMPARE(depth, row <= 4 ? 1 : 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::emptyModel()
|
|
|
|
{
|
|
|
|
// Check that you can assign an empty model, and that
|
|
|
|
// calling functions will work as expected (and at least not crash)
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->setModel(QVariant());
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(treeViewPrivate->loadedItems.size(), 0);
|
2021-11-19 15:58:36 +00:00
|
|
|
QCOMPARE(treeView->rows(), 0);
|
|
|
|
QCOMPARE(treeView->columns(), 0);
|
|
|
|
|
|
|
|
// Check that we don't crash:
|
|
|
|
treeView->expand(10);
|
|
|
|
treeView->collapse(5);
|
|
|
|
|
|
|
|
QCOMPARE(treeView->depth(0), -1);
|
|
|
|
QCOMPARE(treeView->isExpanded(0), false);
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
QVERIFY(!treeView->index(10, 10).isValid());
|
2021-11-19 15:58:36 +00:00
|
|
|
QCOMPARE(treeView->rowAtIndex(QModelIndex()), -1);
|
|
|
|
QCOMPARE(treeView->columnAtIndex(QModelIndex()), -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::updatedModifiedModel()
|
|
|
|
{
|
|
|
|
// Check that if we change the data in the model, the
|
|
|
|
// delegate items get updated.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->expand(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We now expect 5 rows, the root plus it's 4 children
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
|
|
|
|
auto rootFxItem = treeViewPrivate->loadedTableItem(QPoint(0, 0));
|
|
|
|
QVERIFY(rootFxItem);
|
|
|
|
auto rootItem = rootFxItem->item;
|
|
|
|
QVERIFY(rootItem);
|
|
|
|
QCOMPARE(rootItem->property("text"), "0, 0");
|
|
|
|
model->setData(model->index(0, 0), QVariant(QString("Changed")));
|
|
|
|
QCOMPARE(rootItem->property("text"), "Changed");
|
|
|
|
|
|
|
|
auto rootFxItemCol1 = treeViewPrivate->loadedTableItem(QPoint(1, 2));
|
|
|
|
QVERIFY(rootFxItemCol1);
|
|
|
|
auto rootItemCol1 = rootFxItemCol1->item;
|
|
|
|
QVERIFY(rootItemCol1);
|
|
|
|
QCOMPARE(rootItemCol1->property("text"), "1, 1");
|
|
|
|
model->setData(model->index(1, 1, model->index(0,0)), QVariant(QString("Changed")));
|
|
|
|
QCOMPARE(rootItemCol1->property("text"), "Changed");
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::insertRows()
|
|
|
|
{
|
|
|
|
// Check that if we add new rows to the model, TreeView gets updated
|
|
|
|
// to contain the new expected number of rows (flattened to a list)
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->expand(0);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(treeView->rows(), 5);
|
|
|
|
|
|
|
|
const QModelIndex rootNode = model->index(0, 0, QModelIndex());
|
|
|
|
model->insertRows(0, 2, rootNode);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(treeView->rows(), 7);
|
|
|
|
auto childItem1 = treeViewPrivate->loadedTableItem(QPoint(0, 1))->item;
|
|
|
|
QCOMPARE(childItem1->property("text").toString(), "0, 0 (inserted)");
|
|
|
|
auto childItem2 = treeViewPrivate->loadedTableItem(QPoint(0, 2))->item;
|
|
|
|
QCOMPARE(childItem2->property("text").toString(), "1, 0 (inserted)");
|
|
|
|
auto childItem3 = treeViewPrivate->loadedTableItem(QPoint(0, 3))->item;
|
|
|
|
QCOMPARE(childItem3->property("text").toString(), "0, 0");
|
|
|
|
|
|
|
|
const QModelIndex indexOfInsertedChild = model->index(1, 0, rootNode);
|
|
|
|
model->insertRows(0, 2, indexOfInsertedChild);
|
|
|
|
treeView->expand(2);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(treeView->rows(), 9);
|
|
|
|
}
|
|
|
|
|
2022-01-17 16:02:06 +00:00
|
|
|
void tst_qquicktreeview::expandChildPendingToBeVisible()
|
|
|
|
{
|
|
|
|
// Check that if we expand a row r1, and that row has a child r2 that can
|
|
|
|
// be expanded, we can continue to expand c2 immediately, even if r1 is
|
|
|
|
// still pending to be shown as expanded in the view.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->expand(0);
|
|
|
|
QVERIFY(treeView->isExpanded(0));
|
|
|
|
// The view has not yet been updated at this point to show
|
|
|
|
// the newly expanded children, so it still has only one row.
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
// ...but we still expand row 5, which is a child that has children
|
|
|
|
// in the proxy model
|
|
|
|
treeView->expand(4);
|
|
|
|
QVERIFY(treeView->isExpanded(4));
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
// Now the view have updated to show
|
|
|
|
// all the rows that has been expanded.
|
2022-01-21 15:01:53 +00:00
|
|
|
QCOMPARE(treeView->rows(), 9);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::expandRecursivelyRoot_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<int>("rowToExpand");
|
|
|
|
QTest::addColumn<int>("depth");
|
|
|
|
|
|
|
|
QTest::newRow("0, -1") << 0 << -1;
|
|
|
|
QTest::newRow("0, 0") << 0 << 0;
|
|
|
|
QTest::newRow("0, 1") << 0 << 1;
|
|
|
|
QTest::newRow("0, 2") << 0 << 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::expandRecursivelyRoot()
|
|
|
|
{
|
|
|
|
// Check that we can expand the root node (row 0), and that
|
|
|
|
// all its children are expanded recursively down to the
|
|
|
|
// given depth.
|
|
|
|
QFETCH(int, rowToExpand);
|
|
|
|
QFETCH(int, depth);
|
|
|
|
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
|
|
|
|
|
|
|
|
treeView->expandRecursively(rowToExpand, depth);
|
|
|
|
|
|
|
|
if (depth == 0) {
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 0);
|
2022-01-21 15:01:53 +00:00
|
|
|
} else {
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
const auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == rowToExpand);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
const int rowToExpandDepth = treeView->depth(rowToExpand);
|
|
|
|
const int effectiveMaxDepth = depth != -1 ? rowToExpandDepth + depth : model->maxDepth();
|
|
|
|
|
|
|
|
if (depth > 0 || depth == -1)
|
|
|
|
QVERIFY(treeView->isExpanded(rowToExpand));
|
|
|
|
else
|
|
|
|
QVERIFY(!treeView->isExpanded(rowToExpand));
|
|
|
|
|
|
|
|
// Check that all rows after rowToExpand, that are also
|
|
|
|
// children of that row, is expanded (down to depth)
|
|
|
|
for (int currentRow = rowToExpand + 1; currentRow < treeView->rows(); ++currentRow) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto modelIndex = treeView->index(currentRow, 0);
|
2022-01-21 15:01:53 +00:00
|
|
|
const int currentDepth = treeView->depth(currentRow);
|
|
|
|
const bool isChild = currentDepth > rowToExpandDepth;
|
|
|
|
const bool isExpandable = model->rowCount(modelIndex) > 0;
|
|
|
|
const bool shouldBeExpanded = isChild && isExpandable && currentDepth < effectiveMaxDepth;
|
|
|
|
QCOMPARE(treeView->isExpanded(currentRow), shouldBeExpanded);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::expandRecursivelyChild_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<int>("rowToExpand");
|
|
|
|
QTest::addColumn<int>("depth");
|
|
|
|
|
|
|
|
QTest::newRow("5, -1") << 4 << -1;
|
|
|
|
QTest::newRow("5, 0") << 4 << 0;
|
|
|
|
QTest::newRow("5, 1") << 4 << 1;
|
|
|
|
QTest::newRow("5, 2") << 4 << 2;
|
|
|
|
QTest::newRow("5, 3") << 4 << 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::expandRecursivelyChild()
|
|
|
|
{
|
|
|
|
// Check that we can first expand the root node, and the expand
|
|
|
|
// recursive the first child node with children (row 4), and that all
|
|
|
|
// its children of that node are expanded recursively according to depth.
|
|
|
|
QFETCH(int, rowToExpand);
|
|
|
|
QFETCH(int, depth);
|
|
|
|
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
|
|
|
|
|
|
|
|
treeView->expand(0);
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == 0);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == 1);
|
|
|
|
|
|
|
|
treeView->expandRecursively(rowToExpand, depth);
|
|
|
|
|
|
|
|
if (depth == 0) {
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 0);
|
2022-01-21 15:01:53 +00:00
|
|
|
} else {
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == rowToExpand);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
const bool rowToExpandDepth = treeView->depth(rowToExpand);
|
|
|
|
const int effectiveMaxDepth = depth != -1 ? rowToExpandDepth + depth : model->maxDepth();
|
|
|
|
|
2022-10-17 12:11:48 +00:00
|
|
|
// Check that none of the rows before rowToExpand are expanded
|
2022-01-21 15:01:53 +00:00
|
|
|
// (except the root node)
|
|
|
|
for (int currentRow = 1; currentRow < rowToExpand; ++currentRow)
|
|
|
|
QVERIFY(!treeView->isExpanded(currentRow));
|
|
|
|
|
|
|
|
// Check if rowToExpand is expanded
|
|
|
|
if (depth > 0 || depth == -1)
|
|
|
|
QVERIFY(treeView->isExpanded(rowToExpand));
|
|
|
|
else
|
|
|
|
QVERIFY(!treeView->isExpanded(rowToExpand));
|
|
|
|
|
2022-10-17 12:11:48 +00:00
|
|
|
// Check that any row after rowToExpand, that is also
|
|
|
|
// a child of that row, is expanded (down to depth)
|
2022-01-21 15:01:53 +00:00
|
|
|
for (int currentRow = rowToExpand + 1; currentRow < treeView->rows(); ++currentRow) {
|
|
|
|
const int currentDepth = treeView->depth(currentRow);
|
|
|
|
const bool isChild = currentDepth > rowToExpandDepth;
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto modelIndex = treeView->index(currentRow, 0);
|
2022-01-21 15:01:53 +00:00
|
|
|
const bool isExpandable = model->rowCount(modelIndex) > 0;
|
|
|
|
const bool shouldBeExpanded = isChild && isExpandable && currentDepth < effectiveMaxDepth;
|
|
|
|
QCOMPARE(treeView->isExpanded(currentRow), shouldBeExpanded);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::expandRecursivelyWholeTree()
|
|
|
|
{
|
|
|
|
// Check that we expand the whole tree recursively by passing -1, -1
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
|
|
|
|
treeView->expandRecursively(-1, -1);
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-01-21 15:01:53 +00:00
|
|
|
auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == -1);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == -1);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
// Check that all rows that have children are expanded
|
|
|
|
for (int currentRow = 0; currentRow < treeView->rows(); ++currentRow) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto modelIndex = treeView->index(currentRow, 0);
|
2022-01-21 15:01:53 +00:00
|
|
|
const bool isExpandable = model->rowCount(modelIndex) > 0;
|
|
|
|
QCOMPARE(treeView->isExpanded(currentRow), isExpandable);
|
|
|
|
}
|
2022-01-17 16:02:06 +00:00
|
|
|
}
|
|
|
|
|
2022-02-01 13:51:30 +00:00
|
|
|
void tst_qquicktreeview::collapseRecursivelyRoot()
|
|
|
|
{
|
|
|
|
// Check that we can collapse the root node (row 0), and that
|
|
|
|
// all its children are collapsed recursively down to the leaves.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->expandRecursively();
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
// Verify that the tree is now fully expanded
|
2022-10-17 12:11:48 +00:00
|
|
|
// The number of rows should be the root, + 4 children per level. All parents
|
|
|
|
// (minus the root), will also have a node with 4 non-recursive children.
|
|
|
|
const int expectedRowCount = 1 + (model->maxDepth() * 8) - 4;
|
2022-02-01 13:51:30 +00:00
|
|
|
QCOMPARE(treeView->rows(), expectedRowCount);
|
|
|
|
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
|
|
|
|
|
|
|
|
// Collapse the whole tree again. This time, only the root should end up visible
|
|
|
|
treeView->collapseRecursively();
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-02-01 13:51:30 +00:00
|
|
|
const auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == -1);
|
|
|
|
QVERIFY(signalArgs.at(1).toBool() == true);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
|
|
|
|
// We need to check that all descendants are collapsed as well. But since they're
|
|
|
|
// now no longer visible in the view, we need to expand each parent one by one again to make
|
|
|
|
// them visible, and check that the child inside that has children is still collapsed.
|
|
|
|
// We can do that by simply iterate over the rows in the view as we expand.
|
|
|
|
int currentRow = 0;
|
|
|
|
while (currentRow < treeView->rows()) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const QModelIndex currentIndex = treeView->index(currentRow, 0);
|
2022-02-01 13:51:30 +00:00
|
|
|
if (model->hasChildren(currentIndex)) {
|
|
|
|
QVERIFY(!treeView->isExpanded(currentRow));
|
|
|
|
treeView->expand(currentRow);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
}
|
|
|
|
currentRow++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sanity check that we ended up with all rows expanded again
|
|
|
|
QCOMPARE(currentRow, expectedRowCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::collapseRecursivelyChild()
|
|
|
|
{
|
|
|
|
// Check that we can collapse a child node (row 4), and that all its children
|
|
|
|
// are collapsed recursively down to the leaves (without touching the root).
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
treeView->expandRecursively();
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
// Verify that the tree is now fully expanded
|
2022-10-17 12:11:48 +00:00
|
|
|
// The number of rows should be the root, + 4 children per level. All parents
|
|
|
|
// (minus the root), will also have a node with 4 non-recursive children.
|
|
|
|
const int expectedRowCount = 1 + (model->maxDepth() * 8) - 4;
|
2022-02-01 13:51:30 +00:00
|
|
|
QCOMPARE(treeView->rows(), expectedRowCount);
|
|
|
|
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
|
|
|
|
|
2022-10-17 12:11:48 +00:00
|
|
|
// Collapse the 8th child recursive
|
|
|
|
const int rowToCollapse = 8;
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const QModelIndex collapseIndex = treeView->index(rowToCollapse, 0);
|
2022-10-17 12:11:48 +00:00
|
|
|
const auto expectedLabel = model->data(collapseIndex, Qt::DisplayRole);
|
|
|
|
QCOMPARE(expectedLabel, QStringLiteral("3, 0"));
|
2022-02-01 13:51:30 +00:00
|
|
|
treeView->collapseRecursively(rowToCollapse);
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-02-01 13:51:30 +00:00
|
|
|
const auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == rowToCollapse);
|
|
|
|
QVERIFY(signalArgs.at(1).toBool() == true);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
2022-10-17 12:11:48 +00:00
|
|
|
QCOMPARE(treeView->rows(), 9); // root + 4 children + 4 grand children of the 3rd row
|
2022-02-01 13:51:30 +00:00
|
|
|
|
|
|
|
// We need to check that all descendants are collapsed as well. But since they're
|
|
|
|
// now no longer visible in the view, we need to expand each parent one by one again to make
|
|
|
|
// them visible, and check that the child inside that has children is still collapsed.
|
|
|
|
// We can do that by simply iterate over the rows in the view as we expand.
|
|
|
|
int currentRow = 1; // start at first child
|
|
|
|
while (currentRow < treeView->rows()) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const QModelIndex currentIndex = treeView->index(currentRow, 0);
|
2022-02-01 13:51:30 +00:00
|
|
|
if (model->hasChildren(currentIndex)) {
|
2022-10-17 12:11:48 +00:00
|
|
|
if (treeView->depth(currentRow) == 1 && currentIndex.row() == 2) {
|
|
|
|
// We did only recursively expand the 4th child, so the
|
|
|
|
// third should still be expanded
|
|
|
|
QVERIFY(treeView->isExpanded(currentRow));
|
|
|
|
} else {
|
|
|
|
QVERIFY(!treeView->isExpanded(currentRow));
|
|
|
|
treeView->expand(currentRow);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
}
|
2022-02-01 13:51:30 +00:00
|
|
|
}
|
|
|
|
currentRow++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sanity check that we ended up with all rows expanded again
|
|
|
|
QCOMPARE(currentRow, expectedRowCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::collapseRecursivelyWholeTree()
|
|
|
|
{
|
|
|
|
// Check that we collapse the whole tree recursively by passing -1
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(collapsed(int, bool)));
|
|
|
|
treeView->expandRecursively();
|
|
|
|
treeView->collapseRecursively();
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-02-01 13:51:30 +00:00
|
|
|
auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == -1);
|
|
|
|
QVERIFY(signalArgs.at(1).toBool() == true);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(treeView->rows(), 1); // root
|
|
|
|
}
|
|
|
|
|
2022-02-07 10:00:21 +00:00
|
|
|
void tst_qquicktreeview::expandToIndex()
|
|
|
|
{
|
|
|
|
// Check that expandToIndex(index) expands the tree so
|
|
|
|
// that index becomes visible in the view
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
QSignalSpy spy(treeView, SIGNAL(expanded(int, int)));
|
|
|
|
|
|
|
|
const QModelIndex root = model->index(0, 0);
|
|
|
|
const QModelIndex child1 = model->index(3, 0, root);
|
|
|
|
const QModelIndex child2 = model->index(3, 0, child1);
|
|
|
|
|
|
|
|
QVERIFY(model->hasChildren(root));
|
|
|
|
QVERIFY(model->hasChildren(child1));
|
|
|
|
QVERIFY(model->hasChildren(child2));
|
|
|
|
|
|
|
|
QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(root)));
|
|
|
|
QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(child1)));
|
|
|
|
QVERIFY(!treeView->isExpanded(treeView->rowAtIndex(child2)));
|
|
|
|
|
|
|
|
const QModelIndex childToExpand = model->index(1, 0, child2);
|
|
|
|
treeView->expandToIndex(childToExpand);
|
|
|
|
|
|
|
|
QVERIFY(treeView->isExpanded(treeView->rowAtIndex(root)));
|
|
|
|
QVERIFY(treeView->isExpanded(treeView->rowAtIndex(child1)));
|
|
|
|
QVERIFY(treeView->isExpanded(treeView->rowAtIndex(child2)));
|
|
|
|
|
2022-10-05 05:29:16 +00:00
|
|
|
QCOMPARE(spy.size(), 1);
|
2022-02-07 10:00:21 +00:00
|
|
|
auto signalArgs = spy.takeFirst();
|
|
|
|
QVERIFY(signalArgs.at(0).toInt() == 0);
|
|
|
|
QVERIFY(signalArgs.at(1).toInt() == 3);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
// The view should now have 13 rows:
|
|
|
|
// root + 3 expanded nodes that each have 4 children
|
|
|
|
QCOMPARE(treeView->rows(), 13);
|
|
|
|
}
|
|
|
|
|
2022-04-07 08:07:28 +00:00
|
|
|
void tst_qquicktreeview::toggleExpandedUsingArrowKeys()
|
|
|
|
{
|
|
|
|
// Check that you can use the left and right arrow key to
|
|
|
|
// expand and collapse nodes in the tree.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
treeView->setFocus(true);
|
|
|
|
QQuickWindow *window = treeView->window();
|
|
|
|
|
|
|
|
// Start by making cell 0, 0 current
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
treeView->selectionModel()->setCurrentIndex(treeView->index(0, 0), QItemSelectionModel::NoUpdate);
|
2022-04-07 08:07:28 +00:00
|
|
|
|
|
|
|
// Expand row 0
|
|
|
|
const int row0 = 0;
|
|
|
|
QCOMPARE(treeView->rows(), 1);
|
|
|
|
QVERIFY(!treeView->isExpanded(row0));
|
|
|
|
QTest::keyPress(window, Qt::Key_Right);
|
|
|
|
QVERIFY(treeView->isExpanded(row0));
|
|
|
|
|
|
|
|
// A polish event was scheduled, but since the call to keyPress() processes
|
|
|
|
// events, WAIT_UNTIL_POLISHED will be unreliable. So use QTRY_COMPARE instead.
|
|
|
|
QTRY_COMPARE(treeView->rows(), 5);
|
|
|
|
|
|
|
|
// Hitting Key_Right again should be a no-op
|
|
|
|
QTest::keyPress(window, Qt::Key_Right);
|
|
|
|
QVERIFY(treeView->isExpanded(row0));
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row0, 0));
|
2022-04-07 08:07:28 +00:00
|
|
|
|
|
|
|
// Move down to row 1 and try to expand it. Since Row 1
|
|
|
|
// doesn't have children, expanding it will be a no-op.
|
|
|
|
// And also, it shouldn't move currentIndex to the next
|
|
|
|
// column either, it should stay in the tree column.
|
|
|
|
const int row1 = 1;
|
|
|
|
QVERIFY(!treeView->isExpanded(row1));
|
|
|
|
QTest::keyPress(window, Qt::Key_Down);
|
|
|
|
QTest::keyPress(window, Qt::Key_Right);
|
|
|
|
QVERIFY(!treeView->isExpanded(row1));
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row1, 0));
|
2022-04-07 08:07:28 +00:00
|
|
|
|
|
|
|
// Move down to row 4 and expand it
|
|
|
|
const int row4 = 4;
|
|
|
|
QCOMPARE(treeView->rows(), 5);
|
|
|
|
while (treeView->currentRow() != row4)
|
|
|
|
QTest::keyPress(window, Qt::Key_Down);
|
|
|
|
QVERIFY(!treeView->isExpanded(row4));
|
|
|
|
QTest::keyPress(window, Qt::Key_Right);
|
|
|
|
QVERIFY(treeView->isExpanded(row4));
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row4, 0));
|
2022-04-07 08:07:28 +00:00
|
|
|
|
|
|
|
// Move up again to row 0 and collapse it
|
|
|
|
while (treeView->currentRow() != row0)
|
|
|
|
QTest::keyPress(window, Qt::Key_Up);
|
|
|
|
QVERIFY(treeView->isExpanded(row0));
|
|
|
|
QTest::keyPress(window, Qt::Key_Left);
|
|
|
|
QVERIFY(!treeView->isExpanded(row0));
|
|
|
|
QTRY_COMPARE(treeView->rows(), 1);
|
|
|
|
|
|
|
|
// Hitting Key_Left again should be a no-op
|
|
|
|
QTest::keyPress(window, Qt::Key_Left);
|
|
|
|
QVERIFY(!treeView->isExpanded(row0));
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
QCOMPARE(treeView->selectionModel()->currentIndex(), treeView->index(row0, 0));
|
2022-04-07 08:07:28 +00:00
|
|
|
}
|
2022-02-07 10:00:21 +00:00
|
|
|
|
2022-11-30 13:56:37 +00:00
|
|
|
void tst_qquicktreeview::expandAndCollapsUsingDoubleClick()
|
|
|
|
{
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
// Check that the view only has one row loaded so far (the root of the tree)
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
|
|
|
|
// Expand the root by double clicking on the row
|
2023-01-24 18:09:23 +00:00
|
|
|
const auto item = treeView->itemAtIndex(treeView->index(0, 0));
|
2022-11-30 13:56:37 +00:00
|
|
|
QVERIFY(item);
|
|
|
|
const QPoint localPos = QPoint(item->width() / 2, item->height() / 2);
|
|
|
|
const QPoint pos = item->window()->contentItem()->mapFromItem(item, localPos).toPoint();
|
|
|
|
QTest::mouseDClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
|
|
|
|
// We now expect 5 rows, the root pluss it's 4 children. Since
|
|
|
|
// mouseDClick calls processEvents(), it becomes random at this
|
|
|
|
// point if the view has been polished or not. So use QTRY_COMPARE.
|
|
|
|
QTRY_COMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
|
|
|
|
// Collapse the root again
|
|
|
|
QTest::mouseDClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
QTRY_COMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
|
|
|
|
// If edit triggers has DoubleTapped set, we should
|
|
|
|
// start to edit instead of expanding.
|
|
|
|
treeView->setEditTriggers(QQuickTableView::DoubleTapped);
|
|
|
|
QTest::mouseDClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
if (QQuickTest::qIsPolishScheduled(treeView))
|
|
|
|
QVERIFY(QQuickTest::qWaitForPolish(treeView));
|
|
|
|
QTRY_COMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
}
|
|
|
|
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
void tst_qquicktreeview::selectionBehaviorCells_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QPoint>("startCell");
|
|
|
|
QTest::addColumn<QPoint>("endCellDist");
|
|
|
|
|
|
|
|
QTest::newRow("QPoint(0, 0), QPoint(0, 0)") << QPoint(0, 0) << QPoint(0, 0);
|
|
|
|
|
|
|
|
QTest::newRow("QPoint(0, 1), QPoint(0, 1)") << QPoint(0, 1) << QPoint(0, 1);
|
|
|
|
QTest::newRow("QPoint(0, 2), QPoint(0, 2)") << QPoint(0, 2) << QPoint(0, 2);
|
|
|
|
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(0, 0)") << QPoint(2, 2) << QPoint(0, 0);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(1, 0)") << QPoint(2, 2) << QPoint(1, 0);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(2, 0)") << QPoint(2, 2) << QPoint(2, 0);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(-1, 0)") << QPoint(2, 2) << QPoint(-1, 0);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(-2, 0)") << QPoint(2, 2) << QPoint(-2, 0);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(0, 1)") << QPoint(2, 2) << QPoint(0, 1);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(0, 2)") << QPoint(2, 2) << QPoint(0, 2);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(0, -1)") << QPoint(2, 2) << QPoint(0, -1);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(0, -2)") << QPoint(2, 2) << QPoint(0, -2);
|
|
|
|
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(1, 1)") << QPoint(2, 2) << QPoint(1, 1);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(1, 2)") << QPoint(2, 2) << QPoint(1, 2);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(1, -1)") << QPoint(2, 2) << QPoint(1, -1);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(1, -2)") << QPoint(2, 2) << QPoint(1, -2);
|
|
|
|
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(-1, 1)") << QPoint(2, 2) << QPoint(-1, 1);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(-1, 2)") << QPoint(2, 2) << QPoint(-1, 2);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(-1, -1)") << QPoint(2, 2) << QPoint(-1, -1);
|
|
|
|
QTest::newRow("QPoint(2, 2), QPoint(-1, -2)") << QPoint(2, 2) << QPoint(-1, -2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::selectionBehaviorCells()
|
|
|
|
{
|
|
|
|
// Check that the TreeView implement the overridden updateSelection()
|
|
|
|
// function correctly wrt QQuickTableView::SelectCells.
|
|
|
|
QFETCH(QPoint, startCell);
|
|
|
|
QFETCH(QPoint, endCellDist);
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
const auto selectionModel = treeView->selectionModel();
|
|
|
|
treeView->expand(0);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
treeView->setSelectionBehavior(QQuickTableView::SelectCells);
|
|
|
|
|
|
|
|
const QPoint endCell = startCell + endCellDist;
|
|
|
|
const QPoint endCellWrapped = startCell - endCellDist;
|
|
|
|
|
|
|
|
const QQuickItem *startItem = treeView->itemAtCell(startCell);
|
|
|
|
const QQuickItem *endItem = treeView->itemAtCell(endCell);
|
|
|
|
const QQuickItem *endItemWrapped = treeView->itemAtCell(endCellWrapped);
|
|
|
|
QVERIFY(startItem);
|
|
|
|
QVERIFY(endItem);
|
|
|
|
QVERIFY(endItemWrapped);
|
|
|
|
|
|
|
|
const QPointF startPos(startItem->x(), startItem->y());
|
|
|
|
const QPointF endPos(endItem->x(), endItem->y());
|
|
|
|
const QPointF endPosWrapped(endItemWrapped->x(), endItemWrapped->y());
|
|
|
|
|
|
|
|
treeViewPrivate->setSelectionStartPos(startPos);
|
|
|
|
treeViewPrivate->setSelectionEndPos(endPos);
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), true);
|
|
|
|
|
|
|
|
const int x1 = qMin(startCell.x(), endCell.x());
|
|
|
|
const int x2 = qMax(startCell.x(), endCell.x());
|
|
|
|
const int y1 = qMin(startCell.y(), endCell.y());
|
|
|
|
const int y2 = qMax(startCell.y(), endCell.y());
|
|
|
|
|
|
|
|
for (int x = x1; x < x2; ++x) {
|
|
|
|
for (int y = y1; y < y2; ++y) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(y, x);
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QVERIFY(selectionModel->isSelected(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const int expectedCount = (x2 - x1 + 1) * (y2 - y1 + 1);
|
Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:
const std::string o = "object";
auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };
auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
auto exprOfDeclaredType = [&](auto decl) {
return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
};
return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
};
auto renameMethod = [&] (ArrayRef<StringRef> classes,
StringRef from, StringRef to) {
return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
changeTo(cat(access(o, cat(to)), "()")),
cat("use '", to, "' instead of '", from, "'"));
};
renameMethod(<classes>, "count", "size");
renameMethod(<classes>, "length", "size");
except that on() was replaced with a matcher that doesn't ignoreParens().
a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.
Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-08 17:56:03 +00:00
|
|
|
const int actualCount = selectionModel->selectedIndexes().size();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QCOMPARE(actualCount, expectedCount);
|
|
|
|
|
|
|
|
// Wrap the selection
|
|
|
|
treeViewPrivate->setSelectionEndPos(endPosWrapped);
|
|
|
|
|
|
|
|
for (int x = x2; x < x1; ++x) {
|
|
|
|
for (int y = y2; y < y1; ++y) {
|
|
|
|
const auto index = model->index(y, x);
|
|
|
|
QVERIFY(selectionModel->isSelected(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:
const std::string o = "object";
auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };
auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
auto exprOfDeclaredType = [&](auto decl) {
return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
};
return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
};
auto renameMethod = [&] (ArrayRef<StringRef> classes,
StringRef from, StringRef to) {
return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
changeTo(cat(access(o, cat(to)), "()")),
cat("use '", to, "' instead of '", from, "'"));
};
renameMethod(<classes>, "count", "size");
renameMethod(<classes>, "length", "size");
except that on() was replaced with a matcher that doesn't ignoreParens().
a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.
Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-08 17:56:03 +00:00
|
|
|
const int actualCountAfterWrap = selectionModel->selectedIndexes().size();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QCOMPARE(actualCountAfterWrap, expectedCount);
|
|
|
|
|
|
|
|
treeViewPrivate->clearSelection();
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::selectionBehaviorRows()
|
|
|
|
{
|
|
|
|
// Check that the TreeView implement the overridden updateSelection()
|
|
|
|
// function correctly wrt QQuickTableView::SelectionRows.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
const auto selectionModel = treeView->selectionModel();
|
|
|
|
QCOMPARE(treeView->selectionBehavior(), QQuickTableView::SelectRows);
|
|
|
|
treeView->expand(0);
|
|
|
|
treeView->setInteractive(false);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
|
|
|
|
// Drag from row 0 to row 3
|
|
|
|
treeViewPrivate->setSelectionStartPos(QPointF(0, 0));
|
|
|
|
treeViewPrivate->setSelectionEndPos(QPointF(80, 60));
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), true);
|
|
|
|
|
|
|
|
const int expectedCount = treeView->columns() * 3; // all columns * three rows
|
Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:
const std::string o = "object";
auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };
auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
auto exprOfDeclaredType = [&](auto decl) {
return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
};
return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
};
auto renameMethod = [&] (ArrayRef<StringRef> classes,
StringRef from, StringRef to) {
return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
changeTo(cat(access(o, cat(to)), "()")),
cat("use '", to, "' instead of '", from, "'"));
};
renameMethod(<classes>, "count", "size");
renameMethod(<classes>, "length", "size");
except that on() was replaced with a matcher that doesn't ignoreParens().
a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.
Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-08 17:56:03 +00:00
|
|
|
int actualCount = selectionModel->selectedIndexes().size();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QCOMPARE(actualCount, expectedCount);
|
|
|
|
|
|
|
|
for (int x = 0; x < treeView->columns(); ++x) {
|
|
|
|
for (int y = 0; y < 3; ++y) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(y, x);
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QVERIFY(selectionModel->isSelected(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
selectionModel->clear();
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
|
|
|
|
// Drag from row 3 to row 0 (and overshoot mouse)
|
|
|
|
treeViewPrivate->setSelectionStartPos(QPointF(80, 60));
|
|
|
|
treeViewPrivate->setSelectionEndPos(QPointF(-10, -10));
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), true);
|
|
|
|
|
Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:
const std::string o = "object";
auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };
auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
auto exprOfDeclaredType = [&](auto decl) {
return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
};
return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
};
auto renameMethod = [&] (ArrayRef<StringRef> classes,
StringRef from, StringRef to) {
return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
changeTo(cat(access(o, cat(to)), "()")),
cat("use '", to, "' instead of '", from, "'"));
};
renameMethod(<classes>, "count", "size");
renameMethod(<classes>, "length", "size");
except that on() was replaced with a matcher that doesn't ignoreParens().
a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.
Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-08 17:56:03 +00:00
|
|
|
actualCount = selectionModel->selectedIndexes().size();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QCOMPARE(actualCount, expectedCount);
|
|
|
|
|
|
|
|
for (int x = 0; x < treeView->columns(); ++x) {
|
|
|
|
for (int y = 0; y < 3; ++y) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(y, x);
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QVERIFY(selectionModel->isSelected(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::selectionBehaviorColumns()
|
|
|
|
{
|
|
|
|
// Check that the TreeView implement the overridden updateSelection()
|
|
|
|
// function correctly wrt QQuickTableView::SelectColumns.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
const auto selectionModel = treeView->selectionModel();
|
|
|
|
treeView->setSelectionBehavior(QQuickTableView::SelectColumns);
|
|
|
|
treeView->expand(0);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
|
|
|
|
// Drag from column 0 to column 3
|
|
|
|
treeViewPrivate->setSelectionStartPos(QPointF(0, 0));
|
|
|
|
treeViewPrivate->setSelectionEndPos(QPointF(225, 90));
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), true);
|
|
|
|
|
|
|
|
const int expectedCount = treeView->rows() * 3; // all rows * three columns
|
Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:
const std::string o = "object";
auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };
auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
auto exprOfDeclaredType = [&](auto decl) {
return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
};
return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
};
auto renameMethod = [&] (ArrayRef<StringRef> classes,
StringRef from, StringRef to) {
return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
changeTo(cat(access(o, cat(to)), "()")),
cat("use '", to, "' instead of '", from, "'"));
};
renameMethod(<classes>, "count", "size");
renameMethod(<classes>, "length", "size");
except that on() was replaced with a matcher that doesn't ignoreParens().
a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.
Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-08 17:56:03 +00:00
|
|
|
int actualCount = selectionModel->selectedIndexes().size();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QCOMPARE(actualCount, expectedCount);
|
|
|
|
|
|
|
|
for (int x = 0; x < 3; ++x) {
|
|
|
|
for (int y = 0; y < treeView->rows(); ++y) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(y, x);
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QVERIFY(selectionModel->isSelected(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
selectionModel->clear();
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
|
|
|
|
// Drag from column 3 to column 0 (and overshoot mouse)
|
|
|
|
treeViewPrivate->setSelectionStartPos(QPointF(225, 90));
|
|
|
|
treeViewPrivate->setSelectionEndPos(QPointF(-10, -10));
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), true);
|
|
|
|
|
Port from container::count() and length() to size() - V5
This is a semantic patch using ClangTidyTransformator as in
qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to
handle typedefs and accesses through pointers, too:
const std::string o = "object";
auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); };
auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) {
auto exprOfDeclaredType = [&](auto decl) {
return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o);
};
return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))));
};
auto renameMethod = [&] (ArrayRef<StringRef> classes,
StringRef from, StringRef to) {
return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)),
callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))),
changeTo(cat(access(o, cat(to)), "()")),
cat("use '", to, "' instead of '", from, "'"));
};
renameMethod(<classes>, "count", "size");
renameMethod(<classes>, "length", "size");
except that on() was replaced with a matcher that doesn't ignoreParens().
a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'.
Change-Id: I58e1b41b91c34d2e860dbb5847b3752edbfc6fc9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2022-10-08 17:56:03 +00:00
|
|
|
actualCount = selectionModel->selectedIndexes().size();
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QCOMPARE(actualCount, expectedCount);
|
|
|
|
|
|
|
|
for (int x = 0; x < 3; ++x) {
|
|
|
|
for (int y = 0; y < treeView->rows(); ++y) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(y, x);
|
QQuickTreeView: implement support for selecting cells
Selecting cells in a table is quite different from selecting
cells in a tree. The reason is that in a table, all model
items share the same model parent. And ItemSelectionModel
is optimized for this case, meaning that you can select
an area of cells by simply specifying the top-left index,
and the bottom-right index, as long as the cells
in-between all have the same parent.
A tree is not structured this way. Instead it's structured
as a hierarchy of parent-child relationships, where the
requirement that all model items should have the same parent
obviously will not hold.
Because of this, the implementation in TreeView that lets
the user select cells, needs to be quite different from the
optimized version in TableView. Instead, it basically needs to
divide the selected area into individual rows, and sometimes
indices, that can be selected, or deselected, one-by-one.
This patch overrides the 'updateSelection()' function for
QQuickTreeView, and rewrites the logic to take all this into
account. This will make selecting cells work for TreeView.
Change-Id: I2157efcd0e83b5a0342f6af4018323b64d31f6f3
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
2022-05-31 11:38:01 +00:00
|
|
|
QVERIFY(selectionModel->isSelected(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::selectionBehaviorDisabled()
|
|
|
|
{
|
|
|
|
// Check that the TreeView implement the overridden updateSelection()
|
|
|
|
// function correctly wrt QQuickTableView::SelectionDisabled.
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
const auto selectionModel = treeView->selectionModel();
|
|
|
|
treeView->setSelectionBehavior(QQuickTableView::SelectionDisabled);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
|
|
|
|
// Drag from column 0 to column 3
|
|
|
|
treeViewPrivate->setSelectionStartPos(QPointF(0, 0));
|
|
|
|
treeViewPrivate->setSelectionEndPos(QPointF(60, 60));
|
|
|
|
|
|
|
|
QCOMPARE(selectionModel->hasSelection(), false);
|
|
|
|
}
|
|
|
|
|
2022-10-17 12:11:48 +00:00
|
|
|
void tst_qquicktreeview::sortTreeModel_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QSharedPointer<QAbstractItemModel>>("treeModel");
|
|
|
|
|
|
|
|
const auto stringList = QStringList() << "1" << "2" << "3";
|
|
|
|
QTest::newRow("TreeModel") << QSharedPointer<QAbstractItemModel>(new TestModel());
|
|
|
|
QTest::newRow("Number model") << QSharedPointer<QAbstractItemModel>(new QStringListModel(stringList));
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::sortTreeModel()
|
|
|
|
{
|
|
|
|
// Check that if you assign a QSortFilterProxyModel to to a TreeView, the
|
|
|
|
// view will end up sorted correctly if the proxy model is sorted.
|
|
|
|
QFETCH(QSharedPointer<QAbstractItemModel>, treeModel);
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
QSortFilterProxyModel proxyModel;
|
|
|
|
proxyModel.setSourceModel(treeModel.data());
|
|
|
|
treeView->setModel(QVariant::fromValue(&proxyModel));
|
|
|
|
|
|
|
|
// Expand some nodes
|
|
|
|
treeView->expand(0);
|
|
|
|
treeView->expand(4);
|
|
|
|
treeView->expand(3);
|
|
|
|
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
// Go through all rows in the view, and check that display in the model
|
|
|
|
// is the same as in the view. That means that QQmlTreeModelToTableModel
|
|
|
|
// and QSortFilterProxyModel are in sync.
|
|
|
|
for (int row = 0; row < treeView->rows(); ++row) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(row, 0);
|
2022-10-17 12:11:48 +00:00
|
|
|
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
|
|
|
|
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
|
|
|
|
QVERIFY(childFxItem);
|
|
|
|
const auto childItem = childFxItem->item;
|
|
|
|
QVERIFY(childItem);
|
|
|
|
const auto context = qmlContext(childItem.data());
|
|
|
|
const auto itemDisplay = context->contextProperty("display").toString();
|
|
|
|
QCOMPARE(itemDisplay, modelDisplay);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now sort the model, and do the same test again
|
|
|
|
proxyModel.sort(0, Qt::DescendingOrder);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
|
|
|
|
for (int row = 0; row < treeView->rows(); ++row) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(row, 0);
|
2022-10-17 12:11:48 +00:00
|
|
|
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
|
|
|
|
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
|
|
|
|
QVERIFY(childFxItem);
|
|
|
|
const auto childItem = childFxItem->item;
|
|
|
|
QVERIFY(childItem);
|
|
|
|
const auto context = qmlContext(childItem.data());
|
|
|
|
const auto itemDisplay = context->contextProperty("display").toString();
|
|
|
|
QCOMPARE(itemDisplay, modelDisplay);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::sortTreeModelDynamic_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QSharedPointer<QAbstractItemModel>>("treeModel");
|
|
|
|
QTest::addColumn<int>("row");
|
|
|
|
|
|
|
|
const auto stringList = QStringList() << "1" << "2" << "3";
|
|
|
|
QTest::newRow("TreeModel 0") << QSharedPointer<QAbstractItemModel>(new TestModel()) << 0;
|
|
|
|
QTest::newRow("TreeModel 1") << QSharedPointer<QAbstractItemModel>(new TestModel()) << 1;
|
|
|
|
QTest::newRow("TreeModel 3") << QSharedPointer<QAbstractItemModel>(new TestModel()) << 3;
|
|
|
|
QTest::newRow("TreeModel 6") << QSharedPointer<QAbstractItemModel>(new TestModel()) << 6;
|
|
|
|
QTest::newRow("Number model") << QSharedPointer<QAbstractItemModel>(new QStringListModel(stringList)) << 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_qquicktreeview::sortTreeModelDynamic()
|
|
|
|
{
|
|
|
|
// Check that if you assign a QSortFilterProxyModel to a TreeView, and
|
|
|
|
// set DynamicSortFilter to true, the view will end up sorted correctly
|
|
|
|
// if you change the text for one of the items.
|
|
|
|
QFETCH(QSharedPointer<QAbstractItemModel>, treeModel);
|
|
|
|
QFETCH(int, row);
|
|
|
|
LOAD_TREEVIEW("normaltreeview.qml");
|
|
|
|
|
|
|
|
QSortFilterProxyModel proxyModel;
|
|
|
|
proxyModel.setSourceModel(treeModel.data());
|
|
|
|
proxyModel.setDynamicSortFilter(true);
|
|
|
|
proxyModel.sort(Qt::AscendingOrder);
|
|
|
|
treeView->setModel(QVariant::fromValue(&proxyModel));
|
|
|
|
|
|
|
|
// Expand some nodes
|
|
|
|
treeView->expand(0);
|
|
|
|
treeView->expand(4);
|
|
|
|
treeView->expand(3);
|
|
|
|
|
|
|
|
// Go through all rows in the view, and check that display in the model
|
|
|
|
// is the same as in the view. That means that QQmlTreeModelToTableModel
|
|
|
|
// and QSortFilterProxyModel are in sync.
|
|
|
|
for (int row = 0; row < treeView->rows(); ++row) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(row, 0);
|
2022-10-17 12:11:48 +00:00
|
|
|
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
|
|
|
|
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
|
|
|
|
QVERIFY(childFxItem);
|
|
|
|
const auto childItem = childFxItem->item;
|
|
|
|
QVERIFY(childItem);
|
|
|
|
const auto context = qmlContext(childItem.data());
|
|
|
|
const auto itemDisplay = context->contextProperty("display").toString();
|
|
|
|
QCOMPARE(itemDisplay, modelDisplay);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now change the text in one of the items. This will trigger
|
|
|
|
// a sort for only one of the parents in the model.
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
proxyModel.setData(treeView->index(row, 0), u"xxx"_s, Qt::DisplayRole);
|
2022-10-17 12:11:48 +00:00
|
|
|
|
|
|
|
for (int row = 0; row < treeView->rows(); ++row) {
|
TableView: deprecate modelIndex(row, column) in favor of index(row, column)
Deprecate modelIndex(row, column) in favor of a new
function index(row, column), starting from Qt 6.4.3.
This has the advantage that we can print out a deprecation
warning when modelIndex() is is used at run-time from QML.
This will inform the developer early on that he should
avoid using modelIndex(row, column), since the argument
order differs between different versions of Qt.
Relying on compile time deprecation macros alone will not
work, since the API break is in a private class and only
used publicly from QML (except for our own internal auto
tests).
Since the equivalent function in QAIM is also called
index(row, column), this will additionally make the
naming more consistent with the model classes.
[ChangeLog][Quick][TableView] modelIndex(row, column)
has been deprecated in favor of index(row, column).
Task-number: QTBUG-109542
Pick-to: 6.5 6.4
Change-Id: Iec8f5f8fa2a0ca714153128717b546bbd62c7e2c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-01-20 09:49:31 +00:00
|
|
|
const auto index = treeView->index(row, 0);
|
2022-10-17 12:11:48 +00:00
|
|
|
const QString modelDisplay = proxyModel.data(index, Qt::DisplayRole).toString();
|
|
|
|
const auto childFxItem = treeViewPrivate->loadedTableItem(QPoint(0, row));
|
|
|
|
QVERIFY(childFxItem);
|
|
|
|
const auto childItem = childFxItem->item;
|
|
|
|
QVERIFY(childItem);
|
|
|
|
const auto context = qmlContext(childItem.data());
|
|
|
|
const auto itemDisplay = context->contextProperty("display").toString();
|
|
|
|
QCOMPARE(itemDisplay, modelDisplay);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-19 15:58:36 +00:00
|
|
|
QTEST_MAIN(tst_qquicktreeview)
|
|
|
|
|
|
|
|
#include "tst_qquicktreeview.moc"
|