285 lines
11 KiB
C++
285 lines
11 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2021 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtQuick module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
#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 <QtQuickTemplates2/private/qquicktreeviewdelegate_p.h>
|
|
|
|
#include <QtQml/qqmlengine.h>
|
|
#include <QtQml/qqmlcontext.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;
|
|
|
|
#define LOAD_TREEVIEW(fileName) \
|
|
view->setSource(testFileUrl(fileName)); \
|
|
view->show(); \
|
|
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::qWaitForItemPolished(item))
|
|
#define WAIT_UNTIL_POLISHED WAIT_UNTIL_POLISHED_ARG(treeView)
|
|
|
|
// ########################################################
|
|
|
|
class tst_qquicktreeviewdelegate : public QQmlDataTest
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
tst_qquicktreeviewdelegate();
|
|
|
|
private:
|
|
QQuickView *view = nullptr;
|
|
|
|
private slots:
|
|
void initTestCase() override;
|
|
void showTreeView();
|
|
void expandAndCollapsUsingDoubleClick();
|
|
void expandAndCollapseClickOnIndicator();
|
|
void expandAndCollapsUsingNonSupportedButtonAndModifers_data();
|
|
void expandAndCollapsUsingNonSupportedButtonAndModifers();
|
|
void checkPropertiesRoot();
|
|
void checkPropertiesChildren();
|
|
};
|
|
|
|
tst_qquicktreeviewdelegate::tst_qquicktreeviewdelegate()
|
|
: QQmlDataTest(QT_QMLTEST_DATADIR)
|
|
{
|
|
}
|
|
|
|
void tst_qquicktreeviewdelegate::initTestCase()
|
|
{
|
|
QQmlDataTest::initTestCase();
|
|
qmlRegisterType<TestModel>("TestModel", 1, 0, "TestModel");
|
|
view = createView();
|
|
}
|
|
|
|
void tst_qquicktreeviewdelegate::showTreeView()
|
|
{
|
|
LOAD_TREEVIEW("unmodified.qml");
|
|
// Check that the view is showing the root of the tree
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
}
|
|
|
|
void tst_qquicktreeviewdelegate::expandAndCollapsUsingDoubleClick()
|
|
{
|
|
LOAD_TREEVIEW("unmodified.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
|
|
const auto item = treeView->itemAtCell(0, 0);
|
|
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);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
// We now expect 5 rows, the root pluss it's 4 children
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
// Collapse the root again
|
|
QTest::mouseDClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
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_qquicktreeviewdelegate::expandAndCollapseClickOnIndicator()
|
|
{
|
|
LOAD_TREEVIEW("unmodified.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 clicking on the indicator
|
|
const auto item = qobject_cast<QQuickTreeViewDelegate *>(treeView->itemAtCell(0, 0));
|
|
QVERIFY(item);
|
|
const auto indicator = item->indicator();
|
|
const QPoint localPos = QPoint(indicator->width() / 2, indicator->height() / 2);
|
|
const QPoint pos = item->window()->contentItem()->mapFromItem(indicator, localPos).toPoint();
|
|
QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
// We now expect 5 rows, the root pluss it's 4 children
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
// Collapse the root again
|
|
QTest::mouseClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
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_qquicktreeviewdelegate::expandAndCollapsUsingNonSupportedButtonAndModifers_data()
|
|
{
|
|
QTest::addColumn<Qt::MouseButton>("button");
|
|
QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
|
|
|
|
QTest::newRow("left + Qt::ControlModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::ControlModifier);
|
|
QTest::newRow("left + Qt::ShiftModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::ShiftModifier);
|
|
QTest::newRow("left + Qt::AltModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::AltModifier);
|
|
QTest::newRow("left + Qt::MetaModifier") << Qt::LeftButton << Qt::KeyboardModifiers(Qt::MetaModifier);
|
|
QTest::newRow("left + Qt::ControlModifier + Qt::ShiftModifier") << Qt::LeftButton << (Qt::ShiftModifier | Qt::ControlModifier);
|
|
|
|
QTest::newRow("right + Qt::NoModifier") << Qt::RightButton << Qt::KeyboardModifiers(Qt::ControlModifier);
|
|
QTest::newRow("right + Qt::ControlModifier") << Qt::RightButton << Qt::KeyboardModifiers(Qt::ShiftModifier);
|
|
}
|
|
|
|
void tst_qquicktreeviewdelegate::expandAndCollapsUsingNonSupportedButtonAndModifers()
|
|
{
|
|
QFETCH(Qt::MouseButton, button);
|
|
QFETCH(Qt::KeyboardModifiers, modifiers);
|
|
// Ensure that we don't expand or collapse the tree if the user is using the right mouse
|
|
// button, or holding down modifier keys. This "space" is reserved for application specific actions.
|
|
LOAD_TREEVIEW("unmodified.qml");
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
const auto item = treeView->itemAtCell(0, 0);
|
|
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(), button, modifiers, pos);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
// Expand first row, and ensure we don't collapse it again
|
|
// if doing a double click together with Qt::CTRL.
|
|
QTest::mouseDClick(item->window(), Qt::LeftButton, Qt::NoModifier, pos);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We now expect 5 rows, the root pluss it's 4 children
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
|
|
QTest::mouseDClick(item->window(), button, modifiers, pos);
|
|
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
// We still expect 5 rows, the root pluss it's 4 children
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 5);
|
|
}
|
|
|
|
void tst_qquicktreeviewdelegate::checkPropertiesRoot()
|
|
{
|
|
LOAD_TREEVIEW("unmodified.qml");
|
|
QCOMPARE(treeViewPrivate->loadedRows.count(), 1);
|
|
|
|
const auto rootFxItem = treeViewPrivate->loadedTableItem(QPoint(0, 0));
|
|
QVERIFY(rootFxItem);
|
|
const auto rootItem = qobject_cast<QQuickTreeViewDelegate *>(rootFxItem->item);
|
|
QVERIFY(rootItem);
|
|
|
|
QCOMPARE(rootItem->treeView(), treeView);
|
|
QCOMPARE(rootItem->isTreeNode(), true);
|
|
QCOMPARE(rootItem->expanded(), false);
|
|
QCOMPARE(rootItem->hasChildren(), true);
|
|
QCOMPARE(rootItem->depth(), 0);
|
|
QCOMPARE(rootItem->leftPadding(), rootItem->leftMargin() + (rootItem->depth() * rootItem->indentation()) + rootItem->indicator()->width() + rootItem->spacing());
|
|
QCOMPARE(rootItem->indicator()->x(), rootItem->leftMargin() + (rootItem->depth() * rootItem->indentation()));
|
|
|
|
treeView->expand(0);
|
|
WAIT_UNTIL_POLISHED;
|
|
|
|
QCOMPARE(rootItem->expanded(), true);
|
|
}
|
|
|
|
void tst_qquicktreeviewdelegate::checkPropertiesChildren()
|
|
{
|
|
LOAD_TREEVIEW("unmodified.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 = qobject_cast<QQuickTreeViewDelegate *>(childFxItem->item);
|
|
QVERIFY(childItem);
|
|
|
|
QCOMPARE(childItem->treeView(), treeView);
|
|
QCOMPARE(childItem->isTreeNode(), true);
|
|
QCOMPARE(childItem->expanded(), row == 4);
|
|
QCOMPARE(childItem->hasChildren(), row == 4 || row == 8);
|
|
QCOMPARE(childItem->depth(), row <= 4 ? 1 : 2);
|
|
QCOMPARE(childItem->leftPadding(), childItem->leftMargin() + (childItem->depth() * childItem->indentation()) + childItem->indicator()->width() + childItem->spacing());
|
|
QCOMPARE(childItem->indicator()->x(), childItem->leftMargin() + (childItem->depth() * childItem->indentation()));
|
|
}
|
|
}
|
|
|
|
QTEST_MAIN(tst_qquicktreeviewdelegate)
|
|
|
|
#include "tst_qquicktreeviewdelegate.moc"
|