优化LayerTree的数据结构

This commit is contained in:
tangchao0503
2026-03-14 00:38:44 +08:00
parent 1c7780eb14
commit 6d8c2f0419
12 changed files with 239 additions and 126 deletions

View File

@ -905,7 +905,7 @@ void HPPA::removeLayerByTreeIndex()
LayerTreeNode* node = static_cast<LayerTreeNode*>(currentIndexTmp.internalPointer()); LayerTreeNode* node = static_cast<LayerTreeNode*>(currentIndexTmp.internalPointer());
if (!node || node->type() != LayerTreeNode::Type::Layer) return; if (!node || node->type() != LayerTreeNode::Type::Layer) return;
auto* layerNode = static_cast<LayerTreeLayerNode*>(node); auto* layerNode = static_cast<LayerTreeLayer*>(node);
MapLayer* mapLayer = layerNode->mapLayer(); MapLayer* mapLayer = layerNode->mapLayer();
QWidget* layerWidget = nullptr; QWidget* layerWidget = nullptr;
@ -957,7 +957,7 @@ void HPPA::removeAllLayersInRasterGroup()
if (node->type() != LayerTreeNode::Type::Layer) continue; if (node->type() != LayerTreeNode::Type::Layer) continue;
auto* layerNode = static_cast<LayerTreeLayerNode*>(node); auto* layerNode = static_cast<LayerTreeLayer*>(node);
MapLayer* mapLayer = layerNode->mapLayer(); MapLayer* mapLayer = layerNode->mapLayer();
QWidget* layerWidget = nullptr; QWidget* layerWidget = nullptr;
@ -1572,7 +1572,7 @@ void HPPA::onOpenImg()
RasterLayer* rl = new RasterLayer(baseName, uri); RasterLayer* rl = new RasterLayer(baseName, uri);
auto* layerNode = new LayerTreeLayerNode(rl); auto* layerNode = new LayerTreeLayer(rl);
m_LayerTreeModel->addLayer(m_RasterGroup, layerNode); m_LayerTreeModel->addLayer(m_RasterGroup, layerNode);
QWidget* mapcavasContainer = onCreateTab(baseName); QWidget* mapcavasContainer = onCreateTab(baseName);
@ -1722,26 +1722,6 @@ void HPPA::testImagerStatus()
m_TestImagerStausThread->start(); m_TestImagerStausThread->start();
} }
void HPPA::onImageFileSaved(QString path, int fileIndex)
{
// 该槽在 UI 线程中执行Qt 会使用 queued connection可以安全操作 model
QFileInfo fi(path);
QString base = fi.completeBaseName(); // 去掉路径与扩展名(例如 tmp_image_0
// 将新的 layer 添加到 Raster 分组
if (!m_LayerTreeModel || !m_RasterGroup) return;
// layer 名称可根据需要调整,这里用文件名作为图层名
{
auto* ln = new LayerTreeLayerNode(nullptr);
ln->setName(base);
m_LayerTreeModel->addLayer(m_RasterGroup, ln);
}
// 可选:展开 TOC 或者做其他 UI 更新(目前不做动画,仅打印日志)
qDebug() << "ImageFileSaved -> add layer:" << base << " index:" << fileIndex;
}
void HPPA::onAutoExposure() void HPPA::onAutoExposure()
{ {
double ReturnedExposureTime = m_Imager->auto_exposure(); double ReturnedExposureTime = m_Imager->auto_exposure();
@ -2054,9 +2034,9 @@ void HPPA::onLayerCreatedFromFile(const QString& baseName, const QString& filePa
QList<Mapcavas*> mapcavas = mapcavasContainer->findChildren<Mapcavas*>(); QList<Mapcavas*> mapcavas = mapcavasContainer->findChildren<Mapcavas*>();
mapcavas[0]->setLayers(ml); mapcavas[0]->setLayers(ml);
auto* layerNode = new LayerTreeLayerNode(ml); auto* layerNode = new LayerTreeLayer(ml);
LayerTreeNode* node = m_LayerTreeModel->addLayer(m_RasterGroup, layerNode); LayerTreeNode* node = m_LayerTreeModel->addLayer(m_RasterGroup, layerNode);
LayerTreeLayerNode* lnode = dynamic_cast<LayerTreeLayerNode*>(node); LayerTreeLayer* lnode = dynamic_cast<LayerTreeLayer*>(node);
if (!lnode) return; if (!lnode) return;
// layerNode already holds the MapLayer pointer from constructor // layerNode already holds the MapLayer pointer from constructor
@ -2085,7 +2065,7 @@ void HPPA::onLayerTreeSelectionChanged(const QItemSelection& selected, const QIt
return; return;
} }
auto* layerNode = static_cast<LayerTreeLayerNode*>(node); auto* layerNode = static_cast<LayerTreeLayer*>(node);
MapLayer* mapLayer = layerNode->mapLayer(); MapLayer* mapLayer = layerNode->mapLayer();
if (!mapLayer || mapLayer->layerType() != MapLayer::LayerType::Raster) { if (!mapLayer || mapLayer->layerType() != MapLayer::LayerType::Raster) {
m_ic->setActiveLayer(nullptr); m_ic->setActiveLayer(nullptr);

View File

@ -341,8 +341,6 @@ public Q_SLOTS:
void onCreated3DModelPlantPhenotype(); void onCreated3DModelPlantPhenotype();
void onCreated3DModelOneMotor(); void onCreated3DModelOneMotor();
void onImageFileSaved(QString path, int fileIndex);
void onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex); void onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex);
void removeLayerByTreeIndex(); void removeLayerByTreeIndex();
void removeAllLayersInRasterGroup(); void removeAllLayersInRasterGroup();

View File

@ -1,39 +1,13 @@
#include "LayerTree.h" #include "LayerTree.h"
#include "LayerTreeGroupNode.h"
LayerTree::LayerTree(QObject* parent) LayerTree::LayerTree(QObject* parent)
: QObject(parent) : LayerTreeGroup("__root__", parent)
{ {
// root <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><><EFBFBD><EFBFBD>ʾ setVisible(Qt::Checked);
m_root = new LayerTreeGroupNode("__root__", this);
m_root->setVisible(Qt::Checked);
} }
LayerTree::~LayerTree() 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) void LayerTree::setChildrenVisible(LayerTreeNode* n, Qt::CheckState state)

View File

@ -1,18 +1,16 @@
#pragma once #pragma once
#include <QObject> #include "LayerTreeGroupNode.h"
#include "LayerTreeNode.h"
/** /**
* LayerTree<65><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * LayerTree<65><65>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20><><EFBFBD><EFBFBD> root * - <20>̳<EFBFBD><EFBFBD><EFBFBD> LayerTreeGroup<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <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> * - <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> * ע<>⣺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> * LayerTree ֻ<><D6BB><EFBFBD><EFBFBD>ά<EFBFBD><CEAC><EFBFBD><EFBFBD><EFBFBD>ݽṹ<DDBD><E1B9B9>ȷ<EFBFBD>ԡ<EFBFBD>
*/ */
class LayerTree : public QObject class LayerTree : public LayerTreeGroup
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -22,28 +20,7 @@ public:
LayerTree(const LayerTree&) = delete; LayerTree(const LayerTree&) = delete;
LayerTree& operator=(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> // <20>ɼ<EFBFBD><C9BC><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD> Model <20><><EFBFBD>ã<EFBFBD>
static void setChildrenVisible(LayerTreeNode* n, Qt::CheckState state); static void setChildrenVisible(LayerTreeNode* n, Qt::CheckState state);
static void updateParentVisibleFromChildren(LayerTreeNode* parent); 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

@ -1,6 +1,103 @@
#include "LayerTreeGroupNode.h" #include "LayerTreeGroupNode.h"
#include "LayerTreeLayerNode.h"
LayerTreeGroupNode::LayerTreeGroupNode(const QString& name, QObject* parent) LayerTreeGroup::LayerTreeGroup(const QString& name, QObject* parent)
: LayerTreeNode(name, parent) : LayerTreeNode(name, parent)
{ {
} }
LayerTreeGroup* LayerTreeGroup::insertGroup(int index, const QString& name)
{
auto* group = new LayerTreeGroup(name);
insertChildNode(index, group);
return group;
}
LayerTreeGroup* LayerTreeGroup::addGroup(const QString& name)
{
return insertGroup(childCount(), name);
}
LayerTreeLayer* LayerTreeGroup::insertLayer(int index, LayerTreeLayer* layer)
{
if (!layer) return nullptr;
insertChildNode(index, layer);
return layer;
}
LayerTreeLayer* LayerTreeGroup::addLayer(LayerTreeLayer* layer)
{
return insertLayer(childCount(), layer);
}
void LayerTreeGroup::insertChildNode(int index, LayerTreeNode* node)
{
insertChild(index, node);
}
void LayerTreeGroup::addChildNode(LayerTreeNode* node)
{
appendChild(node);
}
LayerTreeNode* LayerTreeGroup::removeChildNode(LayerTreeNode* node)
{
if (!node) return nullptr;
int row = -1;
for (int i = 0; i < childCount(); ++i)
{
if (childAt(i) == node)
{
row = i;
break;
}
}
if (row < 0) return nullptr;
removeChild(row, 1, false);
return node;
}
LayerTreeLayer* LayerTreeGroup::findLayer(const QString& name) const
{
const auto layers = findLayers();
for (auto* l : layers)
{
if (l->name() == name)
return l;
}
return nullptr;
}
QList<LayerTreeLayer*> LayerTreeGroup::findLayers() const
{
QList<LayerTreeLayer*> result;
for (int i = 0; i < childCount(); ++i)
{
LayerTreeNode* child = childAt(i);
if (LayerTreeNode::isLayer(child))
{
result.append(static_cast<LayerTreeLayer*>(child));
}
else if (LayerTreeNode::isGroup(child))
{
result.append(static_cast<LayerTreeGroup*>(child)->findLayers());
}
}
return result;
}
QList<LayerTreeGroup*> LayerTreeGroup::findGroups() const
{
QList<LayerTreeGroup*> result;
for (int i = 0; i < childCount(); ++i)
{
LayerTreeNode* child = childAt(i);
if (LayerTreeNode::isGroup(child))
{
auto* g = static_cast<LayerTreeGroup*>(child);
result.append(g);
result.append(g->findGroups());
}
}
return result;
}

View File

@ -1,15 +1,44 @@
#pragma once #pragma once
#include "LayerTreeNode.h" #include "LayerTreeNode.h"
/** Group <20>ڵ<EFBFBD> */ class LayerTreeLayer;
class LayerTreeGroupNode : public LayerTreeNode
/**
* LayerTreeGroup<75><70>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20><><EFBFBD><EFBFBD>Ϊ LayerTreeNode
* - <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ڵ㣨LayerTreeLayer<65><72><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>飨LayerTreeGroup<75><70><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
class LayerTreeGroup : public LayerTreeNode
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LayerTreeGroupNode(const QString& name, explicit LayerTreeGroup(const QString& name = QString(),
QObject* parent = nullptr); QObject* parent = nullptr);
Type type() const override { return Type::Group; } Type type() const override { return Type::Group; }
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LayerTreeGroup* insertGroup(int index, const QString& name);
LayerTreeGroup* addGroup(const QString& name);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ڵ<EFBFBD>
LayerTreeLayer* insertLayer(int index, LayerTreeLayer* layer);
LayerTreeLayer* addLayer(LayerTreeLayer* layer);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
void insertChildNode(int index, LayerTreeNode* node);
void addChildNode(LayerTreeNode* node);
// <20>Ƴ<EFBFBD><C6B3>ӽڵ㣨<DAB5><E3A3A8> delete<74><65><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1>Ƴ<EFBFBD><C6B3>ڵ㣩
LayerTreeNode* removeChildNode(LayerTreeNode* node);
// <20><><EFBFBD><EFBFBD>
LayerTreeLayer* findLayer(const QString& name) const;
QList<LayerTreeLayer*> findLayers() const;
QList<LayerTreeGroup*> findGroups() const;
// <20>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>collapsed / groupOpacity <20><> // <20>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>collapsed / groupOpacity <20><>
}; };
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
using LayerTreeGroupNode = LayerTreeGroup;

View File

@ -1,22 +1,22 @@
#include "LayerTreeLayerNode.h" #include "LayerTreeLayerNode.h"
LayerTreeLayerNode::LayerTreeLayerNode(MapLayer* layer, QObject* parent) LayerTreeLayer::LayerTreeLayer(MapLayer* layer, QObject* parent)
: LayerTreeNode(layer ? layer->name() : QString(), parent), m_layer(layer) : LayerTreeNode(layer ? layer->name() : QString(), parent), m_layer(layer)
{ {
} }
LayerTreeNode::Type LayerTreeLayerNode::type() const LayerTreeNode::Type LayerTreeLayer::type() const
{ {
return Type::Layer; return Type::Layer;
} }
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD> // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
void LayerTreeLayerNode::setMapLayer(MapLayer* layer) void LayerTreeLayer::setMapLayer(MapLayer* layer)
{ {
m_layer = layer; m_layer = layer;
} }
MapLayer* LayerTreeLayerNode::mapLayer() const MapLayer* LayerTreeLayer::mapLayer() const
{ {
return m_layer; return m_layer;
} }

View File

@ -2,16 +2,19 @@
#include "LayerTreeNode.h" #include "LayerTreeNode.h"
#include "MapLayer.h" #include "MapLayer.h"
/** Layer <20>ڵ<EFBFBD> */ /**
class LayerTreeLayerNode : public LayerTreeNode * LayerTreeLayer<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20><><EFBFBD><EFBFBD>Ϊ LayerTreeNode
* - <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
*/
class LayerTreeLayer : public LayerTreeNode
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LayerTreeLayerNode(MapLayer* layer, QObject* parent = nullptr); explicit LayerTreeLayer(MapLayer* layer, QObject* parent = nullptr);
Type type() const override; Type type() const override;
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
void setMapLayer(MapLayer* layer); void setMapLayer(MapLayer* layer);
MapLayer* mapLayer() const; MapLayer* mapLayer() const;
@ -20,3 +23,6 @@ private:
// <20><><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>layerId / pointer / legendItems <20><> // <20><><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>layerId / pointer / legendItems <20><>
}; };
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
using LayerTreeLayerNode = LayerTreeLayer;

View File

@ -28,10 +28,10 @@ QModelIndex LayerTreeModel::index(int row, int column, const QModelIndex& parent
QModelIndex LayerTreeModel::parent(const QModelIndex& child) const QModelIndex LayerTreeModel::parent(const QModelIndex& child) const
{ {
LayerTreeNode* node = nodeFromIndex(child); LayerTreeNode* node = nodeFromIndex(child);
if (!node || node == m_tree->root()) return {}; if (!node || node == m_tree) return {};
LayerTreeNode* p = node->parentNode(); LayerTreeNode* p = node->parentNode();
if (!p || p == m_tree->root()) return {}; if (!p || p == m_tree) return {};
return createIndex(p->rowInParent(), 0, p); return createIndex(p->rowInParent(), 0, p);
} }
@ -50,7 +50,7 @@ int LayerTreeModel::columnCount(const QModelIndex&) const
QVariant LayerTreeModel::data(const QModelIndex& index, int role) const QVariant LayerTreeModel::data(const QModelIndex& index, int role) const
{ {
LayerTreeNode* n = nodeFromIndex(index); LayerTreeNode* n = nodeFromIndex(index);
if (!n || n == m_tree->root()) return {}; if (!n || n == m_tree) return {};
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
@ -59,9 +59,9 @@ QVariant LayerTreeModel::data(const QModelIndex& index, int role) const
case Qt::DecorationRole: case Qt::DecorationRole:
{ {
auto* tmp = nodeFromIndex(index); auto* tmp = nodeFromIndex(index);
if (LayerTree::isGroup(tmp)) if (LayerTreeNode::isGroup(tmp))
return QIcon(); return QIcon();
else if (LayerTree::isLayer(tmp)) else if (LayerTreeNode::isLayer(tmp))
{ {
QString basePath = QCoreApplication::applicationDirPath(); QString basePath = QCoreApplication::applicationDirPath();
return QIcon(basePath + "/icons/mIconRaster.svg"); return QIcon(basePath + "/icons/mIconRaster.svg");
@ -82,7 +82,7 @@ QVariant LayerTreeModel::data(const QModelIndex& index, int role) const
bool LayerTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) bool LayerTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
{ {
LayerTreeNode* n = nodeFromIndex(index); LayerTreeNode* n = nodeFromIndex(index);
if (!n || n == m_tree->root()) return false; if (!n || n == m_tree) return false;
if (role == Qt::CheckStateRole) { if (role == Qt::CheckStateRole) {
auto newState = static_cast<Qt::CheckState>(value.toInt()); auto newState = static_cast<Qt::CheckState>(value.toInt());
@ -111,39 +111,39 @@ Qt::ItemFlags LayerTreeModel::flags(const QModelIndex& index) const
if (!index.isValid()) return Qt::NoItemFlags; if (!index.isValid()) return Qt::NoItemFlags;
LayerTreeNode* n = nodeFromIndex(index); LayerTreeNode* n = nodeFromIndex(index);
if (!n || n == m_tree->root()) return Qt::NoItemFlags; if (!n || n == m_tree) return Qt::NoItemFlags;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
} }
LayerTreeNode* LayerTreeModel::root() const LayerTreeNode* LayerTreeModel::root() const
{ {
return m_tree->root(); return m_tree;
} }
LayerTreeNode* LayerTreeModel::addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon) LayerTreeNode* LayerTreeModel::addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon)
{ {
if (!parent) parent = m_tree->root(); if (!parent) parent = m_tree;
const int row = parent->childCount(); const int row = parent->childCount();
beginInsertRows(indexFromNode(parent), row, row); beginInsertRows(indexFromNode(parent), row, row);
LayerTreeNode* g = m_tree->insertNode(parent, row, new LayerTreeGroupNode(name)); LayerTreeNode* g = m_tree->addGroup(name);
endInsertRows(); endInsertRows();
return g; return g;
} }
LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, LayerTreeLayerNode* layerNode, const QIcon& icon) LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, LayerTreeLayer* layerNode, const QIcon& icon)
{ {
if (!parent) parent = m_tree->root(); if (!parent) parent = m_tree;
if (!layerNode) return nullptr; if (!layerNode) return nullptr;
const int row = parent->childCount(); const int row = parent->childCount();
beginInsertRows(indexFromNode(parent), row, row); beginInsertRows(indexFromNode(parent), row, row);
LayerTreeNode* l = m_tree->insertNode(parent, row, layerNode); parent->insertChild(row, layerNode);
endInsertRows(); endInsertRows();
return l; return layerNode;
} }
void LayerTreeModel::setCascadeCheckEnabled(bool enabled) void LayerTreeModel::setCascadeCheckEnabled(bool enabled)
@ -159,11 +159,12 @@ bool LayerTreeModel::cascadeCheckEnabled() const
// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3>Ƴ<EFBFBD><C6B3>ӽڵ㲢<DAB5><E3B2A2> model <20>Ϸ<EFBFBD><CFB7><EFBFBD> begin/endRemoveRows // <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3>Ƴ<EFBFBD><C6B3>ӽڵ㲢<DAB5><E3B2A2> model <20>Ϸ<EFBFBD><CFB7><EFBFBD> begin/endRemoveRows
LayerTreeNode* LayerTreeModel::removeNode(LayerTreeNode* parent, int row) LayerTreeNode* LayerTreeModel::removeNode(LayerTreeNode* parent, int row)
{ {
if (!parent) parent = m_tree->root(); if (!parent) parent = m_tree;
if (row < 0 || row >= parent->childCount()) return nullptr; if (row < 0 || row >= parent->childCount()) return nullptr;
LayerTreeNode* removed = parent->childAt(row);
beginRemoveRows(indexFromNode(parent), row, row); beginRemoveRows(indexFromNode(parent), row, row);
LayerTreeNode* removed = m_tree->removeNode(parent, row); parent->removeChild(row, 1, false);
endRemoveRows(); endRemoveRows();
return removed; return removed;
@ -171,12 +172,12 @@ LayerTreeNode* LayerTreeModel::removeNode(LayerTreeNode* parent, int row)
LayerTreeNode* LayerTreeModel::nodeFromIndex(const QModelIndex& index) const LayerTreeNode* LayerTreeModel::nodeFromIndex(const QModelIndex& index) const
{ {
if (!index.isValid()) return m_tree->root(); if (!index.isValid()) return m_tree;
return static_cast<LayerTreeNode*>(index.internalPointer()); return static_cast<LayerTreeNode*>(index.internalPointer());
} }
QModelIndex LayerTreeModel::indexFromNode(LayerTreeNode* n) const QModelIndex LayerTreeModel::indexFromNode(LayerTreeNode* n) const
{ {
if (!n || n == m_tree->root()) return {}; if (!n || n == m_tree) return {};
return createIndex(n->rowInParent(), 0, n); return createIndex(n->rowInParent(), 0, n);
} }

View File

@ -3,7 +3,7 @@
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include "LayerTree.h" #include "LayerTree.h"
class LayerTreeLayerNode; // forward declare class LayerTreeLayer; // forward declare
/** /**
* LayerTreeModel<65><6C>Qt <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3A8><EFBFBD>ٹ<EFBFBD><D9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * LayerTreeModel<65><6C>Qt <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3A8><EFBFBD>ٹ<EFBFBD><D9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@ -34,7 +34,7 @@ public:
LayerTreeNode* root() const; LayerTreeNode* root() const;
LayerTreeNode* addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon()); LayerTreeNode* addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon());
LayerTreeNode* addLayer(LayerTreeNode* parent, LayerTreeLayerNode* layerNode, const QIcon& icon = QIcon()); LayerTreeNode* addLayer(LayerTreeNode* parent, LayerTreeLayer* layerNode, const QIcon& icon = QIcon());
void setCascadeCheckEnabled(bool enabled); void setCascadeCheckEnabled(bool enabled);
bool cascadeCheckEnabled() const; bool cascadeCheckEnabled() const;

View File

@ -20,7 +20,11 @@ QString LayerTreeNode::name() const
void LayerTreeNode::setName(const QString& name) void LayerTreeNode::setName(const QString& name)
{ {
if (m_name != name)
{
m_name = name; m_name = name;
emit nameChanged(this, name);
}
} }
QIcon LayerTreeNode::icon() const QIcon LayerTreeNode::icon() const
@ -97,14 +101,35 @@ void LayerTreeNode::insertChild(int row, LayerTreeNode* child)
if (row < 0 || row > m_children.size()) if (row < 0 || row > m_children.size())
row = m_children.size(); row = m_children.size();
emit willAddChildren(this, row, row);
child->setParentNode(this); child->setParentNode(this);
m_children.insert(row, child); m_children.insert(row, child);
emit addedChildren(this, row, row);
} }
LayerTreeNode* LayerTreeNode::takeChild(int row) void LayerTreeNode::removeChild(int from, int count, bool destroy)
{ {
if (row < 0 || row >= m_children.size()) return nullptr; if (from < 0 || count <= 0 || from + count > m_children.size()) return;
LayerTreeNode* taken = m_children.takeAt(row);
if (taken) taken->setParentNode(nullptr); emit willRemoveChildren(this, from, from + count - 1);
return taken;
QVector<LayerTreeNode*> removed;
removed.reserve(count);
for (int i = 0; i < count; ++i)
{
removed.append(m_children.at(from));
m_children.removeAt(from);
}
for (LayerTreeNode* node : removed)
{
node->setParentNode(nullptr);
}
emit removedChildren(this, from, from + count - 1);
if (destroy)
{
qDeleteAll(removed);
}
} }

View File

@ -9,9 +9,10 @@
* LayerTreeNode<64><65><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><E0A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 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>ϵ * - <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> * - Group / Layer <20>ڵ<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>̳<EFBFBD>ʵ<EFBFBD><CAB5>
* - <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD><><C9BE><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ź<EFBFBD>֪ͨ
* *
* ˵<><CBB5><EFBFBD><EFBFBD> * ˵<><CBB5><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD>ͬʱά<CAB1><CEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>m_parentNode<EFBFBD><EFBFBD><EFBFBD><EFBFBD> QObject parent<6E><74><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1> * - <20><><EFBFBD><EFBFBD>ͬʱά<CAB1><CEAC>"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>"<EFBFBD><EFBFBD>m_parentNode<EFBFBD><EFBFBD><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> * - 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 class LayerTreeNode : public QObject
@ -50,7 +51,32 @@ public:
// ---- structure mutation (used by LayerTree / Model) ---- // ---- structure mutation (used by LayerTree / Model) ----
void appendChild(LayerTreeNode* child); void appendChild(LayerTreeNode* child);
void insertChild(int row, LayerTreeNode* child); void insertChild(int row, LayerTreeNode* child);
LayerTreeNode* takeChild(int row); // remove but not delete
// <20><><EFBFBD><EFBFBD> QgsLayerTreeNode::removeChildrenPrivate <20>Ľ<EFBFBD>
// from: <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>, count: <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>, destroy: true <20><> delete <20><><EFBFBD>Ƴ<EFBFBD><C6B3>ڵ<EFBFBD>
void removeChild(int from, int count, bool destroy = true);
// ---- static type helpers ----
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;
}
signals:
// <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>ӽڵ<D3BD>֮ǰ/֮<>󷢳<EFBFBD>
void willAddChildren(LayerTreeNode* node, int indexFrom, int indexTo);
void addedChildren(LayerTreeNode* node, int indexFrom, int indexTo);
// <20><><EFBFBD>Ƴ<EFBFBD><C6B3>ӽڵ<D3BD>֮ǰ/֮<>󷢳<EFBFBD>
void willRemoveChildren(LayerTreeNode* node, int indexFrom, int indexTo);
void removedChildren(LayerTreeNode* node, int indexFrom, int indexTo);
void nameChanged(LayerTreeNode* node, const QString& name);
protected: protected:
void setParentNode(LayerTreeNode* p); void setParentNode(LayerTreeNode* p);