From 631216dc6609b3a0860681b288e8657c6e03db23 Mon Sep 17 00:00:00 2001 From: tangchao0503 <735056338@qq.com> Date: Thu, 5 Feb 2026 15:32:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E7=9A=84=E5=9B=BE=E5=B1=82=E7=AE=A1=E7=90=86=E5=99=A8?= =?UTF-8?q?=E3=80=82=20=E6=B3=A8=E6=84=8F=EF=BC=9A=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=92=8Cmapcavas=E9=80=9A=E8=AE=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HPPA/HPPA.cpp | 50 ++++++++++- HPPA/HPPA.h | 3 + HPPA/HPPA.vcxproj | 10 +++ HPPA/HPPA.vcxproj.filters | 39 +++++++-- HPPA/LayerTree.cpp | 73 ++++++++++++++++ HPPA/LayerTree.h | 49 +++++++++++ HPPA/LayerTreeGroupNode.cpp | 6 ++ HPPA/LayerTreeGroupNode.h | 15 ++++ HPPA/LayerTreeLayerNode.cpp | 6 ++ HPPA/LayerTreeLayerNode.h | 15 ++++ HPPA/LayerTreeModel.cpp | 168 ++++++++++++++++++++++++++++++++++++ HPPA/LayerTreeModel.h | 47 ++++++++++ HPPA/LayerTreeNode.cpp | 110 +++++++++++++++++++++++ HPPA/LayerTreeNode.h | 65 ++++++++++++++ 14 files changed, 643 insertions(+), 13 deletions(-) create mode 100644 HPPA/LayerTree.cpp create mode 100644 HPPA/LayerTree.h create mode 100644 HPPA/LayerTreeGroupNode.cpp create mode 100644 HPPA/LayerTreeGroupNode.h create mode 100644 HPPA/LayerTreeLayerNode.cpp create mode 100644 HPPA/LayerTreeLayerNode.h create mode 100644 HPPA/LayerTreeModel.cpp create mode 100644 HPPA/LayerTreeModel.h create mode 100644 HPPA/LayerTreeNode.cpp create mode 100644 HPPA/LayerTreeNode.h diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index dc2aeb0..23e71d9 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -131,6 +131,7 @@ HPPA::HPPA(QWidget* parent) addDockWidget(Qt::LeftDockWidgetArea, dock_layers); dock_layers->hideMaxButton(); + //1、没用 QWidget* dock_layersWidgetContents = new QWidget(); dock_layersWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents_2")); QGridLayout* gridLayout_toc = new QGridLayout(dock_layersWidgetContents); @@ -151,6 +152,7 @@ HPPA::HPPA(QWidget* parent) graphicsView_delete->setFrameShadow(QFrame::Raised); //gridLayout_toc->addWidget(graphicsView_delete, 0, 0, 1, 1); + //2、没用,仅仅使用QTreeWidget实现的简略ui QTreeWidget* treeWidget = new QTreeWidget(); treeWidget->setColumnCount(1); treeWidget->setIndentation(18); @@ -177,9 +179,6 @@ HPPA::HPPA(QWidget* parent) border-image: none; image: url(D:/cpp_project_vs2022/HPPA/x64/Debug/3DModel/tree_tri_down.svg); } - - - )"); //QList items; @@ -201,8 +200,51 @@ HPPA::HPPA(QWidget* parent) QTreeWidgetItem* layerB = new QTreeWidgetItem(group1); layerB->setText(0, "tmp_image_2"); - gridLayout_toc->addWidget(treeWidget, 0, 0, 1, 1); + //gridLayout_toc->addWidget(treeWidget, 0, 0, 1, 1); + //3、正经TOC + LayerTree* tree = new LayerTree(); + auto* model = new LayerTreeModel(tree, this, true); + + //auto* g1 = model->addGroup(model->root(), "Group A"); + //model->addLayer(g1, "Roads"); + //model->addLayer(g1, "Buildings"); + + + auto* g1 = model->addGroup(model->root(), "Raster"); + model->addLayer(g1, "tmp_image_1"); + model->addLayer(g1, "tmp_image_2"); + + auto* g2 = model->addGroup(model->root(), "Vector"); + //model->addLayer(g2, "Rivers"); + + QTreeView* LayerTreeView = new QTreeView(); + LayerTreeView->setModel(model); + LayerTreeView->setHeaderHidden(true); + LayerTreeView->setStyleSheet(R"( + QTreeView + { + color: #ACCDFF; + } + QTreeView::branch { + background: transparent; + } + + QTreeView::branch:has-children:!has-siblings:closed, + QTreeView::branch:closed:has-children:has-siblings + { + border-image: none; + image: url(D:/cpp_project_vs2022/HPPA/x64/Debug/3DModel/tree_tri_right.svg); + } + QTreeView::branch:open:has-children:!has-siblings, + QTreeView::branch:open:has-children:has-siblings + { + border-image: none; + image: url(D:/cpp_project_vs2022/HPPA/x64/Debug/3DModel/tree_tri_down.svg); + } + )"); + + gridLayout_toc->addWidget(LayerTreeView, 0, 0, 1, 1); dock_layers->setWidget(dock_layersWidgetContents); dock_layersWidgetContents->setStyleSheet(qss_DockWidget_contentWidget); diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index b14a8fd..28fe91b 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -51,6 +51,9 @@ #include "View3DModelManager.h" +#include "LayerTreeModel.h" +#include "LayerTree.h" + #define PI 3.1415926 QT_CHARTS_USE_NAMESPACE//QChartView ʹ ҪӺ꣬ ޷ʹ diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj index 85499e2..434052c 100644 --- a/HPPA/HPPA.vcxproj +++ b/HPPA/HPPA.vcxproj @@ -114,6 +114,11 @@ + + + + + @@ -180,6 +185,11 @@ + + + + + diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters index 89c22cc..fd08928 100644 --- a/HPPA/HPPA.vcxproj.filters +++ b/HPPA/HPPA.vcxproj.filters @@ -21,15 +21,6 @@ {639EADAA-A684-42e4-A9AD-28FC9BCB8F7C} ts - - {eadfac5f-f4f9-49e2-9f99-0849bf074cf8} - - - {4672856c-86fb-46e3-94ff-0a296dcc6111} - - - {f2bfb93e-9ef8-4fdd-a776-db93b81af553} - @@ -148,6 +139,21 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -222,6 +228,21 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/HPPA/LayerTree.cpp b/HPPA/LayerTree.cpp new file mode 100644 index 0000000..208e066 --- /dev/null +++ b/HPPA/LayerTree.cpp @@ -0,0 +1,73 @@ +#include "LayerTree.h" +#include "LayerTreeGroupNode.h" + +LayerTree::LayerTree(QObject* parent) + : QObject(parent) +{ + // root Ϊ view ʾ + m_root = new LayerTreeGroupNode("__root__", this); + m_root->setVisible(Qt::Checked); +} + +LayerTree::~LayerTree() +{ + delete m_root; + m_root = nullptr; +} + +LayerTreeNode* LayerTree::root() const +{ + return m_root; +} + +LayerTreeNode* LayerTree::insertNode(LayerTreeNode* parent, int row, LayerTreeNode* node) +{ + if (!node) return nullptr; + if (!parent) parent = m_root; + + if (row < 0) row = parent->childCount(); + parent->insertChild(row, node); + return node; +} + +LayerTreeNode* LayerTree::removeNode(LayerTreeNode* parent, int row) +{ + if (!parent) parent = m_root; + return parent->takeChild(row); +} + +void LayerTree::setChildrenVisible(LayerTreeNode* n, Qt::CheckState state) +{ + if (!n) return; + const auto& cs = n->children(); + for (LayerTreeNode* c : cs) { + c->setVisible(state); + setChildrenVisible(c, state); + } +} + +void LayerTree::updateParentVisibleFromChildren(LayerTreeNode* p) +{ + if (!p) return; + if (p->childCount() == 0) return; + + int checked = 0, unchecked = 0, partial = 0; + const auto& cs = p->children(); + for (LayerTreeNode* c : cs) { + auto s = c->visible(); + if (s == Qt::Checked) checked++; + else if (s == Qt::Unchecked) unchecked++; + else partial++; + } + + Qt::CheckState newState; + if (partial > 0) newState = Qt::PartiallyChecked; + else if (checked > 0 && unchecked == 0) newState = Qt::Checked; + else if (unchecked > 0 && checked == 0) newState = Qt::Unchecked; + else newState = Qt::PartiallyChecked; + + if (p->visible() != newState) { + p->setVisible(newState); + updateParentVisibleFromChildren(p->parentNode()); + } +} diff --git a/HPPA/LayerTree.h b/HPPA/LayerTree.h new file mode 100644 index 0000000..41a880d --- /dev/null +++ b/HPPA/LayerTree.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include "LayerTreeNode.h" + +/** + * LayerTreeĿ¼ + * - root + * - ṩ/Ƴڵ API + * - ṩɼԼ븸ڵ̬µľ̬ + * + * ע⣺beginInsertRows/endInsertRows Qt Model ֪ͨӦ Model ã + * LayerTree ֻάݽṹȷԡ + */ +class LayerTree : public QObject +{ + Q_OBJECT +public: + explicit LayerTree(QObject* parent = nullptr); + ~LayerTree() override; + + LayerTree(const LayerTree&) = delete; + LayerTree& operator=(const LayerTree&) = delete; + + LayerTreeNode* root() const; + + // 룺parent Ϊ nullptr ʾ rootrow=-1 ʾ append + LayerTreeNode* insertNode(LayerTreeNode* parent, int row, LayerTreeNode* node); + + // Ƴ deleteرƳڵ㣨߸ delete ²룩 + LayerTreeNode* removeNode(LayerTreeNode* parent, int row); + + // ɼ߼ Model ã + static void setChildrenVisible(LayerTreeNode* n, Qt::CheckState state); + static void updateParentVisibleFromChildren(LayerTreeNode* parent); + + static inline bool isLayer(LayerTreeNode* node) + { + return node && node->type() == LayerTreeNode::Type::Layer; + } + + static inline bool isGroup(LayerTreeNode* node) + { + return node && node->type() == LayerTreeNode::Type::Group; + } + +private: + LayerTreeNode* m_root = nullptr; // owned +}; diff --git a/HPPA/LayerTreeGroupNode.cpp b/HPPA/LayerTreeGroupNode.cpp new file mode 100644 index 0000000..056df55 --- /dev/null +++ b/HPPA/LayerTreeGroupNode.cpp @@ -0,0 +1,6 @@ +#include "LayerTreeGroupNode.h" + +LayerTreeGroupNode::LayerTreeGroupNode(const QString& name, QObject* parent) + : LayerTreeNode(name, parent) +{ +} diff --git a/HPPA/LayerTreeGroupNode.h b/HPPA/LayerTreeGroupNode.h new file mode 100644 index 0000000..6b1015a --- /dev/null +++ b/HPPA/LayerTreeGroupNode.h @@ -0,0 +1,15 @@ +#pragma once +#include "LayerTreeNode.h" + +/** Group ڵ */ +class LayerTreeGroupNode : public LayerTreeNode +{ + Q_OBJECT +public: + explicit LayerTreeGroupNode(const QString& name, + QObject* parent = nullptr); + + Type type() const override { return Type::Group; } + + // Ժչcollapsed / groupOpacity +}; diff --git a/HPPA/LayerTreeLayerNode.cpp b/HPPA/LayerTreeLayerNode.cpp new file mode 100644 index 0000000..a2ba524 --- /dev/null +++ b/HPPA/LayerTreeLayerNode.cpp @@ -0,0 +1,6 @@ +#include "LayerTreeLayerNode.h" + +LayerTreeLayerNode::LayerTreeLayerNode(const QString& name, QObject* parent) + : LayerTreeNode(name, parent) +{ +} diff --git a/HPPA/LayerTreeLayerNode.h b/HPPA/LayerTreeLayerNode.h new file mode 100644 index 0000000..e12b971 --- /dev/null +++ b/HPPA/LayerTreeLayerNode.h @@ -0,0 +1,15 @@ +#pragma once +#include "LayerTreeNode.h" + +/** Layer ڵ */ +class LayerTreeLayerNode : public LayerTreeNode +{ + Q_OBJECT +public: + explicit LayerTreeLayerNode(const QString& name, + QObject* parent = nullptr); + + Type type() const override { return Type::Layer; } + + // ԺչlayerId / pointer / legendItems +}; diff --git a/HPPA/LayerTreeModel.cpp b/HPPA/LayerTreeModel.cpp new file mode 100644 index 0000000..a888bb7 --- /dev/null +++ b/HPPA/LayerTreeModel.cpp @@ -0,0 +1,168 @@ +#include "LayerTreeModel.h" +#include "LayerTreeGroupNode.h" +#include "LayerTreeLayerNode.h" + +#include + +LayerTreeModel::LayerTreeModel(LayerTree* tree, QObject* parent, bool cascadeCheck) + : QAbstractItemModel(parent), + m_tree(tree), + m_cascadeCheck(cascadeCheck) +{ + Q_ASSERT(m_tree && "LayerTreeModel requires a valid LayerTree*"); +} + +QModelIndex LayerTreeModel::index(int row, int column, const QModelIndex& parent) const +{ + if (column != 0 || row < 0) return {}; + + LayerTreeNode* parentNode = nodeFromIndex(parent); + if (!parentNode) return {}; + + LayerTreeNode* child = parentNode->childAt(row); + if (!child) return {}; + + return createIndex(row, column, child); +} + +QModelIndex LayerTreeModel::parent(const QModelIndex& child) const +{ + LayerTreeNode* node = nodeFromIndex(child); + if (!node || node == m_tree->root()) return {}; + + LayerTreeNode* p = node->parentNode(); + if (!p || p == m_tree->root()) return {}; + + return createIndex(p->rowInParent(), 0, p); +} + +int LayerTreeModel::rowCount(const QModelIndex& parent) const +{ + LayerTreeNode* p = nodeFromIndex(parent); + return p ? p->childCount() : 0; +} + +int LayerTreeModel::columnCount(const QModelIndex&) const +{ + return 1; +} + +QVariant LayerTreeModel::data(const QModelIndex& index, int role) const +{ + LayerTreeNode* n = nodeFromIndex(index); + if (!n || n == m_tree->root()) return {}; + + switch (role) { + case Qt::DisplayRole: + return n->name(); + + case Qt::DecorationRole: + { + auto* tmp = nodeFromIndex(index); + if (LayerTree::isGroup(tmp)) + return QIcon(); + else if (LayerTree::isLayer(tmp)) + { + QString basePath = QCoreApplication::applicationDirPath(); + return QIcon(basePath + "/icons/mIconRaster.svg"); + } + } + + case Qt::CheckStateRole: + return static_cast(n->visible()); + + case Qt::ToolTipRole: + return (n->type() == LayerTreeNode::Type::Group) ? "Group" : "Layer"; + + default: + return {}; + } +} + +bool LayerTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + LayerTreeNode* n = nodeFromIndex(index); + if (!n || n == m_tree->root()) return false; + + if (role == Qt::CheckStateRole) { + auto newState = static_cast(value.toInt()); + if (n->visible() == newState) return true; + + n->setVisible(newState); + + // 1) -> + if (m_cascadeCheck) { + LayerTree::setChildrenVisible(n, newState); + } + + // 2) -> PartiallyChecked + LayerTree::updateParentVisibleFromChildren(n->parentNode()); + + // 򻯣ˢ£滻Ϊ׼ dataChanged + emit layoutChanged(); + return true; + } + + return false; +} + +Qt::ItemFlags LayerTreeModel::flags(const QModelIndex& index) const +{ + if (!index.isValid()) return Qt::NoItemFlags; + + LayerTreeNode* n = nodeFromIndex(index); + if (!n || n == m_tree->root()) return Qt::NoItemFlags; + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; +} + +LayerTreeNode* LayerTreeModel::root() const +{ + return m_tree->root(); +} + +LayerTreeNode* LayerTreeModel::addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon) +{ + if (!parent) parent = m_tree->root(); + + const int row = parent->childCount(); + beginInsertRows(indexFromNode(parent), row, row); + LayerTreeNode* g = m_tree->insertNode(parent, row, new LayerTreeGroupNode(name)); + endInsertRows(); + + return g; +} + +LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, const QString& name, const QIcon& icon) +{ + if (!parent) parent = m_tree->root(); + + const int row = parent->childCount(); + beginInsertRows(indexFromNode(parent), row, row); + LayerTreeNode* l = m_tree->insertNode(parent, row, new LayerTreeLayerNode(name)); + endInsertRows(); + + return l; +} + +void LayerTreeModel::setCascadeCheckEnabled(bool enabled) +{ + m_cascadeCheck = enabled; +} + +bool LayerTreeModel::cascadeCheckEnabled() const +{ + return m_cascadeCheck; +} + +LayerTreeNode* LayerTreeModel::nodeFromIndex(const QModelIndex& index) const +{ + if (!index.isValid()) return m_tree->root(); + return static_cast(index.internalPointer()); +} + +QModelIndex LayerTreeModel::indexFromNode(LayerTreeNode* n) const +{ + if (!n || n == m_tree->root()) return {}; + return createIndex(n->rowInParent(), 0, n); +} diff --git a/HPPA/LayerTreeModel.h b/HPPA/LayerTreeModel.h new file mode 100644 index 0000000..2473bfe --- /dev/null +++ b/HPPA/LayerTreeModel.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include "LayerTree.h" + +/** + * LayerTreeModelQt 㣨ٹ + * - 1 Уƣͼ꣩+ checkbox + * - ѡɼԣѡѡ + */ +class LayerTreeModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit LayerTreeModel(LayerTree* tree, + QObject* parent = nullptr, + bool cascadeCheck = true); + ~LayerTreeModel() override = default; + + // QAbstractItemModel ӿ + QModelIndex index(int row, int column, + const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role) override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + + // APIڲȷ begin/endInsertRows + LayerTreeNode* root() const; + + LayerTreeNode* addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon()); + LayerTreeNode* addLayer(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon()); + + void setCascadeCheckEnabled(bool enabled); + bool cascadeCheckEnabled() const; + +private: + LayerTree* m_tree = nullptr; // not owned + bool m_cascadeCheck = true; + +private: + LayerTreeNode* nodeFromIndex(const QModelIndex& index) const; + QModelIndex indexFromNode(LayerTreeNode* n) const; +}; diff --git a/HPPA/LayerTreeNode.cpp b/HPPA/LayerTreeNode.cpp new file mode 100644 index 0000000..1504104 --- /dev/null +++ b/HPPA/LayerTreeNode.cpp @@ -0,0 +1,110 @@ +#include "LayerTreeNode.h" + +#include + +LayerTreeNode::LayerTreeNode(const QString& name, QObject* parent) + : QObject(parent), m_name(name) +{ +} + +LayerTreeNode::~LayerTreeNode() +{ + qDeleteAll(m_children); + m_children.clear(); +} + +QString LayerTreeNode::name() const +{ + return m_name; +} + +void LayerTreeNode::setName(const QString& name) +{ + m_name = name; +} + +QIcon LayerTreeNode::icon() const +{ + return m_icon; +} + +void LayerTreeNode::setIcon(const QIcon& icon) +{ + m_icon = icon; +} + +Qt::CheckState LayerTreeNode::visible() const +{ + return m_visible; +} + +void LayerTreeNode::setVisible(Qt::CheckState s) +{ + m_visible = s; +} + +LayerTreeNode* LayerTreeNode::parentNode() const +{ + return m_parentNode; +} + +void LayerTreeNode::setParentNode(LayerTreeNode* p) +{ + m_parentNode = p; + // QObject parent Ҳ棨 Qt ιҲӰֶ delete children + if (p) this->setParent(p); + else this->setParent(nullptr); +} + +int LayerTreeNode::rowInParent() const +{ + if (!m_parentNode) return 0; + + const auto& siblings = m_parentNode->m_children; + for (int i = 0; i < siblings.size(); ++i) + { + if (siblings[i] == this) return i; + } + + return 0; +} + +int LayerTreeNode::childCount() const +{ + return m_children.size(); +} + +LayerTreeNode* LayerTreeNode::childAt(int row) const +{ + if (row < 0 || row >= m_children.size()) return nullptr; + return m_children[row]; +} + +const QVector& LayerTreeNode::children() const +{ + return m_children; +} + +void LayerTreeNode::appendChild(LayerTreeNode* child) +{ + insertChild(m_children.size(), child); +} + +void LayerTreeNode::insertChild(int row, LayerTreeNode* child) +{ + if (!child) return; + + if (row < 0 || row > m_children.size()) + row = m_children.size(); + + child->setParentNode(this); + m_children.insert(row, child); +} + +LayerTreeNode* LayerTreeNode::takeChild(int row) +{ + if (row < 0 || row >= m_children.size()) return nullptr; + LayerTreeNode* taken = m_children.takeAt(row); + if (taken) taken->setParentNode(nullptr); + return taken; +} diff --git a/HPPA/LayerTreeNode.h b/HPPA/LayerTreeNode.h new file mode 100644 index 0000000..1f0bb64 --- /dev/null +++ b/HPPA/LayerTreeNode.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include +#include + +/** + * LayerTreeNodeڵࣨ + * - ͨԣ/ͼ/ɼ/ӹϵ + * - Group / Layer ڵ̳ͨʵ + * + * ˵ + * - ͬʱάָ롱m_parentNode QObject parentѡ + * - children ɽڵԼвͷţʱ delete children + */ +class LayerTreeNode : public QObject +{ + Q_OBJECT +public: + enum class Type { Group, Layer }; + + explicit LayerTreeNode(const QString& name, + QObject* parent = nullptr); + ~LayerTreeNode() override; + + LayerTreeNode(const LayerTreeNode&) = delete; + LayerTreeNode& operator=(const LayerTreeNode&) = delete; + + virtual Type type() const = 0; + + // ---- properties ---- + QString name() const; + void setName(const QString& name); + + QIcon icon() const; + void setIcon(const QIcon& icon); + + Qt::CheckState visible() const; + void setVisible(Qt::CheckState s); + + // ---- tree relations ---- + LayerTreeNode* parentNode() const; + int rowInParent() const; + + int childCount() const; + LayerTreeNode* childAt(int row) const; + const QVector& children() const; + + // ---- structure mutation (used by LayerTree / Model) ---- + void appendChild(LayerTreeNode* child); + void insertChild(int row, LayerTreeNode* child); + LayerTreeNode* takeChild(int row); // remove but not delete + +protected: + void setParentNode(LayerTreeNode* p); + +private: + QString m_name; + QIcon m_icon; + Qt::CheckState m_visible = Qt::Checked; + + LayerTreeNode* m_parentNode = nullptr; + QVector m_children; +};