184 lines
4.7 KiB
C++
184 lines
4.7 KiB
C++
#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) return {};
|
||
|
||
LayerTreeNode* p = node->parentNode();
|
||
if (!p || p == m_tree) 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) return {};
|
||
|
||
switch (role) {
|
||
case Qt::DisplayRole:
|
||
return n->name();
|
||
|
||
case Qt::DecorationRole:
|
||
{
|
||
auto* tmp = nodeFromIndex(index);
|
||
if (LayerTreeNode::isGroup(tmp))
|
||
return QIcon();
|
||
else if (LayerTreeNode::isLayer(tmp))
|
||
{
|
||
QString basePath = QCoreApplication::applicationDirPath();
|
||
return QIcon(":/svg/resources/icons/svg/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) return false;
|
||
|
||
if (role == Qt::CheckStateRole) {
|
||
auto newState = static_cast<Qt::CheckState>(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) return Qt::NoItemFlags;
|
||
|
||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
|
||
}
|
||
|
||
LayerTreeNode* LayerTreeModel::root() const
|
||
{
|
||
return m_tree;
|
||
}
|
||
|
||
LayerTreeNode* LayerTreeModel::addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon)
|
||
{
|
||
if (!parent) parent = m_tree;
|
||
|
||
const int row = parent->childCount();
|
||
beginInsertRows(indexFromNode(parent), row, row);
|
||
LayerTreeNode* g = m_tree->addGroup(name);
|
||
endInsertRows();
|
||
|
||
return g;
|
||
}
|
||
|
||
LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, LayerTreeNode* layerNode, const QIcon& icon)
|
||
{
|
||
if (!parent) parent = m_tree;
|
||
if (!layerNode) return nullptr;
|
||
|
||
const int row = parent->childCount();
|
||
beginInsertRows(indexFromNode(parent), row, row);
|
||
parent->insertChild(row, layerNode);
|
||
endInsertRows();
|
||
|
||
return layerNode;
|
||
}
|
||
|
||
void LayerTreeModel::setCascadeCheckEnabled(bool enabled)
|
||
{
|
||
m_cascadeCheck = enabled;
|
||
}
|
||
|
||
bool LayerTreeModel::cascadeCheckEnabled() const
|
||
{
|
||
return m_cascadeCheck;
|
||
}
|
||
|
||
// 新增实现:移除子节点并在 model 上发出 begin/endRemoveRows
|
||
LayerTreeNode* LayerTreeModel::removeNode(LayerTreeNode* parent, int row)
|
||
{
|
||
if (!parent) parent = m_tree;
|
||
if (row < 0 || row >= parent->childCount()) return nullptr;
|
||
|
||
LayerTreeNode* removed = parent->childAt(row);
|
||
beginRemoveRows(indexFromNode(parent), row, row);
|
||
parent->removeChild(row, 1, false);
|
||
endRemoveRows();
|
||
|
||
return removed;
|
||
}
|
||
|
||
LayerTreeNode* LayerTreeModel::nodeFromIndex(const QModelIndex& index) const
|
||
{
|
||
if (!index.isValid()) return m_tree;
|
||
return static_cast<LayerTreeNode*>(index.internalPointer());
|
||
}
|
||
|
||
QModelIndex LayerTreeModel::indexFromNode(LayerTreeNode* n) const
|
||
{
|
||
if (!n || n == m_tree) return {};
|
||
return createIndex(n->rowInParent(), 0, n);
|
||
}
|