qt5base-lts/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
Ahmad Samir 85eebedb16 QStandardItem: add note about reimplementing data/setData() wrt. flags
Extend the unittests.

Drive-by change: add missing include, otherwise static analyzers
(clangd) complain.

Fixes: QTBUG-105150
Pick-to: 6.6 6.5 5.15
Change-Id: I312133d5b35119e2e51002dfefe0e141c0708e3d
Reviewed-by: David Faure <david.faure@kdab.com>
2023-11-14 21:23:45 +02:00

1094 lines
38 KiB
C++

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QTest>
#include <QSignalSpy>
#include <QStandardItem>
class tst_QStandardItem : public QObject
{
Q_OBJECT
private slots:
void ctor();
void textCtor();
void iconTextCtor();
void rowsColumnsCtor();
void getSetData();
void getSetFlags();
void getSetRowAndColumnCount();
void getSetChild_data();
void getSetChild();
void parent();
void insertColumn_data();
void insertColumn();
void insertRow_data();
void insertRow();
void insertRows_data();
void insertRows();
void appendColumn_data();
void appendColumn();
void appendRow_data();
void appendRow();
void takeChild();
void takeColumn_data();
void takeColumn();
void takeRow_data();
void takeRow();
void streamItem();
void deleteItem();
void clone();
void sortChildren();
void subclassing();
void lessThan();
void clearData();
};
void tst_QStandardItem::clearData()
{
QStandardItem item;
item.setData(QStringLiteral("Test"), Qt::EditRole);
item.setData(5, Qt::UserRole);
item.clearData();
QCOMPARE(item.data(Qt::EditRole), QVariant());
QCOMPARE(item.data(Qt::UserRole), QVariant());
QCOMPARE(item.data(Qt::DisplayRole), QVariant());
}
void tst_QStandardItem::ctor()
{
QStandardItem item;
QVERIFY(!item.hasChildren());
}
void tst_QStandardItem::textCtor()
{
QLatin1String text("text");
QStandardItem item(text);
QCOMPARE(item.text(), text);
QVERIFY(!item.hasChildren());
}
void tst_QStandardItem::iconTextCtor()
{
QPixmap pixmap(32, 32);
pixmap.fill(Qt::red);
QIcon icon(pixmap);
QLatin1String text("text");
QStandardItem item(icon, text);
QCOMPARE(item.icon(), icon);
QCOMPARE(item.text(), text);
QVERIFY(!item.hasChildren());
}
void tst_QStandardItem::rowsColumnsCtor()
{
const int rows = 5;
const int columns = 12;
QStandardItem item(rows, columns);
QCOMPARE(item.rowCount(), rows);
QCOMPARE(item.columnCount(), columns);
}
void tst_QStandardItem::getSetData()
{
QStandardItem item;
for (int x = 0; x < 2; ++x) {
for (int i = 1; i <= 2; ++i) {
const QString iS = QString::number(i);
QString text = QLatin1String("text ") + iS;
item.setText(text);
QCOMPARE(item.text(), text);
QPixmap pixmap(32, 32);
pixmap.fill((i == 1) ? Qt::red : Qt::green);
QIcon icon(pixmap);
item.setIcon(icon);
QCOMPARE(item.icon(), icon);
QString toolTip = QLatin1String("toolTip ") + iS;
item.setToolTip(toolTip);
QCOMPARE(item.toolTip(), toolTip);
QString statusTip = QLatin1String("statusTip ") + iS;
item.setStatusTip(statusTip);
QCOMPARE(item.statusTip(), statusTip);
QString whatsThis = QLatin1String("whatsThis ") + iS;
item.setWhatsThis(whatsThis);
QCOMPARE(item.whatsThis(), whatsThis);
QSize sizeHint(64*i, 48*i);
item.setSizeHint(sizeHint);
QCOMPARE(item.sizeHint(), sizeHint);
QFont font;
item.setFont(font);
QCOMPARE(item.font(), font);
Qt::Alignment textAlignment((i == 1)
? Qt::AlignLeft|Qt::AlignVCenter
: Qt::AlignRight);
item.setTextAlignment(textAlignment);
QCOMPARE(item.textAlignment(), textAlignment);
QColor backgroundColor((i == 1) ? Qt::blue : Qt::yellow);
item.setBackground(backgroundColor);
QCOMPARE(item.background().color(), backgroundColor);
QColor textColor((i == 1) ? Qt::green : Qt::cyan);
item.setForeground(textColor);
QCOMPARE(item.foreground().color(), textColor);
Qt::CheckState checkState((i == 1) ? Qt::PartiallyChecked : Qt::Checked);
item.setCheckState(checkState);
QCOMPARE(item.checkState(), checkState);
QString accessibleText = QLatin1String("accessibleText ") + iS;
item.setAccessibleText(accessibleText);
QCOMPARE(item.accessibleText(), accessibleText);
QString accessibleDescription = QLatin1String("accessibleDescription ") + iS;
item.setAccessibleDescription(accessibleDescription);
QCOMPARE(item.accessibleDescription(), accessibleDescription);
QCOMPARE(item.text(), text);
QCOMPARE(item.icon(), icon);
QCOMPARE(item.toolTip(), toolTip);
QCOMPARE(item.statusTip(), statusTip);
QCOMPARE(item.whatsThis(), whatsThis);
QCOMPARE(item.sizeHint(), sizeHint);
QCOMPARE(item.font(), font);
QCOMPARE(item.textAlignment(), textAlignment);
QCOMPARE(item.background().color(), backgroundColor);
QCOMPARE(item.foreground().color(), textColor);
QCOMPARE(item.checkState(), checkState);
QCOMPARE(item.accessibleText(), accessibleText);
QCOMPARE(item.accessibleDescription(), accessibleDescription);
QCOMPARE(qvariant_cast<QString>(item.data(Qt::DisplayRole)), text);
QCOMPARE(qvariant_cast<QIcon>(item.data(Qt::DecorationRole)), icon);
QCOMPARE(qvariant_cast<QString>(item.data(Qt::ToolTipRole)), toolTip);
QCOMPARE(qvariant_cast<QString>(item.data(Qt::StatusTipRole)), statusTip);
QCOMPARE(qvariant_cast<QString>(item.data(Qt::WhatsThisRole)), whatsThis);
QCOMPARE(qvariant_cast<QSize>(item.data(Qt::SizeHintRole)), sizeHint);
QCOMPARE(qvariant_cast<QFont>(item.data(Qt::FontRole)), font);
QCOMPARE(qvariant_cast<int>(item.data(Qt::TextAlignmentRole)), int(textAlignment));
QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundRole)), QBrush(backgroundColor));
QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::ForegroundRole)), QBrush(textColor));
QCOMPARE(qvariant_cast<int>(item.data(Qt::CheckStateRole)), int(checkState));
QCOMPARE(qvariant_cast<QString>(item.data(Qt::AccessibleTextRole)), accessibleText);
QCOMPARE(qvariant_cast<QString>(item.data(Qt::AccessibleDescriptionRole)), accessibleDescription);
item.setBackground(pixmap);
QCOMPARE(item.background().texture(), pixmap);
QCOMPARE(qvariant_cast<QBrush>(item.data(Qt::BackgroundRole)).texture(), pixmap);
}
item.setData(QVariant(), Qt::DisplayRole);
item.setData(QVariant(), Qt::DecorationRole);
item.setData(QVariant(), Qt::ToolTipRole);
item.setData(QVariant(), Qt::StatusTipRole);
item.setData(QVariant(), Qt::WhatsThisRole);
item.setData(QVariant(), Qt::SizeHintRole);
item.setData(QVariant(), Qt::FontRole);
item.setData(QVariant(), Qt::TextAlignmentRole);
item.setData(QVariant(), Qt::BackgroundRole);
item.setData(QVariant(), Qt::ForegroundRole);
item.setData(QVariant(), Qt::CheckStateRole);
item.setData(QVariant(), Qt::AccessibleTextRole);
item.setData(QVariant(), Qt::AccessibleDescriptionRole);
QCOMPARE(item.data(Qt::DisplayRole), QVariant());
QCOMPARE(item.data(Qt::DecorationRole), QVariant());
QCOMPARE(item.data(Qt::ToolTipRole), QVariant());
QCOMPARE(item.data(Qt::StatusTipRole), QVariant());
QCOMPARE(item.data(Qt::WhatsThisRole), QVariant());
QCOMPARE(item.data(Qt::SizeHintRole), QVariant());
QCOMPARE(item.data(Qt::FontRole), QVariant());
QCOMPARE(item.data(Qt::TextAlignmentRole), QVariant());
QCOMPARE(item.data(Qt::BackgroundRole), QVariant());
QCOMPARE(item.data(Qt::ForegroundRole), QVariant());
QCOMPARE(item.data(Qt::CheckStateRole), QVariant());
QCOMPARE(item.data(Qt::AccessibleTextRole), QVariant());
QCOMPARE(item.data(Qt::AccessibleDescriptionRole), QVariant());
}
}
void tst_QStandardItem::getSetFlags()
{
QStandardItem item;
item.setEnabled(true);
QVERIFY(item.isEnabled());
QVERIFY(item.flags() & Qt::ItemIsEnabled);
item.setEditable(true);
QVERIFY(item.isEditable());
QVERIFY(item.flags() & Qt::ItemIsEditable);
item.setSelectable(true);
QVERIFY(item.isSelectable());
QVERIFY(item.flags() & Qt::ItemIsSelectable);
item.setCheckable(true);
QVERIFY(item.isCheckable());
QCOMPARE(item.checkState(), Qt::Unchecked);
QVERIFY(item.flags() & Qt::ItemIsUserCheckable);
item.setUserTristate(true);
QVERIFY(item.isUserTristate());
QVERIFY(item.flags() & Qt::ItemIsUserTristate);
item.setAutoTristate(true);
QVERIFY(item.isAutoTristate());
QVERIFY(item.flags() & Qt::ItemIsAutoTristate);
#if QT_CONFIG(draganddrop)
item.setDragEnabled(true);
QVERIFY(item.isDragEnabled());
QVERIFY(item.flags() & Qt::ItemIsDragEnabled);
item.setDropEnabled(true);
QVERIFY(item.isDropEnabled());
QVERIFY(item.flags() & Qt::ItemIsDropEnabled);
#endif
QVERIFY(item.isEnabled());
item.setEnabled(false);
QVERIFY(!item.isEnabled());
QVERIFY(!(item.flags() & Qt::ItemIsEnabled));
QVERIFY(item.isEditable());
item.setEditable(false);
QVERIFY(!item.isEditable());
QVERIFY(!(item.flags() & Qt::ItemIsEditable));
QVERIFY(item.isSelectable());
item.setSelectable(false);
QVERIFY(!item.isSelectable());
QVERIFY(!(item.flags() & Qt::ItemIsSelectable));
QVERIFY(item.isCheckable());
item.setCheckable(false);
QVERIFY(!item.isCheckable());
QVERIFY(!(item.flags() & Qt::ItemIsUserCheckable));
item.setUserTristate(false);
QVERIFY(!item.isUserTristate());
QVERIFY(!(item.flags() & Qt::ItemIsUserTristate));
item.setAutoTristate(false);
QVERIFY(!item.isAutoTristate());
QVERIFY(!(item.flags() & Qt::ItemIsAutoTristate));
#if QT_CONFIG(draganddrop)
QVERIFY(item.isDragEnabled());
item.setDragEnabled(false);
QVERIFY(!item.isDragEnabled());
QVERIFY(!(item.flags() & Qt::ItemIsDragEnabled));
QVERIFY(item.isDropEnabled());
item.setDropEnabled(false);
QVERIFY(!item.isDropEnabled());
QVERIFY(!(item.flags() & Qt::ItemIsDropEnabled));
#endif
item.setCheckable(false);
item.setCheckState(Qt::Checked);
item.setCheckable(true);
QCOMPARE(item.checkState(), Qt::Checked);
}
void tst_QStandardItem::getSetRowAndColumnCount()
{
QStandardItem item;
item.setRowCount(-1);
QCOMPARE(item.rowCount(), 0);
item.setColumnCount(-1);
QCOMPARE(item.columnCount(), 0);
item.setRowCount(1);
QCOMPARE(item.rowCount(), 1);
QCOMPARE(item.columnCount(), 0);
item.setColumnCount(1);
QCOMPARE(item.columnCount(), 1);
QCOMPARE(item.rowCount(), 1);
item.setColumnCount(10);
QCOMPARE(item.columnCount(), 10);
QCOMPARE(item.rowCount(), 1);
item.setRowCount(20);
QCOMPARE(item.rowCount(), 20);
QCOMPARE(item.columnCount(), 10);
item.setRowCount(-1);
QCOMPARE(item.rowCount(), 20);
item.setColumnCount(-1);
QCOMPARE(item.columnCount(), 10);
item.setColumnCount(0);
QCOMPARE(item.columnCount(), 0);
QCOMPARE(item.rowCount(), 20);
item.setRowCount(0);
QCOMPARE(item.rowCount(), 0);
}
void tst_QStandardItem::getSetChild_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("row");
QTest::addColumn<int>("column");
QTest::newRow("0x0 children, child at (-1,-1)") << 0 << 0 << -1 << -1;
QTest::newRow("0x0 children, child at (0,0)") << 0 << 0 << 0 << 0;
}
void tst_QStandardItem::getSetChild()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, row);
QFETCH(int, column);
QStandardItem item(rows, columns);
bool shouldHaveChildren = (rows > 0) && (columns > 0);
QCOMPARE(item.hasChildren(), shouldHaveChildren);
QCOMPARE(item.child(row, column), nullptr);
QStandardItem *child = new QStandardItem;
item.setChild(row, column, child);
if ((row >= 0) && (column >= 0)) {
QCOMPARE(item.rowCount(), qMax(rows, row + 1));
QCOMPARE(item.columnCount(), qMax(columns, column + 1));
QCOMPARE(item.child(row, column), child);
QCOMPARE(child->row(), row);
QCOMPARE(child->column(), column);
QStandardItem *anotherChild = new QStandardItem;
item.setChild(row, column, anotherChild);
QCOMPARE(item.child(row, column), anotherChild);
QCOMPARE(anotherChild->row(), row);
QCOMPARE(anotherChild->column(), column);
item.setChild(row, column, nullptr);
} else {
delete child;
}
QCOMPARE(item.child(row, column), nullptr);
}
void tst_QStandardItem::parent()
{
{
QStandardItem item;
QStandardItem *child = new QStandardItem;
QCOMPARE(child->parent(), nullptr);
item.setChild(0, 0, child);
QCOMPARE(child->parent(), &item);
QStandardItem *childOfChild = new QStandardItem;
child->setChild(0, 0, childOfChild);
QCOMPARE(childOfChild->parent(), child);
}
{
QStandardItemModel model;
QStandardItem *item = new QStandardItem;
model.appendRow(item);
// parent of a top-level item should be 0
QCOMPARE(item->parent(), nullptr);
}
}
void tst_QStandardItem::insertColumn_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("column");
QTest::addColumn<int>("count");
QTest::newRow("insert 0 at -1 in 0x0") << 0 << 0 << -1 << 0;
QTest::newRow("insert 0 at 0 in 0x0") << 0 << 0 << 0 << 0;
QTest::newRow("insert 0 at 0 in 1x0") << 1 << 0 << 0 << 0;
QTest::newRow("insert 0 at 0 in 0x1") << 0 << 1 << 0 << 0;
QTest::newRow("insert 0 at 0 in 1x1") << 1 << 1 << 0 << 0;
QTest::newRow("insert 1 at -1 in 0x0") << 0 << 0 << -1 << 1;
QTest::newRow("insert 1 at 0 in 0x0") << 0 << 0 << 0 << 1;
QTest::newRow("insert 1 at 0 in 1x0") << 1 << 0 << 0 << 1;
QTest::newRow("insert 1 at 0 in 0x1") << 0 << 1 << 0 << 1;
QTest::newRow("insert 1 at 0 in 1x1") << 1 << 1 << 0 << 1;
QTest::newRow("insert 1 at 1 in 1x1") << 1 << 1 << 1 << 1;
QTest::newRow("insert 1 at 0 in 2x1") << 2 << 1 << 0 << 1;
QTest::newRow("insert 1 at 1 in 2x1") << 2 << 1 << 1 << 1;
QTest::newRow("insert 1 at 0 in 1x2") << 1 << 2 << 0 << 1;
QTest::newRow("insert 1 at 1 in 1x2") << 1 << 2 << 1 << 1;
QTest::newRow("insert 1 at 0 in 8x4") << 8 << 4 << 0 << 1;
QTest::newRow("insert 1 at 1 in 8x4") << 8 << 4 << 1 << 1;
QTest::newRow("insert 1 at 2 in 8x4") << 8 << 4 << 2 << 1;
QTest::newRow("insert 1 at 3 in 8x4") << 8 << 4 << 3 << 1;
QTest::newRow("insert 1 at 4 in 8x4") << 8 << 4 << 4 << 1;
QTest::newRow("insert 4 at 0 in 8x4") << 8 << 4 << 0 << 4;
QTest::newRow("insert 4 at 4 in 8x4") << 8 << 4 << 4 << 4;
QTest::newRow("insert 6 at 0 in 8x4") << 8 << 4 << 0 << 6;
QTest::newRow("insert 6 at 4 in 8x4") << 8 << 4 << 4 << 6;
}
void tst_QStandardItem::insertColumn()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, column);
QFETCH(int, count);
QStandardItem item(rows, columns);
// make items for a new column
QList<QStandardItem*> columnItems;
for (int i = 0; i < count; ++i)
columnItems.append(new QStandardItem);
item.insertColumn(column, columnItems);
if (column >= 0) {
QCOMPARE(item.columnCount(), columns + 1);
QCOMPARE(item.rowCount(), qMax(rows, count));
// check to make sure items were inserted in correct place
for (int i = 0; i < count; ++i)
QCOMPARE(item.child(i, column), columnItems.at(i));
for (int i = count; i < item.rowCount(); ++i)
QCOMPARE(item.child(i, column), nullptr);
} else {
QCOMPARE(item.columnCount(), columns);
QCOMPARE(item.rowCount(), rows);
qDeleteAll(columnItems);
}
}
void tst_QStandardItem::insertRow_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("row");
QTest::addColumn<int>("count");
QTest::newRow("insert 0 at -1 in 0x0") << 0 << 0 << -1 << 0;
QTest::newRow("insert 0 at 0 in 0x0") << 0 << 0 << 0 << 0;
QTest::newRow("insert 0 at 0 in 1x0") << 1 << 0 << 0 << 0;
QTest::newRow("insert 0 at 0 in 0x1") << 0 << 1 << 0 << 0;
QTest::newRow("insert 0 at 0 in 1x1") << 1 << 1 << 0 << 0;
QTest::newRow("insert 1 at -1 in 0x0") << 0 << 0 << -1 << 1;
QTest::newRow("insert 1 at 0 in 0x0") << 0 << 0 << 0 << 1;
QTest::newRow("insert 1 at 0 in 1x0") << 1 << 0 << 0 << 1;
QTest::newRow("insert 1 at 0 in 0x1") << 0 << 1 << 0 << 1;
QTest::newRow("insert 1 at 0 in 1x1") << 1 << 1 << 0 << 1;
QTest::newRow("insert 1 at 1 in 1x1") << 1 << 1 << 1 << 1;
QTest::newRow("insert 1 at 0 in 2x1") << 2 << 1 << 0 << 1;
QTest::newRow("insert 1 at 1 in 2x1") << 2 << 1 << 1 << 1;
QTest::newRow("insert 1 at 0 in 1x2") << 1 << 2 << 0 << 1;
QTest::newRow("insert 1 at 1 in 1x2") << 1 << 2 << 1 << 1;
QTest::newRow("insert 1 at 0 in 4x8") << 4 << 8 << 0 << 1;
QTest::newRow("insert 1 at 1 in 4x8") << 4 << 8 << 1 << 1;
QTest::newRow("insert 1 at 2 in 4x8") << 4 << 8 << 2 << 1;
QTest::newRow("insert 1 at 3 in 4x8") << 4 << 8 << 3 << 1;
QTest::newRow("insert 1 at 4 in 4x8") << 4 << 8 << 4 << 1;
QTest::newRow("insert 4 at 0 in 4x8") << 4 << 8 << 0 << 4;
QTest::newRow("insert 4 at 4 in 4x8") << 4 << 8 << 4 << 4;
QTest::newRow("insert 6 at 0 in 4x8") << 4 << 8 << 0 << 6;
QTest::newRow("insert 6 at 4 in 4x8") << 4 << 8 << 4 << 6;
}
void tst_QStandardItem::insertRow()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, row);
QFETCH(int, count);
QStandardItem item(rows, columns);
// make items for a new column
QList<QStandardItem*> rowItems;
for (int i = 0; i < count; ++i)
rowItems.append(new QStandardItem);
item.insertRow(row, rowItems);
if (row >= 0) {
QCOMPARE(item.columnCount(), qMax(columns, count));
QCOMPARE(item.rowCount(), rows + 1);
// check to make sure items were inserted in correct place
for (int i = 0; i < count; ++i)
QCOMPARE(item.child(row, i), rowItems.at(i));
for (int i = count; i < item.columnCount(); ++i)
QCOMPARE(item.child(row, i), nullptr);
} else {
QCOMPARE(item.columnCount(), columns);
QCOMPARE(item.rowCount(), rows);
qDeleteAll(rowItems);
}
}
void tst_QStandardItem::insertRows_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("insertAt");
QTest::addColumn<int>("insertCount");
QTest::newRow("insert {0,1} at 0 in 0x0") << 0 << 0 << 0 << 2;
}
void tst_QStandardItem::insertRows()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, insertAt);
QFETCH(int, insertCount);
QStandardItem item(rows, columns);
QList<QStandardItem*> items;
for (int i = 0; i < insertCount; ++i)
items.append(new QStandardItem());
item.insertRows(insertAt, items);
QCOMPARE(item.rowCount(), rows + insertCount);
}
void tst_QStandardItem::appendColumn_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("count");
QTest::newRow("append 0 to 0x0") << 0 << 0 << 0;
QTest::newRow("append 1 to 0x0") << 0 << 0 << 1;
QTest::newRow("append 1 to 1x0") << 1 << 0 << 1;
QTest::newRow("append 1 to 0x1") << 0 << 1 << 1;
QTest::newRow("append 1 to 1x1") << 1 << 1 << 1;
QTest::newRow("append 1 to 2x0") << 2 << 0 << 1;
QTest::newRow("append 1 to 0x2") << 0 << 2 << 1;
QTest::newRow("append 1 to 2x1") << 2 << 1 << 1;
QTest::newRow("append 1 to 1x2") << 1 << 2 << 1;
QTest::newRow("append 1 to 2x2") << 2 << 2 << 1;
QTest::newRow("append 2 to 0x0") << 0 << 0 << 2;
QTest::newRow("append 2 to 1x0") << 1 << 0 << 2;
QTest::newRow("append 2 to 0x1") << 0 << 1 << 2;
QTest::newRow("append 2 to 1x1") << 1 << 1 << 2;
QTest::newRow("append 2 to 2x0") << 2 << 0 << 2;
QTest::newRow("append 2 to 0x2") << 0 << 2 << 2;
QTest::newRow("append 2 to 2x1") << 2 << 1 << 2;
QTest::newRow("append 2 to 1x2") << 1 << 2 << 2;
QTest::newRow("append 2 to 2x2") << 2 << 2 << 2;
QTest::newRow("append 3 to 2x1") << 2 << 1 << 3;
QTest::newRow("append 3 to 1x2") << 1 << 2 << 3;
QTest::newRow("append 3 to 2x2") << 2 << 2 << 3;
QTest::newRow("append 3 to 4x2") << 4 << 2 << 3;
QTest::newRow("append 3 to 2x4") << 2 << 4 << 3;
QTest::newRow("append 3 to 4x4") << 4 << 4 << 3;
QTest::newRow("append 7 to 4x2") << 4 << 2 << 7;
QTest::newRow("append 7 to 2x4") << 2 << 4 << 7;
QTest::newRow("append 7 to 4x4") << 4 << 4 << 7;
}
void tst_QStandardItem::appendColumn()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, count);
QStandardItem item(rows, columns);
QList<QStandardItem*> originalChildren;
// initialize children
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
QStandardItem *child = new QStandardItem;
originalChildren.append(child);
item.setChild(i, j, child);
}
}
// make items for a new column
QList<QStandardItem*> columnItems;
for (int i = 0; i < count; ++i)
columnItems.append(new QStandardItem);
item.appendColumn(columnItems);
QCOMPARE(item.columnCount(), columns + 1);
QCOMPARE(item.rowCount(), qMax(rows, count));
// check to make sure items were inserted in correct place
for (int i = 0; i < count; ++i)
QCOMPARE(item.child(i, columns), columnItems.at(i));
for (int i = count; i < item.rowCount(); ++i)
QCOMPARE(item.child(i, columns), nullptr);
// make sure original children remained unchanged
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j)
QCOMPARE(item.child(i, j), originalChildren.at(i*columns+j));
}
}
void tst_QStandardItem::appendRow_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("count");
QTest::newRow("append 0 to 0x0") << 0 << 0 << 0;
QTest::newRow("append 1 to 0x0") << 0 << 0 << 1;
QTest::newRow("append 1 to 1x0") << 1 << 0 << 1;
QTest::newRow("append 1 to 0x1") << 0 << 1 << 1;
QTest::newRow("append 1 to 1x1") << 1 << 1 << 1;
QTest::newRow("append 1 to 2x0") << 2 << 0 << 1;
QTest::newRow("append 1 to 0x2") << 0 << 2 << 1;
QTest::newRow("append 1 to 2x1") << 2 << 1 << 1;
QTest::newRow("append 1 to 1x2") << 1 << 2 << 1;
QTest::newRow("append 1 to 2x2") << 2 << 2 << 1;
QTest::newRow("append 2 to 0x0") << 0 << 0 << 2;
QTest::newRow("append 2 to 1x0") << 1 << 0 << 2;
QTest::newRow("append 2 to 0x1") << 0 << 1 << 2;
QTest::newRow("append 2 to 1x1") << 1 << 1 << 2;
QTest::newRow("append 2 to 2x0") << 2 << 0 << 2;
QTest::newRow("append 2 to 0x2") << 0 << 2 << 2;
QTest::newRow("append 2 to 2x1") << 2 << 1 << 2;
QTest::newRow("append 2 to 1x2") << 1 << 2 << 2;
QTest::newRow("append 2 to 2x2") << 2 << 2 << 2;
QTest::newRow("append 3 to 2x1") << 2 << 1 << 3;
QTest::newRow("append 3 to 1x2") << 1 << 2 << 3;
QTest::newRow("append 3 to 2x2") << 2 << 2 << 3;
QTest::newRow("append 3 to 4x2") << 4 << 2 << 3;
QTest::newRow("append 3 to 2x4") << 2 << 4 << 3;
QTest::newRow("append 3 to 4x4") << 4 << 4 << 3;
QTest::newRow("append 7 to 4x2") << 4 << 2 << 7;
QTest::newRow("append 7 to 2x4") << 2 << 4 << 7;
QTest::newRow("append 7 to 4x4") << 4 << 4 << 7;
}
void tst_QStandardItem::appendRow()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, count);
QStandardItem item(rows, columns);
QList<QStandardItem*> originalChildren;
// initialize children
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
QStandardItem *child = new QStandardItem;
originalChildren.append(child);
item.setChild(i, j, child);
}
}
// make items for a new row
QList<QStandardItem*> rowItems;
for (int i = 0; i < count; ++i)
rowItems.append(new QStandardItem);
item.appendRow(rowItems);
QCOMPARE(item.rowCount(), rows + 1);
QCOMPARE(item.columnCount(), qMax(columns, count));
// check to make sure items were inserted in correct place
for (int i = 0; i < count; ++i)
QCOMPARE(item.child(rows, i), rowItems.at(i));
for (int i = count; i < item.columnCount(); ++i)
QCOMPARE(item.child(rows, i), nullptr);
// make sure original children remained unchanged
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j)
QCOMPARE(item.child(i, j), originalChildren.at(i*columns+j));
}
}
void tst_QStandardItem::takeChild()
{
QList<QStandardItem*> itemList;
for (int i = 0; i < 10; ++i)
itemList.append(new QStandardItem);
QStandardItem item;
item.appendColumn(itemList);
for (int i = 0; i < item.rowCount(); ++i) {
QCOMPARE(item.takeChild(i), itemList.at(i));
QCOMPARE(item.takeChild(0, 0), nullptr);
for (int j = i + 1; j < item.rowCount(); ++j)
QCOMPARE(item.child(j), itemList.at(j));
}
qDeleteAll(itemList);
}
void tst_QStandardItem::takeColumn_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("column");
QTest::addColumn<bool>("expectSuccess");
QTest::newRow("take -1 from 0x0") << 0 << 0 << -1 << false;
QTest::newRow("take 0 from 0x0") << 0 << 0 << 0 << false;
QTest::newRow("take 0 from 1x0") << 1 << 0 << 0 << false;
QTest::newRow("take 0 from 0x1") << 0 << 1 << 0 << true;
QTest::newRow("take 1 from 0x1") << 0 << 1 << 1 << false;
QTest::newRow("take 0 from 1x1") << 1 << 1 << 0 << true;
QTest::newRow("take 1 from 1x1") << 0 << 1 << 1 << false;
QTest::newRow("take 0 from 4x1") << 4 << 1 << 0 << true;
QTest::newRow("take 1 from 4x1") << 4 << 1 << 1 << false;
QTest::newRow("take 0 from 4x8") << 4 << 8 << 0 << true;
QTest::newRow("take 7 from 4x8") << 4 << 8 << 7 << true;
QTest::newRow("take 8 from 4x8") << 4 << 8 << 8 << false;
}
void tst_QStandardItem::takeColumn()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, column);
QFETCH(bool, expectSuccess);
QStandardItem item(rows, columns);
QList<QStandardItem*> originalChildren;
// initialize children
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
QStandardItem *child = new QStandardItem;
originalChildren.append(child);
item.setChild(i, j, child);
}
}
QList<QStandardItem *> taken = item.takeColumn(column);
if (expectSuccess) {
QCOMPARE(taken.size(), item.rowCount());
QCOMPARE(item.columnCount(), columns - 1);
int index = column;
for (int i = 0; i < taken.size(); ++i) {
QCOMPARE(taken.at(i), originalChildren.takeAt(index));
index += item.columnCount();
}
index = 0;
for (int i = 0; i < item.rowCount(); ++i) {
for (int j = 0; j < item.columnCount(); ++j) {
QCOMPARE(item.child(i, j), originalChildren.at(index));
++index;
}
}
} else {
QVERIFY(taken.isEmpty());
}
qDeleteAll(taken);
}
void tst_QStandardItem::takeRow_data()
{
QTest::addColumn<int>("rows");
QTest::addColumn<int>("columns");
QTest::addColumn<int>("row");
QTest::addColumn<bool>("expectSuccess");
QTest::newRow("take -1 from 0x0") << 0 << 0 << -1 << false;
QTest::newRow("take 0 from 0x0") << 0 << 0 << 0 << false;
QTest::newRow("take 0 from 1x0") << 1 << 0 << 0 << true;
QTest::newRow("take 0 from 0x1") << 0 << 1 << 0 << false;
QTest::newRow("take 1 from 0x1") << 0 << 1 << 1 << false;
QTest::newRow("take 0 from 1x1") << 1 << 1 << 0 << true;
QTest::newRow("take 1 from 1x1") << 0 << 1 << 1 << false;
QTest::newRow("take 0 from 1x4") << 1 << 4 << 0 << true;
QTest::newRow("take 1 from 1x4") << 1 << 4 << 1 << false;
QTest::newRow("take 0 from 8x4") << 8 << 4 << 0 << true;
QTest::newRow("take 7 from 8x4") << 8 << 4 << 7 << true;
QTest::newRow("take 8 from 8x4") << 8 << 4 << 8 << false;
}
void tst_QStandardItem::takeRow()
{
QFETCH(int, rows);
QFETCH(int, columns);
QFETCH(int, row);
QFETCH(bool, expectSuccess);
QStandardItem item(rows, columns);
QList<QStandardItem*> originalChildren;
// initialize children
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
QStandardItem *child = new QStandardItem;
originalChildren.append(child);
item.setChild(i, j, child);
}
}
QList<QStandardItem *> taken = item.takeRow(row);
if (expectSuccess) {
QCOMPARE(taken.size(), item.columnCount());
QCOMPARE(item.rowCount(), rows - 1);
int index = row * columns;
for (int i = 0; i < taken.size(); ++i) {
QCOMPARE(taken.at(i), originalChildren.takeAt(index));
}
index = 0;
for (int i = 0; i < item.rowCount(); ++i) {
for (int j = 0; j < item.columnCount(); ++j) {
QCOMPARE(item.child(i, j), originalChildren.at(index));
++index;
}
}
} else {
QVERIFY(taken.isEmpty());
}
qDeleteAll(taken);
}
void tst_QStandardItem::streamItem()
{
QStandardItem item;
item.setText(QLatin1String("text"));
item.setToolTip(QLatin1String("toolTip"));
item.setStatusTip(QLatin1String("statusTip"));
item.setWhatsThis(QLatin1String("whatsThis"));
item.setSizeHint(QSize(64, 48));
item.setFont(QFont());
item.setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
item.setBackground(QColor(Qt::blue));
item.setForeground(QColor(Qt::green));
item.setCheckState(Qt::PartiallyChecked);
item.setAccessibleText(QLatin1String("accessibleText"));
item.setAccessibleDescription(QLatin1String("accessibleDescription"));
QByteArray ba;
{
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << item;
}
{
QStandardItem streamedItem;
QDataStream ds(&ba, QIODevice::ReadOnly);
ds >> streamedItem;
QCOMPARE(streamedItem.text(), item.text());
QCOMPARE(streamedItem.toolTip(), item.toolTip());
QCOMPARE(streamedItem.statusTip(), item.statusTip());
QCOMPARE(streamedItem.whatsThis(), item.whatsThis());
QCOMPARE(streamedItem.sizeHint(), item.sizeHint());
QCOMPARE(streamedItem.font(), item.font());
QCOMPARE(streamedItem.textAlignment(), item.textAlignment());
QCOMPARE(streamedItem.background(), item.background());
QCOMPARE(streamedItem.foreground(), item.foreground());
QCOMPARE(streamedItem.checkState(), item.checkState());
QCOMPARE(streamedItem.accessibleText(), item.accessibleText());
QCOMPARE(streamedItem.accessibleDescription(), item.accessibleDescription());
QCOMPARE(streamedItem.flags(), item.flags());
}
}
void tst_QStandardItem::deleteItem()
{
QStandardItemModel model(4, 6);
// initialize items
for (int i = 0; i < model.rowCount(); ++i) {
for (int j = 0; j < model.columnCount(); ++j) {
QStandardItem *item = new QStandardItem();
model.setItem(i, j, item);
}
}
// delete items
for (int i = 0; i < model.rowCount(); ++i) {
for (int j = 0; j < model.columnCount(); ++j) {
QStandardItem *item = model.item(i, j);
delete item;
QCOMPARE(model.item(i, j), nullptr);
}
}
}
void tst_QStandardItem::clone()
{
QStandardItem item;
item.setText(QLatin1String("text"));
item.setToolTip(QLatin1String("toolTip"));
item.setStatusTip(QLatin1String("statusTip"));
item.setWhatsThis(QLatin1String("whatsThis"));
item.setSizeHint(QSize(64, 48));
item.setFont(QFont());
item.setTextAlignment(Qt::AlignLeft|Qt::AlignVCenter);
item.setBackground(QColor(Qt::blue));
item.setForeground(QColor(Qt::green));
item.setCheckState(Qt::PartiallyChecked);
item.setAccessibleText(QLatin1String("accessibleText"));
item.setAccessibleDescription(QLatin1String("accessibleDescription"));
item.setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
QStandardItem *clone = item.clone();
QCOMPARE(clone->text(), item.text());
QCOMPARE(clone->toolTip(), item.toolTip());
QCOMPARE(clone->statusTip(), item.statusTip());
QCOMPARE(clone->whatsThis(), item.whatsThis());
QCOMPARE(clone->sizeHint(), item.sizeHint());
QCOMPARE(clone->font(), item.font());
QCOMPARE(clone->textAlignment(), item.textAlignment());
QCOMPARE(clone->background(), item.background());
QCOMPARE(clone->foreground(), item.foreground());
QCOMPARE(clone->checkState(), item.checkState());
QCOMPARE(clone->accessibleText(), item.accessibleText());
QCOMPARE(clone->accessibleDescription(), item.accessibleDescription());
QCOMPARE(clone->flags(), item.flags());
QVERIFY(!(*clone < item));
delete clone;
}
void tst_QStandardItem::sortChildren()
{
for (int x = 0; x < 2; ++x) {
QStandardItemModel *model = new QStandardItemModel;
QStandardItem *item = (x == 0) ? new QStandardItem : model->invisibleRootItem();
QStandardItem *one = new QStandardItem;
one->appendRow(new QStandardItem(QLatin1String("a")));
one->appendRow(new QStandardItem(QLatin1String("b")));
one->appendRow(new QStandardItem(QLatin1String("c")));
QStandardItem *two = new QStandardItem;
two->appendRow(new QStandardItem(QLatin1String("f")));
two->appendRow(new QStandardItem(QLatin1String("d")));
two->appendRow(new QStandardItem(QLatin1String("e")));
item->appendRow(one);
item->appendRow(two);
QSignalSpy layoutAboutToBeChangedSpy(
model, &QAbstractItemModel::layoutAboutToBeChanged);
QSignalSpy layoutChangedSpy(
model, &QAbstractItemModel::layoutChanged);
one->sortChildren(0, Qt::DescendingOrder);
// verify sorted
QCOMPARE(one->child(0)->text(), QLatin1String("c"));
QCOMPARE(one->child(1)->text(), QLatin1String("b"));
QCOMPARE(one->child(2)->text(), QLatin1String("a"));
// verify siblings unaffected
QCOMPARE(two->child(0)->text(), QLatin1String("f"));
QCOMPARE(two->child(1)->text(), QLatin1String("d"));
QCOMPARE(two->child(2)->text(), QLatin1String("e"));
two->sortChildren(0, Qt::AscendingOrder);
// verify sorted
QCOMPARE(two->child(0)->text(), QLatin1String("d"));
QCOMPARE(two->child(1)->text(), QLatin1String("e"));
QCOMPARE(two->child(2)->text(), QLatin1String("f"));
// verify siblings unaffected
QCOMPARE(one->child(0)->text(), QLatin1String("c"));
QCOMPARE(one->child(1)->text(), QLatin1String("b"));
QCOMPARE(one->child(2)->text(), QLatin1String("a"));
item->sortChildren(0, Qt::AscendingOrder);
// verify everything sorted
QCOMPARE(one->child(0)->text(), QLatin1String("a"));
QCOMPARE(one->child(1)->text(), QLatin1String("b"));
QCOMPARE(one->child(2)->text(), QLatin1String("c"));
QCOMPARE(two->child(0)->text(), QLatin1String("d"));
QCOMPARE(two->child(1)->text(), QLatin1String("e"));
QCOMPARE(two->child(2)->text(), QLatin1String("f"));
QCOMPARE(layoutAboutToBeChangedSpy.size(), (x == 0) ? 0 : 3);
QCOMPARE(layoutChangedSpy.size(), (x == 0) ? 0 : 3);
if (x == 0)
delete item;
delete model;
}
}
class CustomItem : public QStandardItem
{
public:
using QStandardItem::QStandardItem;
int type() const override { return QStandardItem::UserType + 1; }
bool operator<(const QStandardItem &other) const override {
return text().size() < other.text().size();
}
using QStandardItem::clone;
using QStandardItem::emitDataChanged;
void setData(const QVariant &value, int role) override
{
switch (role) {
case Qt::DisplayRole:
QStandardItem::setData(value, role);
break;
default:
// setFlags() uses "UserRole - 1" to store the flags, which is an
// implementation detail not exposed in the docs.
QStandardItem::setData(value, role);
break;
}
}
QVariant data(int role) const override
{
switch (role) {
case Qt::DisplayRole:
return QStandardItem::data(role);
default:
// flags() uses "UserRole - 1" to get the flags, which is an implementation
// detail not exposed in the docs.
return QStandardItem::data(role);
}
}
};
Q_DECLARE_METATYPE(QStandardItem*)
void tst_QStandardItem::subclassing()
{
qMetaTypeId<QStandardItem*>();
CustomItem *item = new CustomItem;
QCOMPARE(item->type(), int(QStandardItem::UserType + 1));
item->setText(QString::fromLatin1("foo"));
QCOMPARE(item->text(), QString::fromLatin1("foo"));
item->emitDataChanged(); // does nothing
QStandardItemModel model;
model.appendRow(item);
QSignalSpy itemChangedSpy(&model, &QStandardItemModel::itemChanged);
item->emitDataChanged();
QCOMPARE(itemChangedSpy.size(), 1);
QCOMPARE(itemChangedSpy.at(0).size(), 1);
QCOMPARE(qvariant_cast<QStandardItem*>(itemChangedSpy.at(0).at(0)), item);
CustomItem *child0 = new CustomItem("cc");
CustomItem *child1 = new CustomItem("bbb");
CustomItem *child2 = new CustomItem("a");
item->appendRow(child0);
item->appendRow(child1);
item->appendRow(child2);
item->sortChildren(0);
QCOMPARE(item->child(0), child2);
QCOMPARE(item->child(1), child0);
QCOMPARE(item->child(2), child1);
item->setFlags(Qt::ItemFlags{0});
QCOMPARE(item->flags(), Qt::ItemFlags{0});
item->setFlags(Qt::ItemFlags{Qt::ItemIsEditable | Qt::ItemIsSelectable});
QCOMPARE(item->flags(), Qt::ItemFlags{Qt::ItemIsEditable | Qt::ItemIsSelectable});
}
void tst_QStandardItem::lessThan()
{
QStandardItem stringA("A");
QStandardItem stringB("B");
QStandardItem invalid1;
QStandardItem invalid2;
QVERIFY(stringA < stringB);
QVERIFY(!(stringB < stringA));
// Items with invalid data go to the end.
QVERIFY(stringA < invalid1);
QVERIFY(!(invalid1 < stringA));
QVERIFY(!(invalid1 < invalid2));
}
QTEST_MAIN(tst_QStandardItem)
#include "tst_qstandarditem.moc"