初步实现单独的图层管理器。

注意:没有和mapcavas通讯。
This commit is contained in:
tangchao0503
2026-02-05 15:32:34 +08:00
parent 7d123ca11c
commit 631216dc66
14 changed files with 643 additions and 13 deletions

View File

@ -131,6 +131,7 @@ HPPA::HPPA(QWidget* parent)
addDockWidget(Qt::LeftDockWidgetArea, dock_layers); addDockWidget(Qt::LeftDockWidgetArea, dock_layers);
dock_layers->hideMaxButton(); dock_layers->hideMaxButton();
//1、没用
QWidget* dock_layersWidgetContents = new QWidget(); QWidget* dock_layersWidgetContents = new QWidget();
dock_layersWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents_2")); dock_layersWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents_2"));
QGridLayout* gridLayout_toc = new QGridLayout(dock_layersWidgetContents); QGridLayout* gridLayout_toc = new QGridLayout(dock_layersWidgetContents);
@ -151,6 +152,7 @@ HPPA::HPPA(QWidget* parent)
graphicsView_delete->setFrameShadow(QFrame::Raised); graphicsView_delete->setFrameShadow(QFrame::Raised);
//gridLayout_toc->addWidget(graphicsView_delete, 0, 0, 1, 1); //gridLayout_toc->addWidget(graphicsView_delete, 0, 0, 1, 1);
//2、没用仅仅使用QTreeWidget实现的简略ui
QTreeWidget* treeWidget = new QTreeWidget(); QTreeWidget* treeWidget = new QTreeWidget();
treeWidget->setColumnCount(1); treeWidget->setColumnCount(1);
treeWidget->setIndentation(18); treeWidget->setIndentation(18);
@ -177,9 +179,6 @@ HPPA::HPPA(QWidget* parent)
border-image: none; border-image: none;
image: url(D:/cpp_project_vs2022/HPPA/x64/Debug/3DModel/tree_tri_down.svg); image: url(D:/cpp_project_vs2022/HPPA/x64/Debug/3DModel/tree_tri_down.svg);
} }
)"); )");
//QList<QTreeWidgetItem*> items; //QList<QTreeWidgetItem*> items;
@ -201,8 +200,51 @@ HPPA::HPPA(QWidget* parent)
QTreeWidgetItem* layerB = new QTreeWidgetItem(group1); QTreeWidgetItem* layerB = new QTreeWidgetItem(group1);
layerB->setText(0, "tmp_image_2"); 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_layers->setWidget(dock_layersWidgetContents);
dock_layersWidgetContents->setStyleSheet(qss_DockWidget_contentWidget); dock_layersWidgetContents->setStyleSheet(qss_DockWidget_contentWidget);

View File

@ -51,6 +51,9 @@
#include "View3DModelManager.h" #include "View3DModelManager.h"
#include "LayerTreeModel.h"
#include "LayerTree.h"
#define PI 3.1415926 #define PI 3.1415926
QT_CHARTS_USE_NAMESPACE//QChartView ʹ<><CAB9> <20><>Ҫ<EFBFBD>Ӻ꣬ <20><><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>ʹ<EFBFBD><CAB9> QT_CHARTS_USE_NAMESPACE//QChartView ʹ<><CAB9> <20><>Ҫ<EFBFBD>Ӻ꣬ <20><><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD>ʹ<EFBFBD><CAB9>

View File

@ -114,6 +114,11 @@
<ClCompile Include="ImagerOperationBase.cpp" /> <ClCompile Include="ImagerOperationBase.cpp" />
<ClCompile Include="imager_base.cpp" /> <ClCompile Include="imager_base.cpp" />
<ClCompile Include="irisximeaimager.cpp" /> <ClCompile Include="irisximeaimager.cpp" />
<ClCompile Include="LayerTree.cpp" />
<ClCompile Include="LayerTreeGroupNode.cpp" />
<ClCompile Include="LayerTreeLayerNode.cpp" />
<ClCompile Include="LayerTreeModel.cpp" />
<ClCompile Include="LayerTreeNode.cpp" />
<ClCompile Include="OneMotorControl.cpp" /> <ClCompile Include="OneMotorControl.cpp" />
<ClCompile Include="path_tc.cpp" /> <ClCompile Include="path_tc.cpp" />
<ClCompile Include="PowerControl.cpp" /> <ClCompile Include="PowerControl.cpp" />
@ -180,6 +185,11 @@
<QtMoc Include="OneMotorControl.h" /> <QtMoc Include="OneMotorControl.h" />
<QtMoc Include="TwoMotorControl.h" /> <QtMoc Include="TwoMotorControl.h" />
<QtMoc Include="TabManager.h" /> <QtMoc Include="TabManager.h" />
<QtMoc Include="LayerTreeModel.h" />
<QtMoc Include="LayerTreeNode.h" />
<QtMoc Include="LayerTree.h" />
<QtMoc Include="LayerTreeGroupNode.h" />
<QtMoc Include="LayerTreeLayerNode.h" />
<ClInclude Include="utility_tc.h" /> <ClInclude Include="utility_tc.h" />
<QtMoc Include="aboutWindow.h" /> <QtMoc Include="aboutWindow.h" />
<ClInclude Include="hppaConfigFile.h" /> <ClInclude Include="hppaConfigFile.h" />

View File

@ -21,15 +21,6 @@
<UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier> <UniqueIdentifier>{639EADAA-A684-42e4-A9AD-28FC9BCB8F7C}</UniqueIdentifier>
<Extensions>ts</Extensions> <Extensions>ts</Extensions>
</Filter> </Filter>
<Filter Include="Header Files\motor">
<UniqueIdentifier>{eadfac5f-f4f9-49e2-9f99-0849bf074cf8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\motor">
<UniqueIdentifier>{4672856c-86fb-46e3-94ff-0a296dcc6111}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\focus">
<UniqueIdentifier>{f2bfb93e-9ef8-4fdd-a776-db93b81af553}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtRcc Include="HPPA.qrc"> <QtRcc Include="HPPA.qrc">
@ -148,6 +139,21 @@
<ClCompile Include="View3DModelManager.cpp"> <ClCompile Include="View3DModelManager.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="LayerTreeNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LayerTreeModel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LayerTree.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LayerTreeGroupNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LayerTreeLayerNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="fileOperation.h"> <QtMoc Include="fileOperation.h">
@ -222,6 +228,21 @@
<QtMoc Include="View3DModelManager.h"> <QtMoc Include="View3DModelManager.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="LayerTreeModel.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="LayerTreeNode.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="LayerTree.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="LayerTreeGroupNode.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="LayerTreeLayerNode.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="imageProcessor.h"> <ClInclude Include="imageProcessor.h">

73
HPPA/LayerTree.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "LayerTree.h"
#include "LayerTreeGroupNode.h"
LayerTree::LayerTree(QObject* parent)
: QObject(parent)
{
// root <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><><EFBFBD><EFBFBD>ʾ
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());
}
}

49
HPPA/LayerTree.h Normal file
View File

@ -0,0 +1,49 @@
#pragma once
#include <QObject>
#include "LayerTreeNode.h"
/**
* LayerTree<65><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD> root
* - <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD>/<2F>Ƴ<EFBFBD><C6B3>ڵ<EFBFBD><DAB5><EFBFBD> API
* - <20><EFBFBD>ɼ<EFBFBD><C9BC>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>̬<EFBFBD><CCAC><EFBFBD>µľ<C2B5>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>
*
* ע<>⣺beginInsertRows/endInsertRows <20><> Qt Model <20><><EFBFBD><EFBFBD>֪ͨӦ<D6AA><D3A6> Model <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
* LayerTree ֻ<><D6BB><EFBFBD><EFBFBD>ά<EFBFBD><CEAC><EFBFBD><EFBFBD><EFBFBD>ݽṹ<DDBD><E1B9B9>ȷ<EFBFBD>ԡ<EFBFBD>
*/
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;
// <20><><EFBFBD>룺parent Ϊ nullptr <20><>ʾ root<6F><74>row=-1 <20><>ʾ append
LayerTreeNode* insertNode(LayerTreeNode* parent, int row, LayerTreeNode* node);
// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD> delete<74><65><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1>Ƴ<EFBFBD><C6B3>ڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD>߸<EFBFBD><DFB8><EFBFBD> delete <20><><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2>
LayerTreeNode* removeNode(LayerTreeNode* parent, int row);
// <20>ɼ<EFBFBD><C9BC><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD> Model <20><><EFBFBD>ã<EFBFBD>
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
};

View File

@ -0,0 +1,6 @@
#include "LayerTreeGroupNode.h"
LayerTreeGroupNode::LayerTreeGroupNode(const QString& name, QObject* parent)
: LayerTreeNode(name, parent)
{
}

15
HPPA/LayerTreeGroupNode.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include "LayerTreeNode.h"
/** Group <20>ڵ<EFBFBD> */
class LayerTreeGroupNode : public LayerTreeNode
{
Q_OBJECT
public:
explicit LayerTreeGroupNode(const QString& name,
QObject* parent = nullptr);
Type type() const override { return Type::Group; }
// <20>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>collapsed / groupOpacity <20><>
};

View File

@ -0,0 +1,6 @@
#include "LayerTreeLayerNode.h"
LayerTreeLayerNode::LayerTreeLayerNode(const QString& name, QObject* parent)
: LayerTreeNode(name, parent)
{
}

15
HPPA/LayerTreeLayerNode.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include "LayerTreeNode.h"
/** Layer <20>ڵ<EFBFBD> */
class LayerTreeLayerNode : public LayerTreeNode
{
Q_OBJECT
public:
explicit LayerTreeLayerNode(const QString& name,
QObject* parent = nullptr);
Type type() const override { return Type::Layer; }
// <20>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>layerId / pointer / legendItems <20><>
};

168
HPPA/LayerTreeModel.cpp Normal file
View File

@ -0,0 +1,168 @@
#include "LayerTreeModel.h"
#include "LayerTreeGroupNode.h"
#include "LayerTreeLayerNode.h"
#include <QtGlobal>
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<int>(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<Qt::CheckState>(value.toInt());
if (n->visible() == newState) return true;
n->setVisible(newState);
// 1) <20><> -> <20><> <20><><EFBFBD><EFBFBD>
if (m_cascadeCheck) {
LayerTree::setChildrenVisible(n, newState);
}
// 2) <20><> -> <20><> <20><><EFBFBD><EFBFBD> PartiallyChecked
LayerTree::updateParentVisibleFromChildren(n->parentNode());
// <20>򻯣<EFBFBD><F2BBAFA3><EFBFBD><EFBFBD><EFBFBD>ˢ<EFBFBD>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻Ϊ<E6BBBB><CEAA>׼ dataChanged<65><64>
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<LayerTreeNode*>(index.internalPointer());
}
QModelIndex LayerTreeModel::indexFromNode(LayerTreeNode* n) const
{
if (!n || n == m_tree->root()) return {};
return createIndex(n->rowInParent(), 0, n);
}

47
HPPA/LayerTreeModel.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include <QCoreApplication>
#include <QAbstractItemModel>
#include "LayerTree.h"
/**
* LayerTreeModel<65><6C>Qt <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3A8><EFBFBD>ٹ<EFBFBD><D9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - 1 <20>У<EFBFBD><D0A3><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD>ͼ<EFBFBD>꣩+ checkbox
* - <20><>ѡ<EFBFBD>ɼ<EFBFBD><C9BC>ԣ<EFBFBD><D4A3><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
*/
class LayerTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit LayerTreeModel(LayerTree* tree,
QObject* parent = nullptr,
bool cascadeCheck = true);
~LayerTreeModel() override = default;
// QAbstractItemModel <20><><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>
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;
// <20><><EFBFBD><EFBFBD> API<50><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD> begin/endInsertRows<77><73>
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;
};

110
HPPA/LayerTreeNode.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "LayerTreeNode.h"
#include <QtGlobal>
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;
// <20><> QObject <20><> parent Ҳ<><D2B2><EFBFBD><EFBFBD><E6A3A8><EFBFBD><EFBFBD> Qt <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ι<EFBFBD><CEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD> delete children<65><6E>
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*>& 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;
}

65
HPPA/LayerTreeNode.h Normal file
View File

@ -0,0 +1,65 @@
#pragma once
#include <QObject>
#include <QVector>
#include <QIcon>
#include <QString>
/**
* LayerTreeNode<64><65><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><E0A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><><CDBC>/<2F>ɼ<EFBFBD><C9BC><EFBFBD>/<2F><><EFBFBD>ӹ<EFBFBD>ϵ
* - Group / Layer <20>ڵ<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>̳<EFBFBD>ʵ<EFBFBD><CAB5>
*
* ˵<><CBB5><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD>ͬʱά<CAB1><CEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EBA1B1>m_parentNode<64><65><EFBFBD><EFBFBD> QObject parent<6E><74><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
* - children <20>ɽڵ<C9BD><DAB5>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷţ<CDB7><C5A3><EFBFBD><EFBFBD><EFBFBD>ʱ delete children<65><6E>
*/
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<LayerTreeNode*>& 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<LayerTreeNode*> m_children;
};