summaryrefslogtreecommitdiffstats
path: root/examples/widgets/itemviews/simpletreemodel
diff options
context:
space:
mode:
Diffstat (limited to 'examples/widgets/itemviews/simpletreemodel')
-rw-r--r--examples/widgets/itemviews/simpletreemodel/CMakeLists.txt55
-rw-r--r--examples/widgets/itemviews/simpletreemodel/main.cpp20
-rw-r--r--examples/widgets/itemviews/simpletreemodel/test.cpp35
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treeitem.cpp54
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treeitem.h9
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treemodel.cpp125
-rw-r--r--examples/widgets/itemviews/simpletreemodel/treemodel.h14
7 files changed, 179 insertions, 133 deletions
diff --git a/examples/widgets/itemviews/simpletreemodel/CMakeLists.txt b/examples/widgets/itemviews/simpletreemodel/CMakeLists.txt
index 519810f70f..2fd31fae43 100644
--- a/examples/widgets/itemviews/simpletreemodel/CMakeLists.txt
+++ b/examples/widgets/itemviews/simpletreemodel/CMakeLists.txt
@@ -1,16 +1,10 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(simpletreemodel LANGUAGES CXX)
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/itemviews/simpletreemodel")
-
-find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Test Widgets)
qt_standard_project_setup()
@@ -44,7 +38,46 @@ qt_add_resources(simpletreemodel "simpletreemodel"
)
install(TARGETS simpletreemodel
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
+
+qt_generate_deploy_app_script(
+ TARGET simpletreemodel
+ OUTPUT_SCRIPT deploy_script
+ NO_UNSUPPORTED_PLATFORM_ERROR
+)
+install(SCRIPT ${deploy_script})
+
+#! [1]
+# Unit Test
+
+include(CTest)
+
+qt_add_executable(simpletreemodel_tester
+ test.cpp
+ treeitem.cpp treeitem.h
+ treemodel.cpp treemodel.h)
+
+target_link_libraries(simpletreemodel_tester PRIVATE
+ Qt6::Core
+ Qt6::Test
+)
+
+if(ANDROID)
+ target_link_libraries(simpletreemodel_tester PRIVATE
+ Qt6::Gui
+ )
+endif()
+
+qt_add_resources(simpletreemodel_tester "simpletreemodel"
+ PREFIX
+ "/"
+ FILES
+ ${simpletreemodel_resource_files}
+)
+
+add_test(NAME simpletreemodel_tester
+ COMMAND simpletreemodel_tester)
+#! [1]
diff --git a/examples/widgets/itemviews/simpletreemodel/main.cpp b/examples/widgets/itemviews/simpletreemodel/main.cpp
index 10075a18e5..5800c595c8 100644
--- a/examples/widgets/itemviews/simpletreemodel/main.cpp
+++ b/examples/widgets/itemviews/simpletreemodel/main.cpp
@@ -5,22 +5,28 @@
#include <QApplication>
#include <QFile>
+#include <QScreen>
#include <QTreeView>
+using namespace Qt::StringLiterals;
+
int main(int argc, char *argv[])
{
- Q_INIT_RESOURCE(simpletreemodel);
-
QApplication app(argc, argv);
- QFile file(":/default.txt");
- file.open(QIODevice::ReadOnly);
- TreeModel model(file.readAll());
+ QFile file(":/default.txt"_L1);
+ file.open(QIODevice::ReadOnly | QIODevice::Text);
+ TreeModel model(QString::fromUtf8(file.readAll()));
file.close();
QTreeView view;
view.setModel(&model);
- view.setWindowTitle(QObject::tr("Simple Tree Model"));
+ view.setWindowTitle(TreeModel::tr("Simple Tree Model"));
+ for (int c = 0; c < model.columnCount(); ++c)
+ view.resizeColumnToContents(c);
+ view.expandAll();
+ const auto screenSize = view.screen()->availableSize();
+ view.resize({screenSize.width() / 2, screenSize.height() * 2 / 3});
view.show();
- return app.exec();
+ return QCoreApplication::exec();
}
diff --git a/examples/widgets/itemviews/simpletreemodel/test.cpp b/examples/widgets/itemviews/simpletreemodel/test.cpp
new file mode 100644
index 0000000000..7e9479a396
--- /dev/null
+++ b/examples/widgets/itemviews/simpletreemodel/test.cpp
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "treemodel.h"
+
+#include <QObject>
+#include <QAbstractItemModelTester>
+#include <QTest>
+
+using namespace Qt::StringLiterals;
+
+//! [1]
+class TestSimpleTreeModel : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testTreeModel();
+};
+
+void TestSimpleTreeModel::testTreeModel()
+{
+ constexpr auto fileName = ":/default.txt"_L1;
+ QFile file(fileName);
+ QVERIFY2(file.open(QIODevice::ReadOnly | QIODevice::Text),
+ qPrintable(fileName + " cannot be opened: "_L1 + file.errorString()));
+ TreeModel model(QString::fromUtf8(file.readAll()));
+
+ QAbstractItemModelTester tester(&model);
+}
+
+QTEST_APPLESS_MAIN(TestSimpleTreeModel)
+
+#include "test.moc"
+//! [1]
diff --git a/examples/widgets/itemviews/simpletreemodel/treeitem.cpp b/examples/widgets/itemviews/simpletreemodel/treeitem.cpp
index 59292bbbca..67e021d622 100644
--- a/examples/widgets/itemviews/simpletreemodel/treeitem.cpp
+++ b/examples/widgets/itemviews/simpletreemodel/treeitem.cpp
@@ -10,70 +10,66 @@
#include "treeitem.h"
//! [0]
-TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
- : m_itemData(data), m_parentItem(parent)
+TreeItem::TreeItem(QVariantList data, TreeItem *parent)
+ : m_itemData(std::move(data)), m_parentItem(parent)
{}
//! [0]
//! [1]
-TreeItem::~TreeItem()
+void TreeItem::appendChild(std::unique_ptr<TreeItem> &&child)
{
- qDeleteAll(m_childItems);
+ m_childItems.push_back(std::move(child));
}
//! [1]
//! [2]
-void TreeItem::appendChild(TreeItem *item)
+TreeItem *TreeItem::child(int row)
{
- m_childItems.append(item);
+ return row >= 0 && row < childCount() ? m_childItems.at(row).get() : nullptr;
}
//! [2]
//! [3]
-TreeItem *TreeItem::child(int row)
+int TreeItem::childCount() const
{
- if (row < 0 || row >= m_childItems.size())
- return nullptr;
- return m_childItems.at(row);
+ return int(m_childItems.size());
}
//! [3]
//! [4]
-int TreeItem::childCount() const
+int TreeItem::columnCount() const
{
- return m_childItems.count();
+ return int(m_itemData.count());
}
//! [4]
//! [5]
-int TreeItem::columnCount() const
+QVariant TreeItem::data(int column) const
{
- return m_itemData.count();
+ return m_itemData.value(column);
}
//! [5]
//! [6]
-QVariant TreeItem::data(int column) const
-{
- if (column < 0 || column >= m_itemData.size())
- return QVariant();
- return m_itemData.at(column);
-}
-//! [6]
-
-//! [7]
TreeItem *TreeItem::parentItem()
{
return m_parentItem;
}
-//! [7]
+//! [6]
-//! [8]
+//! [7]
int TreeItem::row() const
{
- if (m_parentItem)
- return m_parentItem->m_childItems.indexOf(const_cast<TreeItem*>(this));
+ if (m_parentItem == nullptr)
+ return 0;
+ const auto it = std::find_if(m_parentItem->m_childItems.cbegin(), m_parentItem->m_childItems.cend(),
+ [this](const std::unique_ptr<TreeItem> &treeItem) {
+ return treeItem.get() == this;
+ });
- return 0;
+ if (it != m_parentItem->m_childItems.cend())
+ return std::distance(m_parentItem->m_childItems.cbegin(), it);
+ Q_ASSERT(false); // should not happen
+ return -1;
}
-//! [8]
+//! [7]
diff --git a/examples/widgets/itemviews/simpletreemodel/treeitem.h b/examples/widgets/itemviews/simpletreemodel/treeitem.h
index b2508b9058..b9002f06fd 100644
--- a/examples/widgets/itemviews/simpletreemodel/treeitem.h
+++ b/examples/widgets/itemviews/simpletreemodel/treeitem.h
@@ -11,10 +11,9 @@
class TreeItem
{
public:
- explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = nullptr);
- ~TreeItem();
+ explicit TreeItem(QVariantList data, TreeItem *parentItem = nullptr);
- void appendChild(TreeItem *child);
+ void appendChild(std::unique_ptr<TreeItem> &&child);
TreeItem *child(int row);
int childCount() const;
@@ -24,8 +23,8 @@ public:
TreeItem *parentItem();
private:
- QList<TreeItem *> m_childItems;
- QList<QVariant> m_itemData;
+ std::vector<std::unique_ptr<TreeItem>> m_childItems;
+ QVariantList m_itemData;
TreeItem *m_parentItem;
};
//! [0]
diff --git a/examples/widgets/itemviews/simpletreemodel/treemodel.cpp b/examples/widgets/itemviews/simpletreemodel/treemodel.cpp
index 1665f18ebe..8538d99629 100644
--- a/examples/widgets/itemviews/simpletreemodel/treemodel.cpp
+++ b/examples/widgets/itemviews/simpletreemodel/treemodel.cpp
@@ -13,20 +13,19 @@
#include <QStringList>
+using namespace Qt::StringLiterals;
+
//! [0]
TreeModel::TreeModel(const QString &data, QObject *parent)
: QAbstractItemModel(parent)
+ , rootItem(std::make_unique<TreeItem>(QVariantList{tr("Title"), tr("Summary")}))
{
- rootItem = new TreeItem({tr("Title"), tr("Summary")});
- setupModelData(data.split('\n'), rootItem);
+ setupModelData(QStringView{data}.split(u'\n'), rootItem.get());
}
//! [0]
//! [1]
-TreeModel::~TreeModel()
-{
- delete rootItem;
-}
+TreeModel::~TreeModel() = default;
//! [1]
//! [2]
@@ -41,14 +40,10 @@ int TreeModel::columnCount(const QModelIndex &parent) const
//! [3]
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid())
- return QVariant();
-
- if (role != Qt::DisplayRole)
- return QVariant();
-
- TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
+ if (!index.isValid() || role != Qt::DisplayRole)
+ return {};
+ const auto *item = static_cast<const TreeItem*>(index.internalPointer());
return item->data(index.column());
}
//! [3]
@@ -56,10 +51,8 @@ QVariant TreeModel::data(const QModelIndex &index, int role) const
//! [4]
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
- if (!index.isValid())
- return Qt::NoItemFlags;
-
- return QAbstractItemModel::flags(index);
+ return index.isValid()
+ ? QAbstractItemModel::flags(index) : Qt::ItemFlags(Qt::NoItemFlags);
}
//! [4]
@@ -67,10 +60,8 @@ Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
- if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
- return rootItem->data(section);
-
- return QVariant();
+ return orientation == Qt::Horizontal && role == Qt::DisplayRole
+ ? rootItem->data(section) : QVariant{};
}
//! [5]
@@ -78,19 +69,15 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
- return QModelIndex();
-
- TreeItem *parentItem;
+ return {};
- if (!parent.isValid())
- parentItem = rootItem;
- else
- parentItem = static_cast<TreeItem*>(parent.internalPointer());
+ TreeItem *parentItem = parent.isValid()
+ ? static_cast<TreeItem*>(parent.internalPointer())
+ : rootItem.get();
- TreeItem *childItem = parentItem->child(row);
- if (childItem)
+ if (auto *childItem = parentItem->child(row))
return createIndex(row, column, childItem);
- return QModelIndex();
+ return {};
}
//! [6]
@@ -98,80 +85,68 @@ QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) con
QModelIndex TreeModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
- return QModelIndex();
+ return {};
- TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
+ auto *childItem = static_cast<TreeItem*>(index.internalPointer());
TreeItem *parentItem = childItem->parentItem();
- if (parentItem == rootItem)
- return QModelIndex();
-
- return createIndex(parentItem->row(), 0, parentItem);
+ return parentItem != rootItem.get()
+ ? createIndex(parentItem->row(), 0, parentItem) : QModelIndex{};
}
//! [7]
//! [8]
int TreeModel::rowCount(const QModelIndex &parent) const
{
- TreeItem *parentItem;
if (parent.column() > 0)
return 0;
- if (!parent.isValid())
- parentItem = rootItem;
- else
- parentItem = static_cast<TreeItem*>(parent.internalPointer());
+ const TreeItem *parentItem = parent.isValid()
+ ? static_cast<const TreeItem*>(parent.internalPointer())
+ : rootItem.get();
return parentItem->childCount();
}
//! [8]
-void TreeModel::setupModelData(const QStringList &lines, TreeItem *parent)
+void TreeModel::setupModelData(const QList<QStringView> &lines, TreeItem *parent)
{
- QList<TreeItem *> parents;
- QList<int> indentations;
- parents << parent;
- indentations << 0;
-
- int number = 0;
-
- while (number < lines.count()) {
- int position = 0;
- while (position < lines[number].length()) {
- if (lines[number].at(position) != ' ')
- break;
- position++;
- }
+ struct ParentIndentation
+ {
+ TreeItem *parent;
+ qsizetype indentation;
+ };
- const QString lineData = lines[number].mid(position).trimmed();
+ QList<ParentIndentation> state{{parent, 0}};
+ for (const auto &line : lines) {
+ qsizetype position = 0;
+ for ( ; position < line.length() && line.at(position).isSpace(); ++position) {
+ }
+
+ const QStringView lineData = line.sliced(position).trimmed();
if (!lineData.isEmpty()) {
// Read the column data from the rest of the line.
- const QStringList columnStrings =
- lineData.split(QLatin1Char('\t'), Qt::SkipEmptyParts);
- QList<QVariant> columnData;
+ const auto columnStrings = lineData.split(u'\t', Qt::SkipEmptyParts);
+ QVariantList columnData;
columnData.reserve(columnStrings.count());
- for (const QString &columnString : columnStrings)
- columnData << columnString;
+ for (const auto &columnString : columnStrings)
+ columnData << columnString.toString();
- if (position > indentations.last()) {
+ if (position > state.constLast().indentation) {
// The last child of the current parent is now the new parent
// unless the current parent has no children.
-
- if (parents.last()->childCount() > 0) {
- parents << parents.last()->child(parents.last()->childCount()-1);
- indentations << position;
- }
+ auto *lastParent = state.constLast().parent;
+ if (lastParent->childCount() > 0)
+ state.append({lastParent->child(lastParent->childCount() - 1), position});
} else {
- while (position < indentations.last() && parents.count() > 0) {
- parents.pop_back();
- indentations.pop_back();
- }
+ while (position < state.constLast().indentation && !state.isEmpty())
+ state.removeLast();
}
// Append a new item to the current parent's list of children.
- parents.last()->appendChild(new TreeItem(columnData, parents.last()));
+ auto *lastParent = state.constLast().parent;
+ lastParent->appendChild(std::make_unique<TreeItem>(columnData, lastParent));
}
- ++number;
}
}
diff --git a/examples/widgets/itemviews/simpletreemodel/treemodel.h b/examples/widgets/itemviews/simpletreemodel/treemodel.h
index aa93c33494..1a42fa585f 100644
--- a/examples/widgets/itemviews/simpletreemodel/treemodel.h
+++ b/examples/widgets/itemviews/simpletreemodel/treemodel.h
@@ -16,23 +16,25 @@ class TreeModel : public QAbstractItemModel
Q_OBJECT
public:
+ Q_DISABLE_COPY_MOVE(TreeModel)
+
explicit TreeModel(const QString &data, QObject *parent = nullptr);
- ~TreeModel();
+ ~TreeModel() override;
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column,
- const QModelIndex &parent = QModelIndex()) const override;
+ const QModelIndex &parent = {}) const override;
QModelIndex parent(const QModelIndex &index) const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ int rowCount(const QModelIndex &parent = {}) const override;
+ int columnCount(const QModelIndex &parent = {}) const override;
private:
- void setupModelData(const QStringList &lines, TreeItem *parent);
+ static void setupModelData(const QList<QStringView> &lines, TreeItem *parent);
- TreeItem *rootItem;
+ std::unique_ptr<TreeItem> rootItem;
};
//! [0]