qt5base-lts/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
Markku Heikkila 9e75354aab Fix crash in QTreeWidgetItem::sortChildren when adding new item.
This is a cherry-pick of 4f388c383e39b598d997e21bd9a4f16d89bd0625
from February

Recursive call is caused if user code calls QtreeWidgetItem()::sortChildren and
sorting is enbled in QTreeWidget.

First call is from user code and second is caused by timer.
When timer expires second call is made.

This recursion is prevented with QTreeModel::SkipSorting skipSorting()
in QTreeWidgetItem::sortChildren();

Task-number: QTBUG-20345
Change-Id: Ibf73e69274423f31397a9e391bfba7d5c4103a3c
Reviewed-by: Markku Tapio Heikkilä <markku.heikkila@digia.com>
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
2012-06-08 18:09:07 +02:00

3382 lines
118 KiB
C++

/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <qtreewidget.h>
#include <qtreewidgetitemiterator.h>
#include <qapplication.h>
#include <qeventloop.h>
#include <qdebug.h>
#include <qheaderview.h>
#include <qlineedit.h>
#include <QScrollBar>
#include <QStyledItemDelegate>
class CustomTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
QModelIndex indexFromItem(QTreeWidgetItem *item, int column = 0) const
{ return QTreeWidget::indexFromItem(item, column); }
};
class tst_QTreeWidget : public QObject
{
Q_OBJECT
public:
tst_QTreeWidget();
~tst_QTreeWidget();
public slots:
void initTestCase();
void cleanupTestCase();
void init();
void cleanup();
private slots:
void getSetCheck();
void addTopLevelItem();
void currentItem_data();
void currentItem();
void editItem_data();
void editItem();
void takeItem_data();
void takeItem();
void removeChild_data();
void removeChild();
void setItemHidden();
void setItemHidden2();
void selectedItems_data();
void selectedItems();
void itemAssignment();
void clone_data();
void clone();
void expand_data();
void expand();
void checkState_data();
void checkState();
void findItems_data();
void findItems();
void findItemsInColumn();
void sortItems_data();
void sortItems();
void deleteItems_data();
void deleteItems();
void itemAboveOrBelow();
void itemStreaming_data();
void itemStreaming();
void insertTopLevelItems_data();
void insertTopLevelItems();
void keyboardNavigation();
void scrollToItem();
void setSortingEnabled();
void match();
void columnCount();
void setHeaderLabels();
void setHeaderItem();
void itemWidget_data();
void itemWidget();
void insertItemsWithSorting_data();
void insertItemsWithSorting();
void insertExpandedItemsWithSorting_data();
void insertExpandedItemsWithSorting();
void changeDataWithSorting_data();
void changeDataWithSorting();
void changeDataWithStableSorting_data();
void changeDataWithStableSorting();
void sortedIndexOfChild_data();
void sortedIndexOfChild();
void defaultRowSizes();
void task191552_rtl();
void task203673_selection();
void rootItemFlags();
void task218661_setHeaderData();
void task245280_sortChildren();
void task253109_itemHeight();
// QTreeWidgetItem
void itemOperatorLessThan();
void addChild();
void setData();
void enableDisable();
void expandAndCallapse();
void itemData();
void setDisabled();
void removeSelectedItem();
void removeCurrentItem();
void removeCurrentItem_task186451();
void randomExpand();
void crashTest();
void sortAndSelect();
void task206367_duplication();
void selectionOrder();
void setSelectionModel();
void task217309();
void setCurrentItemExpandsParent();
void task239150_editorWidth();
void setTextUpdate();
void taskQTBUG2844_visualItemRect();
void setChildIndicatorPolicy();
void task20345_sortChildren();
public slots:
void itemSelectionChanged();
void emitDataChanged();
private:
CustomTreeWidget *testWidget;
};
// Testing get/set functions
void tst_QTreeWidget::getSetCheck()
{
QTreeWidget obj1;
// int QTreeWidget::columnCount()
// void QTreeWidget::setColumnCount(int)
obj1.setColumnCount(0);
QCOMPARE(obj1.columnCount(), 0);
obj1.setColumnCount(INT_MIN);
QCOMPARE(obj1.columnCount(), 0);
//obj1.setColumnCount(INT_MAX);
//QCOMPARE(obj1.columnCount(), INT_MAX);
// Since setColumnCount allocates memory, there is no way this will succeed
obj1.setColumnCount(100);
QCOMPARE(obj1.columnCount(), 100);
// QTreeWidgetItem * QTreeWidget::headerItem()
// void QTreeWidget::setHeaderItem(QTreeWidgetItem *)
QTreeWidgetItem *var2 = new QTreeWidgetItem();
obj1.setHeaderItem(var2);
QCOMPARE(obj1.headerItem(), var2);
obj1.setHeaderItem((QTreeWidgetItem *)0);
// QCOMPARE(obj1.headerItem(), (QTreeWidgetItem *)0);
// QTreeWidgetItem * QTreeWidget::currentItem()
// void QTreeWidget::setCurrentItem(QTreeWidgetItem *)
QTreeWidgetItem *var3 = new QTreeWidgetItem(&obj1);
obj1.setCurrentItem(var3);
QCOMPARE(obj1.currentItem(), var3);
obj1.setCurrentItem((QTreeWidgetItem *)0);
QCOMPARE(obj1.currentItem(), (QTreeWidgetItem *)0);
}
typedef QList<int> IntList;
typedef QList<IntList> ListIntList;
Q_DECLARE_METATYPE(IntList)
Q_DECLARE_METATYPE(ListIntList)
Q_DECLARE_METATYPE(QModelIndex)
Q_DECLARE_METATYPE(Qt::Orientation)
typedef QTreeWidgetItem TreeItem;
typedef QList<TreeItem*> TreeItemList;
Q_DECLARE_METATYPE(QTreeWidgetItem*)
Q_DECLARE_METATYPE(TreeItemList)
tst_QTreeWidget::tst_QTreeWidget(): testWidget(0)
{
}
tst_QTreeWidget::~tst_QTreeWidget()
{
}
void tst_QTreeWidget::initTestCase()
{
qMetaTypeId<QModelIndex>();
qMetaTypeId<Qt::Orientation>();
qRegisterMetaType<QTreeWidgetItem*>("QTreeWidgetItem*");
testWidget = new CustomTreeWidget();
testWidget->show();
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(testWidget);
#endif
}
void tst_QTreeWidget::cleanupTestCase()
{
testWidget->hide();
delete testWidget;
}
void tst_QTreeWidget::init()
{
testWidget->clear();
testWidget->setColumnCount(2);
}
void tst_QTreeWidget::cleanup()
{
}
TreeItem *operator<<(TreeItem *parent, const TreeItemList &children) {
for (int i = 0; i < children.count(); ++i)
parent->addChild(children.at(i));
return parent;
}
static void populate(QTreeWidget *widget, const TreeItemList &topLevelItems,
TreeItem *headerItem = 0)
{
widget->clear();
widget->setHeaderItem(headerItem);
foreach (TreeItem *item, topLevelItems)
widget->addTopLevelItem(item);
}
void tst_QTreeWidget::addTopLevelItem()
{
QTreeWidget tree;
QCOMPARE(tree.topLevelItemCount(), 0);
// try to add 0
tree.addTopLevelItem(0);
QCOMPARE(tree.topLevelItemCount(), 0);
QCOMPARE(tree.indexOfTopLevelItem(0), -1);
// add one at a time
QList<TreeItem*> tops;
for (int i = 0; i < 10; ++i) {
TreeItem *ti = new TreeItem();
QCOMPARE(tree.indexOfTopLevelItem(ti), -1);
tree.addTopLevelItem(ti);
QCOMPARE(tree.topLevelItemCount(), i+1);
QCOMPARE(tree.topLevelItem(i), ti);
QCOMPARE(tree.topLevelItem(-1), static_cast<TreeItem*>(0));
QCOMPARE(tree.indexOfTopLevelItem(ti), i);
QCOMPARE(ti->parent(), static_cast<TreeItem*>(0));
tree.addTopLevelItem(ti);
QCOMPARE(tree.topLevelItemCount(), i+1);
tops.append(ti);
}
// delete one at a time
while (!tops.isEmpty()) {
TreeItem *ti = tops.takeFirst();
delete ti;
QCOMPARE(tree.topLevelItemCount(), tops.count());
for (int i = 0; i < tops.count(); ++i)
QCOMPARE(tree.topLevelItem(i), tops.at(i));
}
// add none
{
int count = tree.topLevelItemCount();
tree.addTopLevelItems(tops);
QCOMPARE(tree.topLevelItemCount(), count);
}
// add many at a time
{
const int count = 10;
for (int i = 0; i < 100; i += count) {
tops.clear();
for (int j = 0; j < count; ++j)
tops << new TreeItem(QStringList() << QString("%0").arg(j));
tree.addTopLevelItems(tops);
QCOMPARE(tree.topLevelItemCount(), count + i);
for (int j = 0; j < count; ++j)
QCOMPARE(tree.topLevelItem(i+j), tops.at(j));
tree.addTopLevelItems(tops);
QCOMPARE(tree.topLevelItemCount(), count + i);
}
}
// insert
{
tops.clear();
for (int i = 0; i < 10; ++i)
tops << new TreeItem();
int count = tree.topLevelItemCount();
tree.insertTopLevelItems(100000, tops);
// ### fixme
QCOMPARE(tree.topLevelItemCount(), count + 10);
}
}
void tst_QTreeWidget::currentItem_data()
{
QTest::addColumn<TreeItemList>("topLevelItems");
QTest::newRow("only top-level items, 2 columns")
<< (TreeItemList()
<< new TreeItem(QStringList() << "a" << "b")
<< new TreeItem(QStringList() << "c" << "d"));
TreeItemList lst;
lst << (new TreeItem(QStringList() << "a" << "b")
<< (TreeItemList()
<< new TreeItem(QStringList() << "c" << "d")
<< new TreeItem(QStringList() << "c" << "d")
)
)
<< (new TreeItem(QStringList() << "e" << "f")
<< (TreeItemList()
<< new TreeItem(QStringList() << "g" << "h")
<< new TreeItem(QStringList() << "g" << "h")
)
);
QTest::newRow("hierarchy, 2 columns") << lst;
}
void tst_QTreeWidget::currentItem()
{
QFETCH(TreeItemList, topLevelItems);
QTreeWidget tree;
tree.show();
populate(&tree, topLevelItems, new TreeItem(QStringList() << "1" << "2"));
QTreeWidgetItem *previous = 0;
for (int x = 0; x < 2; ++x) {
tree.setSelectionBehavior(x ? QAbstractItemView::SelectItems
: QAbstractItemView::SelectRows);
QSignalSpy currentItemChangedSpy(
&tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
QSignalSpy itemSelectionChangedSpy(
&tree, SIGNAL(itemSelectionChanged()));
QTreeWidgetItemIterator it(&tree);
// do all items
while (QTreeWidgetItem *item = (*it++)) {
tree.setCurrentItem(item);
QCOMPARE(tree.currentItem(), item);
QCOMPARE(currentItemChangedSpy.count(), 1);
QVariantList args = currentItemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(1)), previous);
QCOMPARE(itemSelectionChangedSpy.count(), 1);
itemSelectionChangedSpy.clear();
previous = item;
// do all columns
for (int col = 0; col < item->columnCount(); ++col) {
tree.setCurrentItem(item, col);
QCOMPARE(tree.currentItem(), item);
QCOMPARE(tree.currentColumn(), col);
if (!currentItemChangedSpy.isEmpty()) {
// ### we get a currentItemChanged() when what really
// changed was just currentColumn(). Should it be like this?
QCOMPARE(currentItemChangedSpy.count(), 1);
QVariantList args = currentItemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(1)), item);
if (tree.selectionBehavior() == QAbstractItemView::SelectItems) {
QCOMPARE(itemSelectionChangedSpy.count(), 1);
itemSelectionChangedSpy.clear();
} else {
QCOMPARE(itemSelectionChangedSpy.count(), 0);
}
}
}
}
}
// can't set the headerItem to be the current item
tree.setCurrentItem(tree.headerItem());
QCOMPARE(tree.currentItem(), static_cast<TreeItem*>(0));
}
void tst_QTreeWidget::editItem_data()
{
QTest::addColumn<TreeItemList>("topLevelItems");
{
TreeItemList list;
for (int i = 0; i < 10; i++) {
TreeItem *item = new TreeItem(QStringList() << "col1" << "col2");
if ((i & 1) == 0)
item->setFlags(item->flags() | Qt::ItemIsEditable);
else
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
list << item;
}
QTest::newRow("2 columns, only even items editable")
<< list;
}
}
void tst_QTreeWidget::editItem()
{
QFETCH(TreeItemList, topLevelItems);
QTreeWidget tree;
populate(&tree, topLevelItems, new TreeItem(QStringList() << "1" << "2"));
tree.show();
QTest::qWaitForWindowShown(&tree);
QSignalSpy itemChangedSpy(
&tree, SIGNAL(itemChanged(QTreeWidgetItem*,int)));
QTreeWidgetItemIterator it(&tree);
while (QTreeWidgetItem *item = (*it++)) {
for (int col = 0; col < item->columnCount(); ++col) {
if (!(item->flags() & Qt::ItemIsEditable))
QTest::ignoreMessage(QtWarningMsg, "edit: editing failed");
tree.editItem(item, col);
QApplication::instance()->processEvents();
QApplication::instance()->processEvents();
QLineEdit *editor = qFindChild<QLineEdit*>(&tree);
if (editor) {
QVERIFY(item->flags() & Qt::ItemIsEditable);
QCOMPARE(editor->selectedText(), editor->text());
QTest::keyClick(editor, Qt::Key_A);
QTest::keyClick(editor, Qt::Key_Enter);
QApplication::instance()->processEvents();
QCOMPARE(itemChangedSpy.count(), 1);
QVariantList args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), col);
} else {
QVERIFY(!(item->flags() & Qt::ItemIsEditable));
}
}
}
}
void tst_QTreeWidget::takeItem_data()
{
QTest::addColumn<int>("index");
QTest::addColumn<bool>("topLevel");
QTest::addColumn<bool>("outOfBounds");
QTest::newRow("First, topLevel") << 0 << true << false;
QTest::newRow("Last, topLevel") << 2 << true << false;
QTest::newRow("Middle, topLevel") << 1 << true << false;
QTest::newRow("Out of bounds, toplevel, (index: -1)") << -1 << true << true;
QTest::newRow("Out of bounds, toplevel, (index: 3)") << 3 << true << true;
QTest::newRow("First, child of topLevel") << 0 << false << false;
QTest::newRow("Last, child of topLevel") << 2 << false << false;
QTest::newRow("Middle, child of topLevel") << 1 << false << false;
QTest::newRow("Out of bounds, child of toplevel, (index: -1)") << -1 << false << true;
QTest::newRow("Out of bounds, child of toplevel, (index: 3)") << 3 << false << true;
}
void tst_QTreeWidget::takeItem()
{
QFETCH(int, index);
QFETCH(bool, topLevel);
QFETCH(bool, outOfBounds);
for (int i=0; i<3; ++i) {
QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
top->setText(0, QString("top%1").arg(i));
for (int j=0; j<3; ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(top);
child->setText(0, QString("child%1").arg(j));
}
}
QCOMPARE(testWidget->topLevelItemCount(), 3);
QCOMPARE(testWidget->topLevelItem(0)->childCount(), 3);
if (topLevel) {
int count = testWidget->topLevelItemCount();
QTreeWidgetItem *item = testWidget->takeTopLevelItem(index);
if (outOfBounds) {
QCOMPARE(item, (QTreeWidgetItem *)0);
QCOMPARE(count, testWidget->topLevelItemCount());
} else {
QCOMPARE(item->text(0), QString("top%1").arg(index));
QCOMPARE(count-1, testWidget->topLevelItemCount());
delete item;
}
} else {
int count = testWidget->topLevelItem(0)->childCount();
QTreeWidgetItem *item = testWidget->topLevelItem(0)->takeChild(index);
if (outOfBounds) {
QCOMPARE(item, (QTreeWidgetItem *)0);
QCOMPARE(count, testWidget->topLevelItem(0)->childCount());
} else {
QCOMPARE(item->text(0), QString("child%1").arg(index));
QCOMPARE(count-1, testWidget->topLevelItem(0)->childCount());
delete item;
}
}
}
void tst_QTreeWidget::removeChild_data()
{
QTest::addColumn<int>("childCount");
QTest::addColumn<int>("removeAt");
QTest::newRow("10 remove 3") << 10 << 3;
}
void tst_QTreeWidget::removeChild()
{
QFETCH(int, childCount);
QFETCH(int, removeAt);
QTreeWidgetItem *root = new QTreeWidgetItem;
for (int i = 0; i < childCount; ++i)
new QTreeWidgetItem(root, QStringList(QString::number(i)));
QCOMPARE(root->childCount(), childCount);
for (int j = 0; j < childCount; ++j)
QCOMPARE(root->child(j)->text(0), QString::number(j));
QTreeWidgetItem *remove = root->child(removeAt);
root->removeChild(remove);
QCOMPARE(root->childCount(), childCount - 1);
for (int k = 0; k < childCount; ++k) {
if (k == removeAt)
QCOMPARE(remove->text(0), QString::number(k));
else if (k < removeAt)
QCOMPARE(root->child(k)->text(0), QString::number(k));
else if (k > removeAt)
QCOMPARE(root->child(k - 1)->text(0), QString::number(k));
}
delete root;
}
void tst_QTreeWidget::setItemHidden()
{
QTreeWidgetItem *parent = new QTreeWidgetItem(testWidget);
parent->setText(0, "parent");
QTreeWidgetItem *child = new QTreeWidgetItem(parent);
child->setText(0, "child");
QVERIFY(child->parent());
testWidget->expandItem(parent);
testWidget->scrollToItem(child);
QVERIFY(testWidget->visualItemRect(parent).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent)));
QVERIFY(testWidget->visualItemRect(child).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child)));
QVERIFY(!testWidget->isItemHidden(parent));
QVERIFY(!testWidget->isItemHidden(child));
testWidget->setItemHidden(parent, true);
QVERIFY(!(testWidget->visualItemRect(parent).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent))));
QVERIFY(!(testWidget->visualItemRect(child).isValid()
&& testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child))));
QVERIFY(testWidget->isItemHidden(parent));
QVERIFY(!testWidget->isItemHidden(child));
// From task 78670 (This caused an core dump)
// Check if we can set an item visible if it already is visible.
testWidget->setItemHidden(parent, false);
testWidget->setItemHidden(parent, false);
QVERIFY(!testWidget->isItemHidden(parent));
// hide, hide and then unhide.
testWidget->setItemHidden(parent, true);
testWidget->setItemHidden(parent, true);
testWidget->setItemHidden(parent, false);
QVERIFY(!testWidget->isItemHidden(parent));
}
void tst_QTreeWidget::setItemHidden2()
{
// From Task 78587
QStringList hl;
hl << "ID" << "Desc";
testWidget->setColumnCount(hl.count());
testWidget->setHeaderLabels(hl);
testWidget->setSortingEnabled(true);
QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
QTreeWidgetItem *leaf = 0;
top->setText(0, "ItemList");
for (int i = 1; i <= 4; i++) {
leaf = new QTreeWidgetItem(top);
leaf->setText(0, QString().sprintf("%d", i));
leaf->setText(1, QString().sprintf("Item %d", i));
}
if (testWidget->topLevelItemCount() > 0) {
top = testWidget->topLevelItem(0);
testWidget->setItemExpanded(top, true);
}
if (testWidget->topLevelItemCount() > 0) {
top = testWidget->topLevelItem(0);
for (int i = 0; i < top->childCount(); i++) {
leaf = top->child(i);
if (leaf->text(0).toInt() % 2 == 0) {
if (!testWidget->isItemHidden(leaf)) {
testWidget->setItemHidden(leaf, true);
}
}
}
}
}
void tst_QTreeWidget::selectedItems_data()
{
QTest::addColumn<int>("topLevel");
QTest::addColumn<int>("children");
QTest::addColumn<bool>("closeTopLevel");
QTest::addColumn<ListIntList>("selectedItems");
QTest::addColumn<ListIntList>("hiddenItems");
QTest::addColumn<ListIntList>("expectedItems");
ListIntList selectedItems;
ListIntList hiddenItems;
ListIntList expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems
<< (IntList()
<< 0);
expectedItems
<< (IntList() << 0);
QTest::newRow("2 top with 2 children, closed, top0 selected, no hidden")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems
<< (IntList()
<< 0 << 0);
expectedItems
<< (IntList() << 0 << 0);
QTest::newRow("2 top with 2 children, closed, top0child0 selected, no hidden")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems
<< (IntList()
<< 0 << 0);
expectedItems
<< (IntList()
<< 0 << 0);
QTest::newRow("2 top with 2 children, open, top0child0 selected, no hidden")
<< 2 << 2 << false << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems << (IntList() << 0);
hiddenItems << (IntList() << 0);
QTest::newRow("2 top with 2 children, closed, top0 selected, top0 hidden")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems << (IntList() << 0 << 0);
hiddenItems << (IntList() << 0);
expectedItems << (IntList() << 0 << 0);
QTest::newRow("2 top with 2 children, closed, top0child0 selected, top0 hidden")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems
<< (IntList() << 0)
<< (IntList() << 0 << 0)
<< (IntList() << 0 << 1)
<< (IntList() << 1)
<< (IntList() << 1 << 0)
<< (IntList() << 1 << 1);
expectedItems
<< (IntList() << 0)
<< (IntList() << 0 << 0)
<< (IntList() << 0 << 1)
<< (IntList() << 1)
<< (IntList() << 1 << 0)
<< (IntList() << 1 << 1);
QTest::newRow("2 top with 2 children, closed, all selected, no hidden")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems
<< (IntList() << 0)
<< (IntList() << 0 << 0)
<< (IntList() << 0 << 1)
<< (IntList() << 1)
<< (IntList() << 1 << 0)
<< (IntList() << 1 << 1);
hiddenItems
<< (IntList() << 0);
expectedItems
//<< (IntList() << 0)
<< (IntList() << 0 << 0)
<< (IntList() << 0 << 1)
<< (IntList() << 1)
<< (IntList() << 1 << 0)
<< (IntList() << 1 << 1);
QTest::newRow("2 top with 2 children, closed, all selected, top0 hidden")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
selectedItems.clear(); hiddenItems.clear(); expectedItems.clear();
selectedItems
<< (IntList() << 0)
<< (IntList() << 0 << 0)
<< (IntList() << 0 << 1)
<< (IntList() << 1)
<< (IntList() << 1 << 0)
<< (IntList() << 1 << 1);
hiddenItems
<< (IntList() << 0 << 1)
<< (IntList() << 1);
expectedItems
<< (IntList() << 0)
<< (IntList() << 0 << 0)
//<< (IntList() << 0 << 1)
//<< (IntList() << 1)
<< (IntList() << 1 << 0)
<< (IntList() << 1 << 1);
QTest::newRow("2 top with 2 children, closed, all selected, top0child1 and top1")
<< 2 << 2 << true << selectedItems << hiddenItems << expectedItems;
}
void tst_QTreeWidget::selectedItems()
{
QFETCH(int, topLevel);
QFETCH(int, children);
QFETCH(bool, closeTopLevel);
QFETCH(ListIntList, selectedItems);
QFETCH(ListIntList, hiddenItems);
QFETCH(ListIntList, expectedItems);
// create items
for (int t=0; t<topLevel; ++t) {
QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
top->setText(0, QString("top%1").arg(t));
for (int c=0; c<children; ++c) {
QTreeWidgetItem *child = new QTreeWidgetItem(top);
child->setText(0, QString("top%1child%2").arg(t).arg(c));
}
}
// set selected
foreach (IntList itemPath, selectedItems) {
QTreeWidgetItem *item = 0;
foreach(int index, itemPath) {
if (!item)
item = testWidget->topLevelItem(index);
else
item = item->child(index);
}
testWidget->setItemSelected(item, true);
}
// hide rows
foreach (IntList itemPath, hiddenItems) {
QTreeWidgetItem *item = 0;
foreach(int index, itemPath) {
if (!item)
item = testWidget->topLevelItem(index);
else
item = item->child(index);
}
testWidget->setItemHidden(item, true);
}
// open/close toplevel
for (int i=0; i<testWidget->topLevelItemCount(); ++i) {
if (closeTopLevel)
testWidget->collapseItem(testWidget->topLevelItem(i));
else
testWidget->expandItem(testWidget->topLevelItem(i));
}
// check selectedItems
QList<QTreeWidgetItem*> sel = testWidget->selectedItems();
QCOMPARE(sel.count(), expectedItems.count());
foreach (IntList itemPath, expectedItems) {
QTreeWidgetItem *item = 0;
foreach(int index, itemPath) {
if (!item)
item = testWidget->topLevelItem(index);
else
item = item->child(index);
}
if (item)
QVERIFY(sel.contains(item));
}
// compare isSelected
for (int t=0; t<testWidget->topLevelItemCount(); ++t) {
QTreeWidgetItem *top = testWidget->topLevelItem(t);
if (testWidget->isItemSelected(top) && !testWidget->isItemHidden(top))
QVERIFY(sel.contains(top));
for (int c=0; c<top->childCount(); ++c) {
QTreeWidgetItem *child = top->child(c);
if (testWidget->isItemSelected(child) && !testWidget->isItemHidden(child))
QVERIFY(sel.contains(child));
}
}
// Possible to select null without crashing?
testWidget->setItemSelected(0, true);
QVERIFY(!testWidget->isItemSelected(0));
// unselect
foreach (IntList itemPath, selectedItems) {
QTreeWidgetItem *item = 0;
foreach(int index, itemPath) {
if (!item)
item = testWidget->topLevelItem(index);
else
item = item->child(index);
}
testWidget->setItemSelected(item, false);
}
QCOMPARE(testWidget->selectedItems().count(), 0);
}
void tst_QTreeWidget::itemAssignment()
{
// create item with children and parent but not insert in the view
QTreeWidgetItem grandParent;
QTreeWidgetItem *parent = new QTreeWidgetItem(&grandParent);
parent->setText(0, "foo");
parent->setText(1, "bar");
for (int i=0; i<5; ++i) {
QTreeWidgetItem *child = new QTreeWidgetItem(parent);
child->setText(0, "bingo");
child->setText(1, "bango");
}
QCOMPARE(parent->parent(), &grandParent);
QVERIFY(!parent->treeWidget());
QCOMPARE(parent->columnCount(), 2);
QCOMPARE(parent->text(0), QString("foo"));
QCOMPARE(parent->childCount(), 5);
QCOMPARE(parent->child(0)->parent(), parent);
// create item which is inserted in the widget
QTreeWidgetItem item(testWidget);
item.setText(0, "baz");
QVERIFY(!item.parent());
QCOMPARE(item.treeWidget(), static_cast<QTreeWidget *>(testWidget));
QCOMPARE(item.columnCount(), 1);
QCOMPARE(item.text(0), QString("baz"));
QCOMPARE(item.childCount(), 0);
// assign and test
*parent = item;
QCOMPARE(parent->parent(), &grandParent);
QVERIFY(!parent->treeWidget());
QCOMPARE(parent->columnCount(), 1);
QCOMPARE(parent->text(0), QString("baz"));
QCOMPARE(parent->childCount(), 5);
QCOMPARE(parent->child(0)->parent(), parent);
}
void tst_QTreeWidget::clone_data()
{
QTest::addColumn<int>("column");
QTest::addColumn<int>("topLevelIndex");
QTest::addColumn<int>("childIndex");
QTest::addColumn<QStringList>("topLevelText");
QTest::addColumn<QStringList>("childText");
QTest::addColumn<bool>("cloneChild");
QTest::newRow("clone parent with child") << 0 << 0 << 0
<< (QStringList() << "some text")
<< (QStringList() << "more text")
<< false;
QTest::newRow("clone child") << 0 << 0 << 0
<< (QStringList() << "some text")
<< (QStringList() << "more text")
<< true;
}
void tst_QTreeWidget::clone()
{
QFETCH(int, column);
QFETCH(int, topLevelIndex);
QFETCH(int, childIndex);
QFETCH(QStringList, topLevelText);
QFETCH(QStringList, childText);
QFETCH(bool, cloneChild);
for (int i = 0; i < topLevelText.count(); ++i) {
QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
item->setText(column, topLevelText.at(i));
for (int j = 0; j < childText.count(); ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(item);
child->setText(column, childText.at(j));
}
}
QTreeWidgetItem *original = testWidget->topLevelItem(topLevelIndex);
QTreeWidgetItem *copy = original->clone();
QCOMPARE(copy->text(column), original->text(column));
QCOMPARE(copy->childCount(), original->childCount());
QVERIFY(!copy->parent());
QVERIFY(!copy->treeWidget());
QTreeWidgetItem *originalChild = original->child(childIndex);
QTreeWidgetItem *copiedChild = cloneChild ? originalChild->clone() : copy->child(childIndex);
QVERIFY(copiedChild != originalChild);
QCOMPARE(copiedChild->text(column), originalChild->text(column));
QCOMPARE(copiedChild->childCount(), originalChild->childCount());
QCOMPARE(copiedChild->parent(), cloneChild ? 0 : copy);
QVERIFY(!copiedChild->treeWidget());
if (cloneChild)
delete copiedChild;
delete copy;
}
void tst_QTreeWidget::expand_data()
{
QTest::addColumn<int>("topLevelIndex");
QTest::addColumn<int>("topLevelCount");
QTest::addColumn<int>("childIndex");
QTest::addColumn<int>("childCount");
QTest::newRow("the only test data for now") << 0 << 1 << 0 << 1;
}
void tst_QTreeWidget::expand()
{
QFETCH(int, topLevelIndex);
QFETCH(int, topLevelCount);
QFETCH(int, childIndex);
QFETCH(int, childCount);
for (int i = 0; i < topLevelCount; ++i) {
QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
for (int j = 0; j < childCount; ++j)
new QTreeWidgetItem(item);
}
QTreeWidgetItem *topLevelItem = testWidget->topLevelItem(topLevelIndex);
QTreeWidgetItem *childItem = topLevelItem->child(childIndex);
QVERIFY(!testWidget->isItemExpanded(topLevelItem));
testWidget->setItemExpanded(topLevelItem, true);
QVERIFY(testWidget->isItemExpanded(topLevelItem));
QVERIFY(!testWidget->isItemExpanded(childItem));
testWidget->setItemExpanded(childItem, true);
QVERIFY(testWidget->isItemExpanded(childItem));
QVERIFY(testWidget->isItemExpanded(topLevelItem));
testWidget->setItemExpanded(topLevelItem, false);
QVERIFY(!testWidget->isItemExpanded(topLevelItem));
QVERIFY(testWidget->isItemExpanded(childItem));
testWidget->setItemExpanded(childItem, false);
QVERIFY(!testWidget->isItemExpanded(childItem));
}
void tst_QTreeWidget::checkState_data()
{
}
void tst_QTreeWidget::checkState()
{
QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
item->setCheckState(0, Qt::Unchecked);
QTreeWidgetItem *firstChild = new QTreeWidgetItem(item);
firstChild->setCheckState(0, Qt::Unchecked);
QTreeWidgetItem *seccondChild = new QTreeWidgetItem(item);
seccondChild->setCheckState(0, Qt::Unchecked);
QCOMPARE(item->checkState(0), Qt::Unchecked);
QCOMPARE(firstChild->checkState(0), Qt::Unchecked);
QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
firstChild->setCheckState(0, Qt::Checked);
QCOMPARE(item->checkState(0), Qt::Unchecked);
QCOMPARE(firstChild->checkState(0), Qt::Checked);
QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
item->setFlags(item->flags()|Qt::ItemIsTristate);
QCOMPARE(item->checkState(0), Qt::PartiallyChecked);
QCOMPARE(firstChild->checkState(0), Qt::Checked);
QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
seccondChild->setCheckState(0, Qt::Checked);
QCOMPARE(item->checkState(0), Qt::Checked);
QCOMPARE(firstChild->checkState(0), Qt::Checked);
QCOMPARE(seccondChild->checkState(0), Qt::Checked);
firstChild->setCheckState(0, Qt::Unchecked);
seccondChild->setCheckState(0, Qt::Unchecked);
QCOMPARE(item->checkState(0), Qt::Unchecked);
QCOMPARE(firstChild->checkState(0), Qt::Unchecked);
QCOMPARE(seccondChild->checkState(0), Qt::Unchecked);
}
void tst_QTreeWidget::findItems_data()
{
QTest::addColumn<int>("column");
QTest::addColumn<QStringList>("topLevelText");
QTest::addColumn<QStringList>("childText");
QTest::addColumn<QString>("pattern");
QTest::addColumn<int>("resultCount");
QTest::addColumn<QStringList>("resultText");
QTest::newRow("find in toplevel")
<< 0
<< (QStringList() << "This is a text" << "This is another" << "This is the one")
<< (QStringList() << "A child" << "This is not the one" << "And yet another child")
<< "This is the one"
<< 1
<< (QStringList() << "This is the one");
QTest::newRow("find child")
<< 0
<< (QStringList() << "This is a text" << "This is another" << "This is the one")
<< (QStringList() << "A child" << "This is not the one" << "And yet another child")
<< "A child"
<< 3 // once for each branch
<< (QStringList() << "A child");
}
void tst_QTreeWidget::findItems()
{
QFETCH(int, column);
QFETCH(QStringList, topLevelText);
QFETCH(QStringList, childText);
QFETCH(QString, pattern);
QFETCH(int, resultCount);
QFETCH(QStringList, resultText);
for (int i = 0; i < topLevelText.count(); ++i) {
QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
item->setText(column, topLevelText.at(i));
for (int j = 0; j < childText.count(); ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(item);
child->setText(column, childText.at(j));
}
}
QList<QTreeWidgetItem*> result = testWidget->findItems(pattern,
Qt::MatchExactly|Qt::MatchRecursive);
QCOMPARE(result.count(), resultCount);
for (int k = 0; k < result.count() && k < resultText.count(); ++k)
QCOMPARE(result.at(k)->text(column), resultText.at(k));
}
void tst_QTreeWidget::findItemsInColumn()
{
// Create 5 root items.
for (int i = 0; i < 5; i++)
new QTreeWidgetItem(testWidget, QStringList() << QString::number(i));
// Create a child with two columns for each root item.
for (int i = 0; i < 5; i++) {
QTreeWidgetItem * const parent = testWidget->topLevelItem(i);
new QTreeWidgetItem(parent, QStringList() << QString::number(i * 10) << QString::number(i * 100));
}
// Recursively search column one for 400.
QList<QTreeWidgetItem*> items = testWidget->findItems("400", Qt::MatchExactly|Qt::MatchRecursive, 1);
QCOMPARE(items.count(), 1);
}
void tst_QTreeWidget::sortItems_data()
{
QTest::addColumn<int>("column");
QTest::addColumn<int>("order");
QTest::addColumn<QStringList>("topLevelText");
QTest::addColumn<QStringList>("childText");
QTest::addColumn<QStringList>("topLevelResult");
QTest::addColumn<QStringList>("childResult");
QTest::addColumn<IntList>("expectedTopRows");
QTest::addColumn<IntList>("expectedChildRows");
QTest::newRow("ascending order")
<< 0
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "c" << "d" << "a" << "b")
<< (QStringList() << "e" << "h" << "g" << "f")
<< (QStringList() << "a" << "b" << "c" << "d")
<< (QStringList() << "e" << "f" << "g" << "h")
<< (IntList() << 2 << 3 << 0 << 1)
<< (IntList() << 0 << 3 << 2 << 1);
QTest::newRow("descending order")
<< 0
<< static_cast<int>(Qt::DescendingOrder)
<< (QStringList() << "c" << "d" << "a" << "b")
<< (QStringList() << "e" << "h" << "g" << "f")
<< (QStringList() << "d" << "c" << "b" << "a")
<< (QStringList() << "h" << "g" << "f" << "e")
<< (IntList() << 1 << 0 << 3 << 2)
<< (IntList() << 3 << 0 << 1 << 2);
}
void tst_QTreeWidget::sortItems()
{
QFETCH(int, column);
QFETCH(int, order);
QFETCH(QStringList, topLevelText);
QFETCH(QStringList, childText);
QFETCH(QStringList, topLevelResult);
QFETCH(QStringList, childResult);
QFETCH(IntList, expectedTopRows);
QFETCH(IntList, expectedChildRows);
testWidget->setSortingEnabled(false);
for (int i = 0; i < topLevelText.count(); ++i) {
QTreeWidgetItem *item = new QTreeWidgetItem(testWidget);
item->setText(column, topLevelText.at(i));
for (int j = 0; j < childText.count(); ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(item);
child->setText(column, childText.at(j));
}
}
QAbstractItemModel *model = testWidget->model();
QList<QPersistentModelIndex> tops;
for (int r = 0; r < model->rowCount(QModelIndex()); ++r) {
QPersistentModelIndex p = model->index(r, 0, QModelIndex());
tops << p;
}
QList<QPersistentModelIndex> children;
for (int s = 0; s < model->rowCount(tops.first()); ++s) {
QPersistentModelIndex c = model->index(s, 0, tops.first());
children << c;
}
testWidget->sortItems(column, static_cast<Qt::SortOrder>(order));
QCOMPARE(testWidget->sortColumn(), column);
for (int k = 0; k < topLevelResult.count(); ++k) {
QTreeWidgetItem *item = testWidget->topLevelItem(k);
QCOMPARE(item->text(column), topLevelResult.at(k));
for (int l = 0; l < childResult.count(); ++l)
QCOMPARE(item->child(l)->text(column), childResult.at(l));
}
for (int m = 0; m < tops.count(); ++m)
QCOMPARE(tops.at(m).row(), expectedTopRows.at(m));
for (int n = 0; n < children.count(); ++n)
QCOMPARE(children.at(n).row(), expectedChildRows.at(n));
}
void tst_QTreeWidget::deleteItems_data()
{
QTest::addColumn<int>("topLevelCount");
QTest::addColumn<int>("childCount");
QTest::addColumn<int>("grandChildCount");
QTest::addColumn<int>("deleteTopLevelCount");
QTest::addColumn<int>("deleteChildCount");
QTest::addColumn<int>("deleteGrandChildCount");
QTest::addColumn<int>("expectedTopLevelCount");
QTest::addColumn<int>("expectedChildCount");
QTest::addColumn<int>("expectedGrandChildCount");
QTest::addColumn<int>("persistentRow");
QTest::addColumn<int>("persistentColumn");
QTest::addColumn<bool>("persistentIsValid");
QTest::newRow("start with 10, delete 1")
<< 10 << 10 << 10
<< 1 << 1 << 1
<< 9 << 9 << 9
<< 0 << 0 << false;
QTest::newRow("start with 10, delete 5")
<< 10 << 10 << 10
<< 5 << 5 << 5
<< 5 << 5 << 5
<< 0 << 0 << false;
QTest::newRow("mixed")
<< 10 << 13 << 7
<< 3 << 7 << 4
<< 7 << 6 << 3
<< 0 << 0 << false;
QTest::newRow("all")
<< 10 << 10 << 10
<< 10 << 10 << 10
<< 0 << 0 << 0
<< 0 << 0 << false;
}
void tst_QTreeWidget::deleteItems()
{
QFETCH(int, topLevelCount);
QFETCH(int, childCount);
QFETCH(int, grandChildCount);
QFETCH(int, deleteTopLevelCount);
QFETCH(int, deleteChildCount);
QFETCH(int, deleteGrandChildCount);
QFETCH(int, expectedTopLevelCount);
QFETCH(int, expectedChildCount);
QFETCH(int, expectedGrandChildCount);
QFETCH(int, persistentRow);
QFETCH(int, persistentColumn);
QFETCH(bool, persistentIsValid);
for (int i = 0; i < topLevelCount; ++i) {
QTreeWidgetItem *top = new QTreeWidgetItem(testWidget);
for (int j = 0; j < childCount; ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(top);
for (int k = 0; k < grandChildCount; ++k) {
new QTreeWidgetItem(child);
}
}
}
QPersistentModelIndex persistent = testWidget->model()->index(persistentRow,
persistentColumn);
QVERIFY(persistent.isValid());
QTreeWidgetItem *top = testWidget->topLevelItem(0);
QTreeWidgetItem *child = top->child(0);
for (int n = 0; n < deleteGrandChildCount; ++n)
delete child->child(0);
QCOMPARE(child->childCount(), expectedGrandChildCount);
for (int m = 0; m < deleteChildCount; ++m)
delete top->child(0);
QCOMPARE(top->childCount(), expectedChildCount);
for (int l = 0; l < deleteTopLevelCount; ++l)
delete testWidget->topLevelItem(0);
QCOMPARE(testWidget->topLevelItemCount(), expectedTopLevelCount);
QCOMPARE(persistent.isValid(), persistentIsValid);
}
void tst_QTreeWidget::itemAboveOrBelow()
{
QTreeWidget tw;
tw.setColumnCount(1);
QTreeWidgetItem *twi = new QTreeWidgetItem(&tw, QStringList() << "Test");
QTreeWidgetItem *twi2 = new QTreeWidgetItem(&tw, QStringList() << "Test 2");
QTreeWidgetItem *twi3 = new QTreeWidgetItem(&tw, QStringList() << "Test 3");
tw.show();
QCOMPARE(tw.itemAbove(twi2), twi);
QCOMPARE(tw.itemBelow(twi2), twi3);
}
void tst_QTreeWidget::itemStreaming_data()
{
QTest::addColumn<QString>("text");
QTest::addColumn<QString>("toolTip");
QTest::addColumn<int>("column");
QTest::newRow("Data") << "item text" << "tool tip text" << 0;
}
void tst_QTreeWidget::itemStreaming()
{
QFETCH(QString, text);
QFETCH(QString, toolTip);
QFETCH(int, column);
QTreeWidgetItem item(testWidget);
QCOMPARE(item.text(column), QString());
QCOMPARE(item.toolTip(column), QString());
item.setText(column, text);
item.setToolTip(column, toolTip);
QCOMPARE(item.text(column), text);
QCOMPARE(item.toolTip(column), toolTip);
QByteArray buffer;
QDataStream out(&buffer, QIODevice::WriteOnly);
out << item;
QTreeWidgetItem item2(testWidget);
QCOMPARE(item2.text(column), QString());
QCOMPARE(item2.toolTip(column), QString());
QVERIFY(!buffer.isEmpty());
QDataStream in(&buffer, QIODevice::ReadOnly);
in >> item2;
QCOMPARE(item2.text(column), text);
QCOMPARE(item2.toolTip(column), toolTip);
}
void tst_QTreeWidget::insertTopLevelItems_data()
{
QTest::addColumn<QStringList>("initialText");
QTest::addColumn<QStringList>("insertText");
QTest::addColumn<int>("insertTopLevelIndex");
QTest::addColumn<int>("expectedTopLevelIndex");
QTest::addColumn<int>("insertChildIndex");
QTest::addColumn<int>("expectedChildIndex");
QStringList initial = (QStringList() << "foo" << "bar");
QStringList insert = (QStringList() << "baz");
QTest::newRow("Insert at count") << initial << insert
<< initial.count() << initial.count()
<< initial.count() << initial.count();
QTest::newRow("Insert in the middle") << initial << insert
<< (initial.count() / 2) << (initial.count() / 2)
<< (initial.count() / 2) << (initial.count() / 2);
QTest::newRow("Insert less than 0") << initial << insert
<< -1 << -1
<< -1 << -1;
QTest::newRow("Insert beyond count") << initial << insert
<< initial.count() + 1 << -1
<< initial.count() + 1 << -1;
}
void tst_QTreeWidget::insertTopLevelItems()
{
QFETCH(QStringList, initialText);
QFETCH(QStringList, insertText);
QFETCH(int, insertTopLevelIndex);
QFETCH(int, expectedTopLevelIndex);
QFETCH(int, insertChildIndex);
QFETCH(int, expectedChildIndex);
testWidget->setSortingEnabled(false);
{ // insert the initial items
QCOMPARE(testWidget->topLevelItemCount(), 0);
for (int i = 0; i < initialText.count(); ++i) {
QTreeWidgetItem *top = new QTreeWidgetItem(QStringList(initialText.at(i)));
testWidget->addTopLevelItem(top);
QCOMPARE(testWidget->indexOfTopLevelItem(top), i);
}
QCOMPARE(testWidget->topLevelItemCount(), initialText.count());
}
{ // test adding children
QTreeWidgetItem *topLevel = testWidget->topLevelItem(0);
for (int i = 0; i < initialText.count(); ++i)
topLevel->addChild(new QTreeWidgetItem(QStringList(initialText.at(i))));
QCOMPARE(topLevel->childCount(), initialText.count());
}
{ // test adding more top level items
QTreeWidgetItem *topsy = new QTreeWidgetItem(QStringList(insertText.at(0)));
testWidget->insertTopLevelItem(insertTopLevelIndex, topsy);
if (expectedTopLevelIndex == -1) {
QCOMPARE(testWidget->topLevelItemCount(), initialText.count());
delete topsy;
} else {
QTreeWidgetItem *item = testWidget->topLevelItem(expectedTopLevelIndex);
QVERIFY(item != 0);
QCOMPARE(item->text(0), insertText.at(0));
QCOMPARE(testWidget->indexOfTopLevelItem(item), expectedTopLevelIndex);
}
}
{ // test adding more children
QTreeWidgetItem *topLevel = testWidget->topLevelItem(0);
QVERIFY(topLevel != 0);
QTreeWidgetItem *child = new QTreeWidgetItem(QStringList(insertText.at(0)));
topLevel->insertChild(insertChildIndex, child);
if (expectedChildIndex == -1) {
QCOMPARE(topLevel->childCount(), initialText.count());
delete child;
} else {
QTreeWidgetItem *item = topLevel->child(expectedChildIndex);
QVERIFY(item != 0);
QCOMPARE(item->text(0), insertText.at(0));
}
}
}
static void fillTreeWidget(QTreeWidgetItem *parent, int rows)
{
const int columns = parent->treeWidget()->columnCount();
for (int r = 0; r < rows; ++r) {
QTreeWidgetItem *w = new QTreeWidgetItem(parent);
for ( int c = 0; c < columns; ++c ) {
QString s = QString("[r:%1,c:%2]").arg(r).arg(c);
w->setText(c, s);
}
fillTreeWidget(w, rows - r - 1);
}
}
static void fillTreeWidget(QTreeWidget *tree, int rows)
{
for (int r = 0; r < rows; ++r) {
QTreeWidgetItem *w = new QTreeWidgetItem();
for ( int c = 0; c < tree->columnCount(); ++c ) {
QString s = QString("[r:%1,c:%2]").arg(r).arg(c);
w->setText(c, s);
}
tree->insertTopLevelItem(r, w);
fillTreeWidget(w, rows - r - 1);
}
}
void tst_QTreeWidget::keyboardNavigation()
{
int rows = 8;
fillTreeWidget(testWidget, rows);
QVector<Qt::Key> keymoves;
keymoves << Qt::Key_Down << Qt::Key_Right << Qt::Key_Left
<< Qt::Key_Down << Qt::Key_Down << Qt::Key_Down << Qt::Key_Down
<< Qt::Key_Right
<< Qt::Key_Up << Qt::Key_Left << Qt::Key_Left
<< Qt::Key_Up << Qt::Key_Down << Qt::Key_Up << Qt::Key_Up
<< Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up
<< Qt::Key_Down << Qt::Key_Right << Qt::Key_Down << Qt::Key_Down
<< Qt::Key_Down << Qt::Key_Right << Qt::Key_Down << Qt::Key_Down
<< Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down
<< Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Left
<< Qt::Key_Down << Qt::Key_Right << Qt::Key_Right << Qt::Key_Right
<< Qt::Key_Left << Qt::Key_Left << Qt::Key_Right << Qt::Key_Left;
int row = 0;
QTreeWidgetItem *item = testWidget->topLevelItem(0);
testWidget->setCurrentItem(item);
QCOMPARE(testWidget->currentItem(), item);
QApplication::instance()->processEvents();
QScrollBar *scrollBar = testWidget->horizontalScrollBar();
bool checkScroll = false;
for (int i = 0; i < keymoves.size(); ++i) {
Qt::Key key = keymoves.at(i);
int valueBeforeClick = scrollBar->value();
if (valueBeforeClick >= scrollBar->singleStep())
checkScroll = true;
else
checkScroll = false;
QTest::keyClick(testWidget, key);
QApplication::instance()->processEvents();
switch (key) {
case Qt::Key_Up:
if (row > 0) {
if (item->parent())
item = item->parent()->child(row - 1);
else
item = testWidget->topLevelItem(row - 1);
row -= 1;
} else if (item->parent()) {
item = item->parent();
row = item->parent() ? item->parent()->indexOfChild(item) : testWidget->indexOfTopLevelItem(item);
}
break;
case Qt::Key_Down:
if (testWidget->isItemExpanded(item)) {
row = 0;
item = item->child(row);
} else {
row = qMin(rows - 1, row + 1);
if (item->parent())
item = item->parent()->child(row);
else
item = testWidget->topLevelItem(row);
}
break;
case Qt::Key_Left:
if (checkScroll) {
QVERIFY(testWidget->isItemExpanded(item));
QCOMPARE(scrollBar->value(), valueBeforeClick - scrollBar->singleStep());
}
// windows style right will walk to the parent
if (testWidget->currentItem() != item) {
QCOMPARE(testWidget->currentItem(), item->parent());
item = testWidget->currentItem();
row = item->parent() ? item->parent()->indexOfChild(item) : testWidget->indexOfTopLevelItem(item);;
}
break;
case Qt::Key_Right:
if (checkScroll)
QCOMPARE(scrollBar->value(), valueBeforeClick + scrollBar->singleStep());
// windows style right will walk to the first child
if (testWidget->currentItem() != item) {
QCOMPARE(testWidget->currentItem()->parent(), item);
row = item->indexOfChild(testWidget->currentItem());
item = testWidget->currentItem();
QCOMPARE(row, 0);
}
break;
default:
QVERIFY(false);
}
QTreeWidgetItem *current = testWidget->currentItem();
QCOMPARE(current->text(0), QString("[r:%1,c:0]").arg(row));
if (current->parent())
QCOMPARE(current->parent()->indexOfChild(current), row);
else
QCOMPARE(testWidget->indexOfTopLevelItem(current), row);
}
}
void tst_QTreeWidget::scrollToItem()
{
// Check if all parent nodes of the item found are expanded.
// Reported in task #78761
QTreeWidgetItem *bar;
QTreeWidgetItem *search;
for (int i=0; i<2; ++i) {
bar = new QTreeWidgetItem(testWidget);
bar->setText(0, QString::number(i));
for (int j=0; j<2; ++j) {
QTreeWidgetItem *foo = new QTreeWidgetItem(bar);
foo->setText(0, bar->text(0) + QString::number(j));
for (int k=0; k<2; ++k) {
QTreeWidgetItem *yo = new QTreeWidgetItem(foo);
yo->setText(0, foo->text(0) + QString::number(k));
search = yo;
}
}
}
testWidget->setHeaderLabels(QStringList() << "foo");
testWidget->scrollToItem(search);
QVERIFY(search->text(0) == "111");
bar = search->parent();
QVERIFY(testWidget->isItemExpanded(bar));
bar = bar->parent();
QVERIFY(testWidget->isItemExpanded(bar));
}
// From task #85413
void tst_QTreeWidget::setSortingEnabled()
{
QStringList hl;
hl << "ID";
testWidget->setColumnCount(hl.count());
testWidget->setHeaderLabels(hl);
QTreeWidgetItem *item1 = new QTreeWidgetItem(testWidget);
QTreeWidgetItem *item2 = new QTreeWidgetItem(testWidget);
testWidget->setSortingEnabled(true);
QCOMPARE(testWidget->isSortingEnabled(), true);
QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
QCOMPARE(testWidget->topLevelItem(0), item1);
QCOMPARE(testWidget->topLevelItem(1), item2);
// Make sure we do it twice
testWidget->setSortingEnabled(true);
QCOMPARE(testWidget->isSortingEnabled(), true);
QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
testWidget->setSortingEnabled(false);
QCOMPARE(testWidget->isSortingEnabled(), false);
QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
testWidget->setSortingEnabled(false);
QCOMPARE(testWidget->isSortingEnabled(), false);
QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
// And back again so that we make sure that we test the transition from false to true
testWidget->setSortingEnabled(true);
QCOMPARE(testWidget->isSortingEnabled(), true);
QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
testWidget->setSortingEnabled(true);
QCOMPARE(testWidget->isSortingEnabled(), true);
QCOMPARE(testWidget->isSortingEnabled(), testWidget->header()->isSortIndicatorShown());
testWidget->setSortingEnabled(false);
}
void tst_QTreeWidget::addChild()
{
QTreeWidget tree;
for (int x = 0; x < 2; ++x) {
QTreeWidget *view = x ? &tree : static_cast<QTreeWidget*>(0);
QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)view);
QCOMPARE(item->childCount(), 0);
// try to add 0
item->addChild(0);
QCOMPARE(item->childCount(), 0);
QCOMPARE(item->indexOfChild(0), -1);
// add one at a time
QList<QTreeWidgetItem*> children;
for (int i = 0; i < 10; ++i) {
QTreeWidgetItem *child = new QTreeWidgetItem();
item->addChild(child);
QCOMPARE(item->childCount(), i+1);
QCOMPARE(item->child(i), child);
QCOMPARE(item->indexOfChild(child), i);
QCOMPARE(child->parent(), item);
QCOMPARE(child->treeWidget(), view);
item->addChild(child);
QCOMPARE(item->childCount(), i+1);
children.append(child);
}
// take them all
QList<QTreeWidgetItem*> taken = item->takeChildren();
QCOMPARE(taken, children);
QCOMPARE(item->childCount(), 0);
for (int i = 0; i < taken.count(); ++i) {
QCOMPARE(taken.at(i)->parent(), static_cast<QTreeWidgetItem*>(0));
QCOMPARE(taken.at(i)->treeWidget(), static_cast<QTreeWidget*>(0));
item->addChild(taken.at(i)); // re-add
}
// delete one at a time
while (!children.isEmpty()) {
QTreeWidgetItem *ti = children.takeFirst();
delete ti;
QCOMPARE(item->childCount(), children.count());
for (int i = 0; i < children.count(); ++i)
QCOMPARE(item->child(i), children.at(i));
}
// add none
{
int count = item->childCount();
item->addChildren(QList<QTreeWidgetItem*>());
QCOMPARE(item->childCount(), count);
}
// add many at a time
const int count = 10;
for (int i = 0; i < 100; i += count) {
QList<QTreeWidgetItem*> list;
for (int j = 0; j < count; ++j)
list << new QTreeWidgetItem(QStringList() << QString("%0").arg(j));
item->addChildren(list);
QCOMPARE(item->childCount(), count + i);
for (int j = 0; j < count; ++j) {
QCOMPARE(item->child(i+j), list.at(j));
QCOMPARE(item->child(i+j)->parent(), item);
}
item->addChildren(list);
QCOMPARE(item->childCount(), count + i);
}
if (!view)
delete item;
}
}
void tst_QTreeWidget::setData()
{
{
QTreeWidgetItem *headerItem = new QTreeWidgetItem();
headerItem->setText(0, "Item1");
testWidget->setHeaderItem(headerItem);
QSignalSpy headerDataChangedSpy(
testWidget->model(), SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
QSignalSpy dataChangedSpy(
testWidget->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
QSignalSpy itemChangedSpy(
testWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)));
headerItem->setText(0, "test");
QCOMPARE(dataChangedSpy.count(), 0);
QCOMPARE(headerDataChangedSpy.count(), 1);
QCOMPARE(itemChangedSpy.count(), 0); // no itemChanged() signal for header item
headerItem->setData(-1, -1, QVariant());
}
{
QSignalSpy itemChangedSpy(
testWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)));
QTreeWidgetItem *item = new QTreeWidgetItem();
testWidget->addTopLevelItem(item);
for (int x = 0; x < 2; ++x) {
for (int i = 1; i <= 2; ++i) {
for (int j = 0; j < 5; ++j) {
QVariantList args;
QString text = QString("text %0").arg(i);
item->setText(j, text);
QCOMPARE(item->text(j), text);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setText(j, text);
QCOMPARE(itemChangedSpy.count(), 0);
QPixmap pixmap(32, 32);
pixmap.fill((i == 1) ? Qt::red : Qt::green);
QIcon icon(pixmap);
item->setIcon(j, icon);
QCOMPARE(item->icon(j), icon);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setIcon(j, icon);
// #### shouldn't cause dataChanged()
QCOMPARE(itemChangedSpy.count(), 1);
itemChangedSpy.clear();
QString toolTip = QString("toolTip %0").arg(i);
item->setToolTip(j, toolTip);
QCOMPARE(item->toolTip(j), toolTip);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setToolTip(j, toolTip);
QCOMPARE(itemChangedSpy.count(), 0);
QString statusTip = QString("statusTip %0").arg(i);
item->setStatusTip(j, statusTip);
QCOMPARE(item->statusTip(j), statusTip);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setStatusTip(j, statusTip);
QCOMPARE(itemChangedSpy.count(), 0);
QString whatsThis = QString("whatsThis %0").arg(i);
item->setWhatsThis(j, whatsThis);
QCOMPARE(item->whatsThis(j), whatsThis);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setWhatsThis(j, whatsThis);
QCOMPARE(itemChangedSpy.count(), 0);
QSize sizeHint(64*i, 48*i);
item->setSizeHint(j, sizeHint);
QCOMPARE(item->sizeHint(j), sizeHint);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setSizeHint(j, sizeHint);
QCOMPARE(itemChangedSpy.count(), 0);
QFont font;
item->setFont(j, font);
QCOMPARE(item->font(j), font);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setFont(j, font);
QCOMPARE(itemChangedSpy.count(), 0);
Qt::Alignment textAlignment((i == 1)
? Qt::AlignLeft|Qt::AlignVCenter
: Qt::AlignRight);
item->setTextAlignment(j, textAlignment);
QCOMPARE(item->textAlignment(j), int(textAlignment));
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setTextAlignment(j, textAlignment);
QCOMPARE(itemChangedSpy.count(), 0);
QColor backgroundColor((i == 1) ? Qt::blue : Qt::yellow);
item->setBackground(j, backgroundColor);
QCOMPARE(item->background(j).color(), backgroundColor);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setBackground(j, backgroundColor);
QCOMPARE(itemChangedSpy.count(), 0);
QColor textColor((i == 1) ? Qt::green : Qt::cyan);
item->setTextColor(j, textColor);
QCOMPARE(item->textColor(j), textColor);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setTextColor(j, textColor);
QCOMPARE(itemChangedSpy.count(), 0);
Qt::CheckState checkState((i == 1) ? Qt::PartiallyChecked : Qt::Checked);
item->setCheckState(j, checkState);
QCOMPARE(item->checkState(j), checkState);
QCOMPARE(itemChangedSpy.count(), 1);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setCheckState(j, checkState);
QCOMPARE(itemChangedSpy.count(), 0);
QCOMPARE(item->text(j), text);
QCOMPARE(item->icon(j), icon);
QCOMPARE(item->toolTip(j), toolTip);
QCOMPARE(item->statusTip(j), statusTip);
QCOMPARE(item->whatsThis(j), whatsThis);
QCOMPARE(item->sizeHint(j), sizeHint);
QCOMPARE(item->font(j), font);
QCOMPARE(item->textAlignment(j), int(textAlignment));
QCOMPARE(item->background(j).color(), backgroundColor);
QCOMPARE(item->textColor(j), textColor);
QCOMPARE(item->checkState(j), checkState);
QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::DisplayRole)), text);
QCOMPARE(qvariant_cast<QIcon>(item->data(j, Qt::DecorationRole)), icon);
QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::ToolTipRole)), toolTip);
QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::StatusTipRole)), statusTip);
QCOMPARE(qvariant_cast<QString>(item->data(j, Qt::WhatsThisRole)), whatsThis);
QCOMPARE(qvariant_cast<QSize>(item->data(j, Qt::SizeHintRole)), sizeHint);
QCOMPARE(qvariant_cast<QFont>(item->data(j, Qt::FontRole)), font);
QCOMPARE(qvariant_cast<int>(item->data(j, Qt::TextAlignmentRole)), int(textAlignment));
QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundColorRole)), QBrush(backgroundColor));
QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundRole)), QBrush(backgroundColor));
QCOMPARE(qvariant_cast<QColor>(item->data(j, Qt::TextColorRole)), textColor);
QCOMPARE(qvariant_cast<int>(item->data(j, Qt::CheckStateRole)), int(checkState));
item->setBackground(j, pixmap);
QCOMPARE(item->background(j).texture(), pixmap);
QCOMPARE(qvariant_cast<QBrush>(item->data(j, Qt::BackgroundRole)).texture(), pixmap);
args = itemChangedSpy.takeFirst();
QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item);
QCOMPARE(qvariant_cast<int>(args.at(1)), j);
item->setBackground(j, pixmap);
QCOMPARE(itemChangedSpy.count(), 0);
item->setData(j, Qt::DisplayRole, QVariant());
item->setData(j, Qt::DecorationRole, QVariant());
item->setData(j, Qt::ToolTipRole, QVariant());
item->setData(j, Qt::StatusTipRole, QVariant());
item->setData(j, Qt::WhatsThisRole, QVariant());
item->setData(j, Qt::SizeHintRole, QVariant());
item->setData(j, Qt::FontRole, QVariant());
item->setData(j, Qt::TextAlignmentRole, QVariant());
item->setData(j, Qt::BackgroundColorRole, QVariant());
item->setData(j, Qt::TextColorRole, QVariant());
item->setData(j, Qt::CheckStateRole, QVariant());
QCOMPARE(itemChangedSpy.count(), 11);
itemChangedSpy.clear();
QCOMPARE(item->data(j, Qt::DisplayRole).toString(), QString());
QCOMPARE(item->data(j, Qt::DecorationRole), QVariant());
QCOMPARE(item->data(j, Qt::ToolTipRole), QVariant());
QCOMPARE(item->data(j, Qt::StatusTipRole), QVariant());
QCOMPARE(item->data(j, Qt::WhatsThisRole), QVariant());
QCOMPARE(item->data(j, Qt::SizeHintRole), QVariant());
QCOMPARE(item->data(j, Qt::FontRole), QVariant());
QCOMPARE(item->data(j, Qt::TextAlignmentRole), QVariant());
QCOMPARE(item->data(j, Qt::BackgroundColorRole), QVariant());
QCOMPARE(item->data(j, Qt::BackgroundRole), QVariant());
QCOMPARE(item->data(j, Qt::TextColorRole), QVariant());
QCOMPARE(item->data(j, Qt::CheckStateRole), QVariant());
}
}
}
// ### add more data types here
item->setData(0, Qt::DisplayRole, 5);
QCOMPARE(item->data(0, Qt::DisplayRole).type(), QVariant::Int);
item->setData(0, Qt::DisplayRole, "test");
QCOMPARE(item->data(0, Qt::DisplayRole).type(), QVariant::String);
item->setData(0, Qt::DisplayRole, 0.4);
QCOMPARE(item->data(0, Qt::DisplayRole).type(), QVariant::Double);
delete item;
}
}
void tst_QTreeWidget::itemData()
{
QTreeWidget widget;
QTreeWidgetItem item(&widget);
widget.setColumnCount(2);
item.setFlags(item.flags() | Qt::ItemIsEditable);
item.setData(0, Qt::DisplayRole, QString("0"));
item.setData(0, Qt::CheckStateRole, Qt::PartiallyChecked);
item.setData(0, Qt::UserRole + 0, QString("1"));
item.setData(0, Qt::UserRole + 1, QString("2"));
item.setData(0, Qt::UserRole + 2, QString("3"));
item.setData(0, Qt::UserRole + 3, QString("4"));
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
QCOMPARE(flags[Qt::UserRole + 0].toString(), QString("1"));
flags = widget.model()->itemData(widget.model()->index(0, 1));
QCOMPARE(flags.count(), 0);
}
void tst_QTreeWidget::enableDisable()
{
QTreeWidgetItem *itm = new QTreeWidgetItem();
for (int i = 0; i < 10; ++i)
new QTreeWidgetItem(itm);
// make sure all items are enabled
QVERIFY(itm->flags() & Qt::ItemIsEnabled);
for (int j = 0; j < itm->childCount(); ++j)
QVERIFY(itm->child(j)->flags() & Qt::ItemIsEnabled);
// disable root and make sure they are all disabled
itm->setFlags(itm->flags() & ~Qt::ItemIsEnabled);
QVERIFY(!(itm->flags() & Qt::ItemIsEnabled));
for (int k = 0; k < itm->childCount(); ++k)
QVERIFY(!(itm->child(k)->flags() & Qt::ItemIsEnabled));
// disable a child and make sure they are all still disabled
itm->child(5)->setFlags(itm->child(5)->flags() & ~Qt::ItemIsEnabled);
QVERIFY(!(itm->flags() & Qt::ItemIsEnabled));
for (int l = 0; l < itm->childCount(); ++l)
QVERIFY(!(itm->child(l)->flags() & Qt::ItemIsEnabled));
// enable root and make sure all items except one are enabled
itm->setFlags(itm->flags() | Qt::ItemIsEnabled);
QVERIFY(itm->flags() & Qt::ItemIsEnabled);
for (int m = 0; m < itm->childCount(); ++m)
if (m == 5)
QVERIFY(!(itm->child(m)->flags() & Qt::ItemIsEnabled));
else
QVERIFY(itm->child(m)->flags() & Qt::ItemIsEnabled);
}
void tst_QTreeWidget::match()
{
QTreeWidget tree;
QModelIndexList list = tree.model()->match(QModelIndex(), Qt::DisplayRole, QString());
QVERIFY(list.isEmpty());
}
void tst_QTreeWidget::columnCount()
{
int columnCountBefore = testWidget->columnCount();
testWidget->setColumnCount(-1);
QCOMPARE(testWidget->columnCount(), columnCountBefore);
}
void tst_QTreeWidget::setHeaderLabels()
{
QStringList list = QString("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z").split(",");
testWidget->setHeaderLabels(list);
QCOMPARE(testWidget->header()->count(), list.count());
}
void tst_QTreeWidget::setHeaderItem()
{
testWidget->setHeaderItem(0);
QTreeWidgetItem *headerItem = new QTreeWidgetItem();
testWidget->setColumnCount(0);
QCOMPARE(testWidget->header()->count(), 0);
QCOMPARE(testWidget->columnCount(), 0);
headerItem->setText(0, "0");
headerItem->setText(1, "1");
testWidget->setHeaderItem(headerItem);
QTest::qWait(100);
QCOMPARE(testWidget->headerItem(), headerItem);
QCOMPARE(headerItem->treeWidget(), static_cast<QTreeWidget *>(testWidget));
QCOMPARE(testWidget->header()->count(), 2);
QCOMPARE(testWidget->columnCount(), 2);
headerItem->setText(2, "2");
QCOMPARE(testWidget->header()->count(), 3);
QCOMPARE(testWidget->columnCount(), 3);
delete headerItem;
testWidget->setColumnCount(3);
testWidget->setColumnCount(5);
QCOMPARE(testWidget->model()->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(), QString("1"));
QCOMPARE(testWidget->model()->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString(), QString("2"));
QCOMPARE(testWidget->model()->headerData(2, Qt::Horizontal, Qt::DisplayRole).toString(), QString("3"));
QCOMPARE(testWidget->model()->headerData(3, Qt::Horizontal, Qt::DisplayRole).toString(), QString("4"));
QCOMPARE(testWidget->model()->headerData(4, Qt::Horizontal, Qt::DisplayRole).toString(), QString("5"));
headerItem = new QTreeWidgetItem();
testWidget->setHeaderItem(headerItem);
testWidget->model()->insertColumns(0, 5, QModelIndex());
QCOMPARE(testWidget->model()->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(), QString("1"));
QCOMPARE(testWidget->model()->headerData(1, Qt::Horizontal, Qt::DisplayRole).toString(), QString("2"));
QCOMPARE(testWidget->model()->headerData(2, Qt::Horizontal, Qt::DisplayRole).toString(), QString("3"));
QCOMPARE(testWidget->model()->headerData(3, Qt::Horizontal, Qt::DisplayRole).toString(), QString("4"));
QCOMPARE(testWidget->model()->headerData(4, Qt::Horizontal, Qt::DisplayRole).toString(), QString("5"));
}
void tst_QTreeWidget::itemWidget_data()
{
editItem_data();
}
void tst_QTreeWidget::itemWidget()
{
QFETCH(TreeItemList, topLevelItems);
QTreeWidget tree;
populate(&tree, topLevelItems, new TreeItem(QStringList() << "1" << "2"));
tree.show();
for (int x = 0; x < 2; ++x) {
QTreeWidgetItemIterator it(&tree);
while (QTreeWidgetItem *item = (*it++)) {
for (int col = 0; col < item->columnCount(); ++col) {
if (x == 0) {
QCOMPARE(tree.itemWidget(item, col), static_cast<QWidget*>(0));
QWidget *editor = new QLineEdit();
tree.setItemWidget(item, col, editor);
QCOMPARE(tree.itemWidget(item, col), editor);
tree.removeItemWidget(item, col);
QCOMPARE(tree.itemWidget(item, col), static_cast<QWidget*>(0));
} else {
// ### should you really be able to open a persistent
// editor for an item that isn't editable??
tree.openPersistentEditor(item, col);
QWidget *editor = qFindChild<QLineEdit*>(&tree);
QVERIFY(editor != 0);
tree.closePersistentEditor(item, col);
}
}
}
}
}
void tst_QTreeWidget::insertItemsWithSorting_data()
{
QTest::addColumn<int>("sortOrder");
QTest::addColumn<QStringList>("initialItems");
QTest::addColumn<QStringList>("insertItems");
QTest::addColumn<QStringList>("expectedItems");
QTest::addColumn<IntList>("expectedRows");
QTest::newRow("() + (a) = (a)")
<< static_cast<int>(Qt::AscendingOrder)
<< QStringList()
<< (QStringList() << "a")
<< (QStringList() << "a")
<< IntList();
QTest::newRow("() + (c, b, a) = (a, b, c)")
<< static_cast<int>(Qt::AscendingOrder)
<< QStringList()
<< (QStringList() << "c" << "b" << "a")
<< (QStringList() << "a" << "b" << "c")
<< IntList();
QTest::newRow("() + (a, b, c) = (c, b, a)")
<< static_cast<int>(Qt::DescendingOrder)
<< QStringList()
<< (QStringList() << "a" << "b" << "c")
<< (QStringList() << "c" << "b" << "a")
<< IntList();
QTest::newRow("(a) + (b) = (a, b)")
<< static_cast<int>(Qt::AscendingOrder)
<< QStringList("a")
<< (QStringList() << "b")
<< (QStringList() << "a" << "b")
<< (IntList() << 0);
QTest::newRow("(a) + (b) = (b, a)")
<< static_cast<int>(Qt::DescendingOrder)
<< QStringList("a")
<< (QStringList() << "b")
<< (QStringList() << "b" << "a")
<< (IntList() << 1);
QTest::newRow("(a, c, b) + (d) = (a, b, c, d)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "b")
<< (QStringList() << "d")
<< (QStringList() << "a" << "b" << "c" << "d")
<< (IntList() << 0 << 1 << 2);
QTest::newRow("(b, c, a) + (d) = (d, c, b, a)")
<< static_cast<int>(Qt::DescendingOrder)
<< (QStringList() << "b" << "c" << "a")
<< (QStringList() << "d")
<< (QStringList() << "d" << "c" << "b" << "a")
<< (IntList() << 1 << 2 << 3);
{
IntList ascendingRows;
IntList reverseRows;
QStringList ascendingItems;
QStringList reverseItems;
for (int i = 'a'; i <= 'z'; ++i) {
ascendingItems << QString("%0").arg(QLatin1Char(i));
reverseItems << QString("%0").arg(QLatin1Char('z' - i + 'a'));
ascendingRows << i - 'a';
reverseRows << 'z' - i + 'a';
}
QTest::newRow("() + (sorted items) = (sorted items)")
<< static_cast<int>(Qt::AscendingOrder)
<< QStringList()
<< ascendingItems
<< ascendingItems
<< IntList();
QTest::newRow("(sorted items) + () = (sorted items)")
<< static_cast<int>(Qt::AscendingOrder)
<< ascendingItems
<< QStringList()
<< ascendingItems
<< ascendingRows;
QTest::newRow("() + (ascending items) = (reverse items)")
<< static_cast<int>(Qt::DescendingOrder)
<< QStringList()
<< ascendingItems
<< reverseItems
<< IntList();
QTest::newRow("(reverse items) + () = (ascending items)")
<< static_cast<int>(Qt::AscendingOrder)
<< reverseItems
<< QStringList()
<< ascendingItems
<< ascendingRows;
QTest::newRow("(reverse items) + () = (reverse items)")
<< static_cast<int>(Qt::DescendingOrder)
<< reverseItems
<< QStringList()
<< reverseItems
<< ascendingRows;
}
}
void tst_QTreeWidget::insertItemsWithSorting()
{
QFETCH(int, sortOrder);
QFETCH(QStringList, initialItems);
QFETCH(QStringList, insertItems);
QFETCH(QStringList, expectedItems);
QFETCH(IntList, expectedRows);
for (int method = 0; method < 5; ++method) {
QTreeWidget w;
w.setSortingEnabled(true);
w.sortItems(0, static_cast<Qt::SortOrder>(sortOrder));
for (int i = 0; i < initialItems.count(); ++i)
w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i)));
QAbstractItemModel *model = w.model();
QList<QPersistentModelIndex> persistent;
for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
persistent << model->index(j, 0, QModelIndex());
switch (method) {
case 0:
// insert using item constructor
for (int i = 0; i < insertItems.size(); ++i)
new QTreeWidgetItem(&w, QStringList() << insertItems.at(i));
break;
case 1:
{
// insert using insertTopLevelItems()
QList<QTreeWidgetItem*> lst;
for (int i = 0; i < insertItems.size(); ++i)
lst << new QTreeWidgetItem(QStringList() << insertItems.at(i));
w.insertTopLevelItems(0, lst);
break;
}
case 2:
// insert using insertTopLevelItem()
for (int i = 0; i < insertItems.size(); ++i)
w.insertTopLevelItem(0, new QTreeWidgetItem(QStringList() << insertItems.at(i)));
break;
case 3:
{
// insert using addTopLevelItems()
QList<QTreeWidgetItem*> lst;
for (int i = 0; i < insertItems.size(); ++i)
lst << new QTreeWidgetItem(QStringList() << insertItems.at(i));
w.addTopLevelItems(lst);
break;
}
case 4:
// insert using addTopLevelItem()
for (int i = 0; i < insertItems.size(); ++i)
w.addTopLevelItem(new QTreeWidgetItem(QStringList() << insertItems.at(i)));
break;
}
QCOMPARE(w.topLevelItemCount(), expectedItems.count());
for (int i = 0; i < w.topLevelItemCount(); ++i)
QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i));
for (int k = 0; k < persistent.count(); ++k)
QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
}
}
void tst_QTreeWidget::insertExpandedItemsWithSorting_data()
{
QTest::addColumn<QStringList>("parentText");
QTest::addColumn<QStringList>("childText");
QTest::addColumn<QStringList>("parentResult");
QTest::addColumn<QStringList>("childResult");
QTest::newRow("test 1")
<< (QStringList() << "c" << "d" << "a" << "b")
<< (QStringList() << "e" << "h" << "g" << "f")
<< (QStringList() << "d" << "c" << "b" << "a")
<< (QStringList() << "h" << "g" << "f" << "e");
}
// From Task 134978
void tst_QTreeWidget::insertExpandedItemsWithSorting()
{
QFETCH(QStringList, parentText);
QFETCH(QStringList, childText);
QFETCH(QStringList, parentResult);
QFETCH(QStringList, childResult);
// create a tree with autosorting enabled
CustomTreeWidget tree;
tree.setSortingEnabled(true);
// insert expanded items in unsorted order
QList<QTreeWidgetItem *> items;
for (int i = 0; i < parentText.count(); ++i) {
QTreeWidgetItem *parent = new QTreeWidgetItem(&tree, QStringList(parentText.at(i)));
parent->setExpanded(true);
QVERIFY(parent->isExpanded());
items << parent;
for (int j = 0; j < childText.count(); ++j) {
QTreeWidgetItem *child = new QTreeWidgetItem(parent, QStringList(childText.at(j)));
items << child;
}
QCOMPARE(parent->childCount(), childText.count());
QVERIFY(parent->isExpanded());
}
QVERIFY(tree.model()->rowCount() == parentText.count());
// verify that the items are still expanded
foreach (QTreeWidgetItem *item, items) {
if (item->childCount() > 0)
QVERIFY(item->isExpanded());
QModelIndex idx = tree.indexFromItem(const_cast<QTreeWidgetItem *>(item));
QVERIFY(idx.isValid());
//QRect rect = tree.visualRect(idx);
//QVERIFY(rect.isValid());
// ### it is not guarantied that the index is in the viewport
}
// verify that the tree is sorted
QAbstractItemModel *model = tree.model();
QList<QPersistentModelIndex> parents;
for (int i = 0; i < model->rowCount(QModelIndex()); ++i) {
QPersistentModelIndex parent = model->index(i, 0, QModelIndex());
parents << parent;
}
QList<QPersistentModelIndex> children;
for (int i = 0; i < model->rowCount(parents.first()); ++i) {
QPersistentModelIndex child = model->index(i, 0, parents.first());
children << child;
}
for (int i = 0; i < parentResult.count(); ++i) {
QTreeWidgetItem *item = tree.topLevelItem(i);
QCOMPARE(item->text(0), parentResult.at(i));
for (int j = 0; j < childResult.count(); ++j)
QCOMPARE(item->child(j)->text(0), childResult.at(j));
}
}
void tst_QTreeWidget::changeDataWithSorting_data()
{
QTest::addColumn<int>("sortOrder");
QTest::addColumn<QStringList>("initialItems");
QTest::addColumn<int>("itemIndex");
QTest::addColumn<QString>("newValue");
QTest::addColumn<QStringList>("expectedItems");
QTest::addColumn<IntList>("expectedRows");
QTest::addColumn<bool>("reorderingExpected");
QTest::newRow("change a to b in (a)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a")
<< 0 << "b"
<< (QStringList() << "b")
<< (IntList() << 0)
<< false;
QTest::newRow("change a to b in (a, c)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c")
<< 0 << "b"
<< (QStringList() << "b" << "c")
<< (IntList() << 0 << 1)
<< false;
QTest::newRow("change a to c in (a, b)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "b")
<< 0 << "c"
<< (QStringList() << "b" << "c")
<< (IntList() << 1 << 0)
<< true;
QTest::newRow("change c to a in (c, b)")
<< static_cast<int>(Qt::DescendingOrder)
<< (QStringList() << "c" << "b")
<< 0 << "a"
<< (QStringList() << "b" << "a")
<< (IntList() << 1 << 0)
<< true;
QTest::newRow("change e to i in (a, c, e, g)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "e" << "g")
<< 2 << "i"
<< (QStringList() << "a" << "c" << "g" << "i")
<< (IntList() << 0 << 1 << 3 << 2)
<< true;
QTest::newRow("change e to a in (c, e, g, i)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "c" << "e" << "g" << "i")
<< 1 << "a"
<< (QStringList() << "a" << "c" << "g" << "i")
<< (IntList() << 1 << 0 << 2 << 3)
<< true;
QTest::newRow("change e to f in (c, e, g, i)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "c" << "e" << "g" << "i")
<< 1 << "f"
<< (QStringList() << "c" << "f" << "g" << "i")
<< (IntList() << 0 << 1 << 2 << 3)
<< false;
}
void tst_QTreeWidget::changeDataWithSorting()
{
QFETCH(int, sortOrder);
QFETCH(QStringList, initialItems);
QFETCH(int, itemIndex);
QFETCH(QString, newValue);
QFETCH(QStringList, expectedItems);
QFETCH(IntList, expectedRows);
QFETCH(bool, reorderingExpected);
QTreeWidget w;
w.setSortingEnabled(true);
w.sortItems(0, static_cast<Qt::SortOrder>(sortOrder));
for (int i = 0; i < initialItems.count(); ++i)
w.addTopLevelItem(new QTreeWidgetItem(QStringList() << initialItems.at(i)));
QAbstractItemModel *model = w.model();
QList<QPersistentModelIndex> persistent;
for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
persistent << model->index(j, 0, QModelIndex());
QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
QTreeWidgetItem *item = w.topLevelItem(itemIndex);
item->setText(0, newValue);
for (int i = 0; i < expectedItems.count(); ++i) {
QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i));
for (int j = 0; j < persistent.count(); ++j) {
if (persistent.at(j).row() == i) // the same toplevel row
QCOMPARE(persistent.at(j).internalPointer(), (void *)w.topLevelItem(i));
}
}
for (int k = 0; k < persistent.count(); ++k)
QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
QCOMPARE(dataChangedSpy.count(), 1);
QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
}
void tst_QTreeWidget::changeDataWithStableSorting_data()
{
QTest::addColumn<int>("sortOrder");
QTest::addColumn<QStringList>("initialItems");
QTest::addColumn<int>("itemIndex");
QTest::addColumn<QString>("newValue");
QTest::addColumn<QStringList>("expectedItems");
QTest::addColumn<IntList>("expectedRows");
QTest::addColumn<bool>("reorderingExpected");
QTest::addColumn<bool>("forceChange");
QTest::newRow("change a to c in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 0 << "c"
<< (QStringList() << "c" << "c" << "c" << "c" << "e")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< false;
QTest::newRow("change e to c in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 4 << "c"
<< (QStringList() << "a" << "c" << "c" << "c" << "c")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< false;
QTest::newRow("change 1st c to c in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 1 << "c"
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< true;
QTest::newRow("change 2nd c to c in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 2 << "c"
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< true;
QTest::newRow("change 3rd c to c in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 3 << "c"
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< true;
QTest::newRow("change 1st c to c in (e, c, c, c, a)")
<< static_cast<int>(Qt::DescendingOrder)
<< (QStringList() << "e" << "c" << "c" << "c" << "a")
<< 1 << "c"
<< (QStringList() << "e" << "c" << "c" << "c" << "a")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< true;
QTest::newRow("change 2nd c to c in (e, c, c, c, a)")
<< static_cast<int>(Qt::DescendingOrder)
<< (QStringList() << "e" << "c" << "c" << "c" << "a")
<< 2 << "c"
<< (QStringList() << "e" << "c" << "c" << "c" << "a")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< true;
QTest::newRow("change 3rd c to c in (e, c, c, c, a)")
<< static_cast<int>(Qt::DescendingOrder)
<< (QStringList() << "e" << "c" << "c" << "c" << "a")
<< 3 << "c"
<< (QStringList() << "e" << "c" << "c" << "c" << "a")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< true;
QTest::newRow("change 1st c to b in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 1 << "b"
<< (QStringList() << "a" << "b" << "c" << "c" << "e")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< false;
QTest::newRow("change 2nd c to b in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 2 << "b"
<< (QStringList() << "a" << "b" << "c" << "c" << "e")
<< (IntList() << 0 << 2 << 1 << 3 << 4)
<< true
<< false;
QTest::newRow("change 3rd c to b in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 3 << "b"
<< (QStringList() << "a" << "b" << "c" << "c" << "e")
<< (IntList() << 0 << 2 << 3 << 1 << 4)
<< true
<< false;
QTest::newRow("change 1st c to d in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 1 << "d"
<< (QStringList() << "a" << "c" << "c" << "d" << "e")
<< (IntList() << 0 << 3 << 1 << 2 << 4)
<< true
<< false;
QTest::newRow("change 2nd c to d in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 2 << "d"
<< (QStringList() << "a" << "c" << "c" << "d" << "e")
<< (IntList() << 0 << 1 << 3 << 2 << 4)
<< true
<< false;
QTest::newRow("change 3rd c to d in (a, c, c, c, e)")
<< static_cast<int>(Qt::AscendingOrder)
<< (QStringList() << "a" << "c" << "c" << "c" << "e")
<< 3 << "d"
<< (QStringList() << "a" << "c" << "c" << "d" << "e")
<< (IntList() << 0 << 1 << 2 << 3 << 4)
<< false
<< false;
}
void tst_QTreeWidget::changeDataWithStableSorting()
{
QFETCH(int, sortOrder);
QFETCH(QStringList, initialItems);
QFETCH(int, itemIndex);
QFETCH(QString, newValue);
QFETCH(QStringList, expectedItems);
QFETCH(IntList, expectedRows);
QFETCH(bool, reorderingExpected);
QFETCH(bool, forceChange);
class StableItem : public QTreeWidgetItem
{
public:
StableItem(const QStringList &strings) : QTreeWidgetItem(strings, QTreeWidgetItem::UserType) {}
void forceChangeData() {
emitDataChanged();
}
};
QTreeWidget w;
w.setSortingEnabled(true);
w.sortItems(0, static_cast<Qt::SortOrder>(sortOrder));
for (int i = 0; i < initialItems.count(); ++i)
w.addTopLevelItem(new StableItem(QStringList() << initialItems.at(i)));
QAbstractItemModel *model = w.model();
QList<QPersistentModelIndex> persistent;
for (int j = 0; j < model->rowCount(QModelIndex()); ++j)
persistent << model->index(j, 0, QModelIndex());
QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)));
QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged()));
StableItem *item = static_cast<StableItem *>(w.topLevelItem(itemIndex));
item->setText(0, newValue);
if (forceChange)
item->forceChangeData();
for (int i = 0; i < expectedItems.count(); ++i) {
QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i));
for (int j = 0; j < persistent.count(); ++j) {
if (persistent.at(j).row() == i) // the same toplevel row
QCOMPARE(persistent.at(j).internalPointer(), (void *)w.topLevelItem(i));
}
}
for (int k = 0; k < persistent.count(); ++k)
QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
QCOMPARE(dataChangedSpy.count(), 1);
QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0);
}
void tst_QTreeWidget::itemOperatorLessThan()
{
QTreeWidget tw;
tw.setColumnCount(2);
{
QTreeWidgetItem item1(&tw);
QTreeWidgetItem item2(&tw);
QCOMPARE(item1 < item2, false);
item1.setText(1, "a");
item2.setText(1, "b");
QCOMPARE(item1 < item2, false);
item1.setText(0, "a");
item2.setText(0, "b");
QCOMPARE(item1 < item2, true);
tw.sortItems(1, Qt::AscendingOrder);
item1.setText(0, "b");
item2.setText(0, "a");
QCOMPARE(item1 < item2, true);
tw.sortItems(0, Qt::AscendingOrder);
item1.setData(0, Qt::DisplayRole, 11);
item2.setData(0, Qt::DisplayRole, 2);
QCOMPARE(item1 < item2, false);
}
}
void tst_QTreeWidget::sortedIndexOfChild_data()
{
QTest::addColumn<int>("sortOrder");
QTest::addColumn<QStringList>("itemTexts");
QTest::addColumn<QList<int> >("expectedIndexes");
QTest::newRow("three ascending")
<< int(Qt::AscendingOrder)
<< (QStringList() << "A" << "B" << "C")
<< (QList<int>() << 0 << 1 << 2);
QTest::newRow("three descending")
<< int(Qt::DescendingOrder)
<< (QStringList() << "A" << "B" << "C")
<< (QList<int>() << 2 << 1 << 0);
}
void tst_QTreeWidget::sortedIndexOfChild()
{
QFETCH(int, sortOrder);
QFETCH(QStringList, itemTexts);
QFETCH(QList<int>, expectedIndexes);
QTreeWidget tw;
QList<QTreeWidgetItem*> itms;
QTreeWidgetItem *top = new QTreeWidgetItem(&tw, QStringList() << "top");
for (int i = 0; i < itemTexts.count(); ++i)
itms << new QTreeWidgetItem(top, QStringList() << itemTexts.at(i));
tw.sortItems(0, (Qt::SortOrder)sortOrder);
tw.expandAll();
QVERIFY(itms.count() == expectedIndexes.count());
for (int j = 0; j < expectedIndexes.count(); ++j)
QCOMPARE(top->indexOfChild(itms.at(j)), expectedIndexes.at(j));
}
void tst_QTreeWidget::expandAndCallapse()
{
QTreeWidget tw;
QTreeWidgetItem *top = new QTreeWidgetItem(&tw, QStringList() << "top");
QTreeWidgetItem *p;
for (int i = 0; i < 10; ++i) {
p = new QTreeWidgetItem(top, QStringList() << QString("%1").arg(i));
for (int j = 0; j < 10; ++j)
new QTreeWidgetItem(p, QStringList() << QString("%1").arg(j));
}
QSignalSpy spy0(&tw, SIGNAL(itemExpanded(QTreeWidgetItem *)));
QSignalSpy spy1(&tw, SIGNAL(itemCollapsed(QTreeWidgetItem *)));
tw.expandItem(p);
tw.collapseItem(p);
tw.expandItem(p);
tw.expandItem(top);
tw.collapseItem(top);
tw.collapseItem(top);
QCOMPARE(spy0.count(), 3);
QCOMPARE(spy1.count(), 2);
}
void tst_QTreeWidget::setDisabled()
{
QTreeWidget w;
QTreeWidgetItem *i1 = new QTreeWidgetItem();
QTreeWidgetItem *i2 = new QTreeWidgetItem(i1);
QTreeWidgetItem *i3 = new QTreeWidgetItem(i1);
QTreeWidgetItem *top = new QTreeWidgetItem(&w);
top->setDisabled(true);
top->addChild(i1);
QCOMPARE(i1->isDisabled(), true);
QCOMPARE(i2->isDisabled(), true);
QCOMPARE(i3->isDisabled(), true);
i1 = top->takeChild(0);
QCOMPARE(i1->isDisabled(), false);
QCOMPARE(i2->isDisabled(), false);
QCOMPARE(i3->isDisabled(), false);
top->addChild(i1);
QCOMPARE(i1->isDisabled(), true);
QCOMPARE(i2->isDisabled(), true);
QCOMPARE(i3->isDisabled(), true);
top->setDisabled(false);
QCOMPARE(i1->isDisabled(), false);
QCOMPARE(i2->isDisabled(), false);
QCOMPARE(i3->isDisabled(), false);
QList<QTreeWidgetItem*> children;
children.append(new QTreeWidgetItem());
children.append(new QTreeWidgetItem());
children.append(new QTreeWidgetItem());
i1 = top->takeChild(0);
top->addChildren(children);
QCOMPARE(top->child(0)->isDisabled(), false);
QCOMPARE(top->child(1)->isDisabled(), false);
QCOMPARE(top->child(1)->isDisabled(), false);
top->setDisabled(true);
QCOMPARE(top->child(0)->isDisabled(), true);
QCOMPARE(top->child(1)->isDisabled(), true);
QCOMPARE(top->child(1)->isDisabled(), true);
children = top->takeChildren();
QCOMPARE(children.at(0)->isDisabled(), false);
QCOMPARE(children.at(1)->isDisabled(), false);
QCOMPARE(children.at(1)->isDisabled(), false);
}
void tst_QTreeWidget::removeSelectedItem()
{
QTreeWidget *w = new QTreeWidget();
w->setSortingEnabled(true);
QTreeWidgetItem *first = new QTreeWidgetItem();
first->setText(0, QLatin1String("D"));
w->addTopLevelItem(first);
QTreeWidgetItem *itm = new QTreeWidgetItem();
itm->setText(0, QLatin1String("D"));
w->addTopLevelItem(itm);
itm = new QTreeWidgetItem();
itm->setText(0, QLatin1String("C"));
w->addTopLevelItem(itm);
itm->setSelected(true);
itm = new QTreeWidgetItem();
itm->setText(0, QLatin1String("A"));
w->addTopLevelItem(itm);
//w->show();
QItemSelectionModel *selModel = w->selectionModel();
QCOMPARE(selModel->hasSelection(), true);
QCOMPARE(selModel->selectedRows().count(), 1);
QTreeWidgetItem *taken = w->takeTopLevelItem(2);
QCOMPARE(taken->text(0), QLatin1String("C"));
QCOMPARE(selModel->hasSelection(), false);
QCOMPARE(selModel->selectedRows().count(), 0);
QItemSelection sel = selModel->selection();
QCOMPARE(selModel->isSelected(w->model()->index(0,0)), false);
delete w;
}
class AnotherTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
AnotherTreeWidget(QWidget *parent = 0) : QTreeWidget(parent) {}
void deleteCurrent() { if (currentItem()) delete currentItem(); }
};
void tst_QTreeWidget::removeCurrentItem()
{
AnotherTreeWidget widget;
QObject::connect(widget.selectionModel(),
SIGNAL(currentChanged(QModelIndex,QModelIndex)),
&widget, SLOT(clear()));
QTreeWidgetItem *item = new QTreeWidgetItem(&widget);
widget.setCurrentItem(item);
widget.deleteCurrent();
}
void tst_QTreeWidget::removeCurrentItem_task186451()
{
AnotherTreeWidget widget;
QTreeWidgetItem *item = new QTreeWidgetItem(&widget, QStringList() << "1");
QTreeWidgetItem *item2 = new QTreeWidgetItem(&widget, QStringList() << "2");
widget.setCurrentItem(item);
widget.deleteCurrent();
QVERIFY(item2->isSelected());
QCOMPARE(item2, widget.currentItem());
}
class TreeWidget : QTreeWidget {
public:
QModelIndex indexFromItem(QTreeWidgetItem *item, int column = 0) const {
return QTreeWidget::indexFromItem(item, column);
}
QTreeWidgetItem *itemFromIndex(const QModelIndex &index) const {
return QTreeWidget::itemFromIndex(index);
}
};
void tst_QTreeWidget::randomExpand()
{
QTreeWidget tree;
QTreeWidgetItem *item1 = new QTreeWidgetItem(&tree);
QTreeWidgetItem *item3 = new QTreeWidgetItem(&tree, item1);
new QTreeWidgetItem(item1);
new QTreeWidgetItem(item3);
tree.expandAll();
/*
item1
\- item2
item3
\- item4
*/
QTreeWidgetItem *newItem1 = 0;
for (int i = 0; i < 100; i++) {
newItem1 = new QTreeWidgetItem(&tree, item1);
tree.setItemExpanded(newItem1, true);
QCOMPARE(tree.isItemExpanded(newItem1), true);
QTreeWidgetItem *x = new QTreeWidgetItem();
QCOMPARE(tree.isItemExpanded(newItem1), true);
newItem1->addChild(x);
QCOMPARE(tree.isItemExpanded(newItem1), true);
}
}
void tst_QTreeWidget::crashTest()
{
QTreeWidget *tree = new QTreeWidget();
tree->setColumnCount(1);
tree->show();
QTreeWidgetItem *item1 = new QTreeWidgetItem(tree);
item1->setText(0, "item1");
tree->setItemExpanded(item1, true);
QTreeWidgetItem *item2 = new QTreeWidgetItem(item1);
item2->setText(0, "item2");
QTreeWidgetItem *item3 = new QTreeWidgetItem(tree, item1);
item3->setText(0, "item3");
tree->setItemExpanded(item3, true);
QTreeWidgetItem *item4 = new QTreeWidgetItem(item3);
item4->setText(0, "item4");
QTreeWidgetItem *item5 = new QTreeWidgetItem(tree, item3);
item5->setText(0, "item5");
tree->setItemExpanded(item5, true);
QTreeWidgetItem *item6 = new QTreeWidgetItem(item5);
item6->setText(0, "item6");
for (int i = 0; i < 1000; i++) {
QTreeWidgetItem *newItem1 = new QTreeWidgetItem(tree, item1);
newItem1->setText(0, "newItem");
QTreeWidgetItem *newItem2 = new QTreeWidgetItem(newItem1);
newItem2->setText(0, "subItem1");
QTreeWidgetItem *newItem3 = new QTreeWidgetItem(newItem1, newItem2);
newItem3->setText(0, "subItem2");
delete item3;
item3 = newItem1;
}
QApplication::instance()->processEvents();
delete tree;
}
class CrashWidget : public QTreeWidget
{
public:
CrashWidget(QWidget *parent = 0) : QTreeWidget(parent), i(0) {
setSortingEnabled(true);
timerId = startTimer(10);
}
int i;
protected:
void timerEvent(QTimerEvent * event) {
if (event->timerId() == timerId) {
QTreeWidgetItem *newItem = new QTreeWidgetItem((QStringList() << QString::number(i++)));
m_list.append(newItem);
insertTopLevelItem(0, newItem);
while (m_list.count() > 10)
delete m_list.takeFirst();
}
QTreeWidget::timerEvent(event);
}
private:
int timerId;
QList<QTreeWidgetItem*> m_list;
};
void tst_QTreeWidget::sortAndSelect()
{
CrashWidget w;
w.resize(1, 1);
w.show();
while (w.i < 100) {
QApplication::processEvents();
if (w.i & 16) {
QPoint pt = w.viewport()->rect().center();
QTest::mouseClick(w.viewport(), Qt::LeftButton, Qt::NoModifier, pt);
}
}
QVERIFY(true);
}
void tst_QTreeWidget::defaultRowSizes()
{
QTreeWidget *tw = new QTreeWidget();
tw->setIconSize(QSize(50, 50));
tw->setColumnCount(6);
for (int i=0; i<10; ++i) {
QTreeWidgetItem *it = new QTreeWidgetItem(tw);
for (int j=0; j<tw->columnCount() - 1; ++j) {
it->setText(j, "This is a test");
}
QPixmap icon = tw->style()->standardPixmap((QStyle::StandardPixmap)(i + QStyle::SP_TitleBarMenuButton));
if (icon.isNull())
QSKIP("No pixmap found on current style, skipping this test.");
it->setIcon(tw->columnCount() - 1,
icon.scaled(tw->iconSize()));
}
tw->resize(100,100);
tw->show();
QApplication::processEvents();
QRect visualRect = tw->visualItemRect(tw->topLevelItem(0));
QVERIFY(visualRect.height() >= 50);
}
void tst_QTreeWidget::task191552_rtl()
{
Qt::LayoutDirection oldDir = qApp->layoutDirection();
qApp->setLayoutDirection(Qt::RightToLeft);
QTreeWidget tw;
tw.setColumnCount(1);
QTreeWidgetItem *item = new QTreeWidgetItem(&tw);
item->setText(0, "item 1");
item->setCheckState(0, Qt::Checked);
QCOMPARE(item->checkState(0), Qt::Checked);
tw.show();
QTest::qWait(50);
QStyleOptionViewItem opt;
opt.initFrom(&tw);
opt.rect = tw.visualItemRect(item);
// mimic QStyledItemDelegate::initStyleOption logic
opt.features = QStyleOptionViewItem::HasDisplay | QStyleOptionViewItem::HasCheckIndicator;
opt.checkState = Qt::Checked;
opt.widget = &tw;
const QRect checkRect = tw.style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, &tw);
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::NoModifier, checkRect.center());
QTest::qWait(200);
QCOMPARE(item->checkState(0), Qt::Unchecked);
qApp->setLayoutDirection(oldDir);
}
void tst_QTreeWidget::task203673_selection()
{
//we try to change the selection by rightclick + ctrl
//it should do anything when using ExtendedSelection
QTreeWidget tw;
tw.setColumnCount(1);
QTreeWidgetItem *item1 = new QTreeWidgetItem(&tw);
item1->setText(0, "item 1");
tw.setSelectionMode(QTreeView::ExtendedSelection);
QPoint center = tw.visualItemRect(item1).center();
QCOMPARE(item1->isSelected(), false);
QTest::mouseClick(tw.viewport(), Qt::RightButton, Qt::ControlModifier, center);
QCOMPARE(item1->isSelected(), false);
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::ControlModifier, center);
QCOMPARE(item1->isSelected(), true);
QTest::mouseClick(tw.viewport(), Qt::RightButton, Qt::ControlModifier, center);
QCOMPARE(item1->isSelected(), true); //it shouldn't change
QTest::mouseClick(tw.viewport(), Qt::LeftButton, Qt::ControlModifier, center);
QCOMPARE(item1->isSelected(), false);
}
void tst_QTreeWidget::rootItemFlags()
{
QTreeWidget tw;
tw.setColumnCount(1);
QTreeWidgetItem *item = new QTreeWidgetItem(&tw);
item->setText(0, "item 1");
QVERIFY(tw.invisibleRootItem()->flags() & Qt::ItemIsDropEnabled);
tw.invisibleRootItem()->setFlags(tw.invisibleRootItem()->flags() & ~Qt::ItemIsDropEnabled);
QVERIFY(!(tw.invisibleRootItem()->flags() & Qt::ItemIsDropEnabled));
}
void tst_QTreeWidget::task218661_setHeaderData()
{
//We check that setting header data out of bounds returns false
//and doesn't increase the size of the model
QTreeWidget tw;
tw.setColumnCount(1);
QCOMPARE(tw.columnCount(), 1);
QCOMPARE(tw.model()->setHeaderData(99999, Qt::Horizontal, QVariant()), false);
QCOMPARE(tw.columnCount(), 1);
}
void tst_QTreeWidget::task245280_sortChildren()
{
QTreeWidget tw;
tw.setColumnCount(2);
QTreeWidgetItem top(&tw);
top.setText(0,"Col 0");
top.setText(1,"Col 1");
QTreeWidgetItem item1(&top);
item1.setText(0,"X");
item1.setText(1,"0");
QTreeWidgetItem item2(&top);
item2.setText(0,"A");
item2.setText(1,"4");
QTreeWidgetItem item3(&top);
item3.setText(0,"E");
item3.setText(1,"1");
QTreeWidgetItem item4(&top);
item4.setText(0,"Z");
item4.setText(1,"3");
QTreeWidgetItem item5(&top);
item5.setText(0,"U");
item5.setText(1,"2");
tw.expandAll();
tw.show();
top.sortChildren(1,Qt::AscendingOrder);
for (int i = 0; i < top.childCount(); ++i)
QCOMPARE(top.child(i)->text(1), QString::number(i));
}
void tst_QTreeWidget::task253109_itemHeight()
{
QTreeWidget treeWidget;
treeWidget.setColumnCount(1);
treeWidget.show();
QTest::qWait(200);
QTreeWidgetItem item(&treeWidget);
class MyWidget : public QWidget
{
virtual QSize sizeHint() const { return QSize(200,100); }
} w;
treeWidget.setItemWidget(&item, 0, &w);
QTest::qWait(200);
QCOMPARE(w.geometry(), treeWidget.visualItemRect(&item));
}
void tst_QTreeWidget::task206367_duplication()
{
QWidget topLevel;
QTreeWidget treeWidget(&topLevel);
topLevel.show();
treeWidget.resize(200, 200);
treeWidget.setSortingEnabled(true);
QTreeWidgetItem* rootItem = new QTreeWidgetItem( &treeWidget, QStringList("root") );
for (int nFile = 0; nFile < 2; nFile++ ) {
QTreeWidgetItem* itemFile = new QTreeWidgetItem(rootItem, QStringList(QString::number(nFile)));
for (int nRecord = 0; nRecord < 2; nRecord++)
new QTreeWidgetItem(itemFile , QStringList(QString::number(nRecord)));
itemFile->setExpanded(true);
}
rootItem->setExpanded(true);
QTest::qWait(2000);
//there should be enough room for 2x2 items. If there is a scrollbar, it means the items are duplicated
QVERIFY(!treeWidget.verticalScrollBar()->isVisible());
}
void tst_QTreeWidget::itemSelectionChanged()
{
QVERIFY(testWidget);
if(testWidget->topLevelItem(0))
QVERIFY(testWidget->topLevelItem(0)->isSelected());
}
void tst_QTreeWidget::selectionOrder()
{
testWidget->setColumnCount(1);
QList<QTreeWidgetItem *> items;
for (int i = 0; i < 10; ++i)
items.append(new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString("item: %1").arg(i))));
testWidget->insertTopLevelItems(0, items);
QModelIndex idx = testWidget->indexFromItem(items[0]);
connect(testWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
testWidget->selectionModel()->select(idx, QItemSelectionModel::SelectCurrent);
disconnect(testWidget, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
}
void tst_QTreeWidget::setSelectionModel()
{
QTreeWidget tree;
for(int i = 0; i < 3; ++i)
new QTreeWidgetItem(&tree, QStringList(QString::number(i)));
QItemSelectionModel selection(tree.model());
selection.select(tree.model()->index(1,0), QItemSelectionModel::Select);
tree.setSelectionModel(&selection);
QCOMPARE(tree.topLevelItem(1)->isSelected(), true);
}
void tst_QTreeWidget::task217309()
{
QTreeWidgetItem item;
item.setFlags(item.flags() | Qt::ItemIsTristate);
QTreeWidgetItem subitem1;
subitem1.setFlags(subitem1.flags() | Qt::ItemIsTristate);
QTreeWidgetItem subitem2;
subitem2.setFlags(subitem2.flags() | Qt::ItemIsTristate);
item.addChild(&subitem1);
item.addChild(&subitem2);
subitem1.setCheckState(0, Qt::Checked);
subitem2.setCheckState(0, Qt::Unchecked);
QVERIFY(item.data(0, Qt::CheckStateRole) == Qt::PartiallyChecked);
subitem2.setCheckState(0, Qt::PartiallyChecked);
QVERIFY(item.data(0, Qt::CheckStateRole) == Qt::PartiallyChecked);
subitem2.setCheckState(0, Qt::Checked);
QVERIFY(item.data(0, Qt::CheckStateRole) == Qt::Checked);
}
class TreeWidgetItem : public QTreeWidgetItem
{
public:
void _emitDataChanged() { emitDataChanged(); }
};
void tst_QTreeWidget::emitDataChanged()
{
QTreeWidget *tree = new QTreeWidget;
QSignalSpy spy(tree, SIGNAL(itemChanged(QTreeWidgetItem *, int)));
TreeWidgetItem *item = new TreeWidgetItem();
tree->insertTopLevelItem(0, item);
item->_emitDataChanged();
QCOMPARE(spy.count(), 1);
}
void tst_QTreeWidget::setCurrentItemExpandsParent()
{
QTreeWidget w;
w.setColumnCount(1);
QTreeWidgetItem *i1 = new QTreeWidgetItem(&w, QStringList() << "parent");
QTreeWidgetItem *i2 = new QTreeWidgetItem(i1, QStringList() << "child");
QVERIFY(!i2->isExpanded());
QVERIFY(w.currentItem() == 0);
w.setCurrentItem(i2);
QVERIFY(!i2->isExpanded());
QCOMPARE(w.currentItem(), i2);
}
void tst_QTreeWidget::task239150_editorWidth()
{
//we check that an item with no text will get an editor with a correct size
QTreeWidget tree;
QStyleOptionFrameV2 opt;
opt.init(&tree);
const int minWidth = tree.style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(0, 0).
expandedTo(QApplication::globalStrut()), 0).width();
{
QTreeWidgetItem item;
item.setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
tree.addTopLevelItem(&item);
QVERIFY(tree.itemWidget(&item, 0) == 0);
tree.editItem(&item);
QVERIFY(tree.itemWidget(&item, 0));
QVERIFY(tree.itemWidget(&item, 0)->width() >= minWidth);
}
//now let's test it with an item with a lot of text
{
QTreeWidgetItem item;
item.setText(0, "foooooooooooooooooooooooo");
item.setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
tree.addTopLevelItem(&item);
QVERIFY(tree.itemWidget(&item, 0) == 0);
tree.editItem(&item);
QVERIFY(tree.itemWidget(&item, 0));
QVERIFY(tree.itemWidget(&item, 0)->width() >= minWidth + tree.fontMetrics().width(item.text(0)));
}
}
void tst_QTreeWidget::setTextUpdate()
{
QTreeWidget treeWidget;
treeWidget.setColumnCount(2);
class MyItemDelegate : public QStyledItemDelegate
{
public:
MyItemDelegate() : numPaints(0) { }
void paint(QPainter *painter,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
numPaints++;
QStyledItemDelegate::paint(painter, option, index);
}
mutable int numPaints;
} delegate;
treeWidget.setItemDelegate(&delegate);
treeWidget.show();
QStringList strList;
strList << "variable1" << "0";
QTreeWidgetItem *item = new QTreeWidgetItem(strList);
treeWidget.insertTopLevelItem(0, item);
QTest::qWait(50);
QTRY_VERIFY(delegate.numPaints > 0);
delegate.numPaints = 0;
item->setText(1, "42");
QApplication::processEvents();
QTRY_VERIFY(delegate.numPaints > 0);
}
void tst_QTreeWidget::taskQTBUG2844_visualItemRect()
{
CustomTreeWidget tree;
tree.resize(150, 100);
tree.setColumnCount(3);
QTreeWidgetItem item(&tree);
QRect rectCol0 = tree.visualRect(tree.indexFromItem(&item, 0));
QRect rectCol1 = tree.visualRect(tree.indexFromItem(&item, 1));
QRect rectCol2 = tree.visualRect(tree.indexFromItem(&item, 2));
QCOMPARE(tree.visualItemRect(&item), rectCol0 | rectCol2);
tree.setColumnHidden(2, true);
QCOMPARE(tree.visualItemRect(&item), rectCol0 | rectCol1);
}
void tst_QTreeWidget::setChildIndicatorPolicy()
{
QTreeWidget treeWidget;
treeWidget.setColumnCount(1);
class MyItemDelegate : public QStyledItemDelegate
{
public:
MyItemDelegate() : numPaints(0), expectChildren(false) { }
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
numPaints++;
QCOMPARE(!(option.state & QStyle::State_Children), !expectChildren);
QStyledItemDelegate::paint(painter, option, index);
}
mutable int numPaints;
bool expectChildren;
} delegate;
treeWidget.setItemDelegate(&delegate);
treeWidget.show();
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList("Hello"));
treeWidget.insertTopLevelItem(0, item);
QTest::qWait(50);
QTRY_VERIFY(delegate.numPaints > 0);
delegate.numPaints = 0;
delegate.expectChildren = true;
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
QApplication::processEvents();
QTRY_COMPARE(delegate.numPaints, 1);
delegate.numPaints = 0;
delegate.expectChildren = false;
item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
QApplication::processEvents();
QTRY_COMPARE(delegate.numPaints, 1);
delegate.numPaints = 0;
delegate.expectChildren = true;
new QTreeWidgetItem(item);
QApplication::processEvents();
QTRY_COMPARE(delegate.numPaints, 1);
delegate.numPaints = 0;
delegate.expectChildren = false;
item->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
QApplication::processEvents();
QTRY_COMPARE(delegate.numPaints, 1);
}
void tst_QTreeWidget::task20345_sortChildren()
{
// This test case is considered successful if it is executed (no crash in sorting)
QTreeWidget tw;
tw.setColumnCount(3);
tw.headerItem()->setText(0, "Col 0");
tw.headerItem()->setText(1, "Col 1");
tw.header()->setSortIndicator(0, Qt::AscendingOrder);
tw.setSortingEnabled(true);
tw.show();
QTreeWidgetItem *rootItem = 0;
QTreeWidgetItem *childItem = 0;
rootItem = new QTreeWidgetItem(&tw, QStringList("a"));
childItem = new QTreeWidgetItem(rootItem);
childItem->setText(1, "3");
childItem = new QTreeWidgetItem(rootItem);
childItem->setText(1, "1");
childItem = new QTreeWidgetItem(rootItem);
childItem->setText(1, "2");
tw.setCurrentItem(tw.topLevelItem(0));
QTreeWidgetItem * curItem = tw.currentItem();
int childCount = curItem->childCount() + 1;
QTreeWidgetItem * newItem = new QTreeWidgetItem(curItem);
newItem->setText(1, QString::number(childCount));
rootItem->sortChildren(1, Qt::AscendingOrder);
QVERIFY(1);
}
QTEST_MAIN(tst_QTreeWidget)
#include "tst_qtreewidget.moc"