DiagramDesigner/source/topologyView.cpp

469 lines
16 KiB
C++
Raw Normal View History

2025-04-30 16:29:17 +08:00
#include "topologyView.h"
#include "ui_topologyView.h"
#include "tools.h"
2025-05-09 19:36:32 +08:00
#include "topologyTree.h"
2025-05-16 19:20:46 +08:00
#include "dataBase.h"
2025-05-23 10:30:52 +08:00
#include "basePropertyManager.h"
#include "baseProperty.h"
2026-03-02 20:15:22 +08:00
#include "structDataSource.h"
#include "extraPropertyManager.h"
2025-04-30 16:29:17 +08:00
#include <QStandardItemModel>
#include <QMenu>
#include <QUuid>
TopologyView::TopologyView(QWidget *parent)
: QDialog(parent)
, ui(new Ui::topologyView)
2026-03-02 20:15:22 +08:00
,_treeModel(nullptr)
2025-05-09 19:36:32 +08:00
,_treeView(nullptr)
2026-03-02 20:15:22 +08:00
,_pExtraProManager(nullptr)
2025-04-30 16:29:17 +08:00
{
ui->setupUi(this);
//setWindowFlags(windowFlags() | Qt::WindowMinMaxButtonsHint&Qt::WindowCloseButtonHint);
2026-03-02 20:15:22 +08:00
_treeModel = new QStandardItemModel(this);
2025-05-09 19:36:32 +08:00
_treeView = new TopologyTree(this);
ui->verticalLayout->addWidget(_treeView);
_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
2025-04-30 16:29:17 +08:00
}
TopologyView::~TopologyView()
{
delete ui;
}
void TopologyView::initial()
{
2025-05-09 19:36:32 +08:00
connect(_treeView, &QTreeView::clicked, this, &TopologyView::onItemClicked);
2026-03-02 20:15:22 +08:00
connect(_treeModel, &QStandardItemModel::itemChanged, this, &TopologyView::onItemChanged);
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
m_dataSource = new StructDataSource(this);
_pExtraProManager = new ExtraPropertyManager(this);
_pExtraProManager->initial();
2025-04-30 16:29:17 +08:00
2026-03-02 20:15:22 +08:00
if(_pExtraProManager)
m_dataSource->loadExtrapro(_pExtraProManager->geAlltProperty());
2025-04-30 16:29:17 +08:00
2026-03-02 20:15:22 +08:00
_treeView->setHeaderHidden(true);
// 设置模型的列数
_treeModel->setColumnCount(1);
2025-05-16 19:20:46 +08:00
2025-04-30 16:29:17 +08:00
// 创建树视图
2026-03-02 20:15:22 +08:00
_treeView->setModel(_treeModel);
2025-04-30 16:29:17 +08:00
// 展开所有节点
2025-05-09 19:36:32 +08:00
_treeView->expandAll();
2025-04-30 16:29:17 +08:00
// 显示树视图
2025-05-09 19:36:32 +08:00
_treeView->setWindowTitle(QObject::tr("拓扑树"));
2026-03-02 20:15:22 +08:00
loadTopologyFromDB();
2025-04-30 16:29:17 +08:00
}
2026-03-02 20:15:22 +08:00
void TopologyView::loadTopologyFromDB()
2025-04-30 16:29:17 +08:00
{
2026-03-02 20:15:22 +08:00
if(_pExtraProManager)
2025-04-30 16:29:17 +08:00
{
2026-03-02 20:15:22 +08:00
//clearItems();
auto& mapExtra = m_dataSource->allProperties;
/*QStandardItem* root = _treeModel->invisibleRootItem();
for(auto& pro:mapExtra){
QStandardItem* propertyItem = new QStandardItem();
addItemToView(pro,"name",root,propertyItem);
}*/
QVector<ExtraProperty> vec = QVector<ExtraProperty>::fromList(mapExtra.values());
buildTreeStructure(_treeModel,vec);
_treeView->expandAll();
2025-04-30 16:29:17 +08:00
}
}
void TopologyView::onItemChanged(QStandardItem *item)
{
int nLevel = getLevel(item);
QString str = item->text();
EntityInfo info;
info.sName = str;
info.sUuid = item->data(Qt::UserRole+1).toString();
info.eType = EntityType(item->data(Qt::UserRole+2).toInt());
emit entityChange(info);
}
void TopologyView::onItemClicked(const QModelIndex &index)
{
2026-03-02 20:15:22 +08:00
QStandardItem* item = _treeModel->itemFromIndex(index);
2025-04-30 16:29:17 +08:00
if(item)
{
EntityType type = EntityType(item->data(Qt::UserRole+2).toInt());
if(type == EntityType::ConfigurationDiagram)
{
EntityInfo info;
info.eType = EntityType::ConfigurationDiagram;
info.sName = item->text();
info.sUuid = item->data(Qt::UserRole+1).toString();
info.sParentId = item->parent()->data(Qt::UserRole+1).toString();
emit entitySelected(info);
}
}
}
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
void TopologyView::onUpdateTopology(QList<RelationItem> lst,bool refresh)
2025-05-23 10:30:52 +08:00
{
2026-03-02 20:15:22 +08:00
if(refresh){
QStandardItem *root = _treeModel->invisibleRootItem();
int rowCount = root->rowCount();
if (rowCount > 0) {
_treeModel->removeRows(0, rowCount);
}
// 清空缓存
m_mapVoltageLevels.clear();
m_mapBayItems.clear();
}
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
// 第一阶段处理间隔节点nCategory == 1
for(auto &info:lst){
auto curItem = info.item;
if(curItem.nCategory == 1){ // 间隔信息
// 获取间隔的电压层级
QString voltageLevel = curItem.sVoltageLevel;
if(voltageLevel.isEmpty()){
voltageLevel = "未知电压等级"; // 默认值
}
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
// 查找或创建电压层级节点
QStandardItem* pVoltageItem = findOrCreateVoltageLevel(voltageLevel);
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
// 创建间隔节点
QStandardItem* pBayItem = createBayItem(voltageLevel, curItem);
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
pVoltageItem->appendRow(pBayItem);
}
}
// 第二阶段处理设备节点nCategory == 0
for(auto &info:lst){
auto curItem = info.item;
if(curItem.nCategory == 0){ // 设备信息
// 获取设备所属的间隔名称和电压层级
QString bayName = info.parent.sName;
QString voltageLevel = info.parent.sVoltageLevel; // 从父间隔获取电压层级
if(!bayName.isEmpty() && !voltageLevel.isEmpty()){
// 查找对应的间隔节点
QStandardItem* pBayItem = findBayItem(voltageLevel, bayName);
if(pBayItem){
// 创建设备节点
createDeviceItem(pBayItem, curItem);
2025-05-23 10:30:52 +08:00
}
}
}
}
2026-03-02 20:15:22 +08:00
// 展开所有节点
_treeView->expandAll();
2025-05-23 10:30:52 +08:00
}
2026-03-02 20:15:22 +08:00
void TopologyView::clearItems()
2025-05-23 10:30:52 +08:00
{
2026-03-02 20:15:22 +08:00
if(_treeModel){
QStandardItem *root = _treeModel->invisibleRootItem(); //先清空model
int rowCount = root->rowCount();
if (rowCount > 0) {
_treeModel->removeRows(0, rowCount);
2025-10-30 17:20:10 +08:00
}
}
2026-03-02 20:15:22 +08:00
}
2025-05-23 10:30:52 +08:00
2026-03-02 20:15:22 +08:00
QString TopologyView::getLevelType(int index) {
switch (index) {
case 0: return "电网";
case 1: return "区域";
case 2: return "站点";
case 3: return "电压等级";
case 4: return "间隔";
case 5: return "设备";
case 6: return "分组";
default: return "未知层级";
}
}
void TopologyView::buildTreeStructure(QStandardItemModel* model,
const QVector<ExtraProperty>& properties) {
// 清空模型
model->clear();
// 创建根节点
//QStandardItem* root = new QStandardItem("拓扑结构");
//model->appendRow(root);
QStandardItem* root = _treeModel->invisibleRootItem();
// 存储节点映射:路径 -> 节点
QMap<QString, QStandardItem*> nodeMap;
for (const auto& property : properties) {
// 判断是否有设备信息
bool hasDevice = !property.component_uuid.isNull() && !property.component_name.isEmpty();
// 检查间隔信息(根据业务逻辑,间隔应该总是存在)
QString bayDisplayName = property.bay_name.isEmpty() ?
(property.bay_tag.isEmpty() ? "未命名间隔" : property.bay_tag) :
property.bay_name;
// 构建完整的节点路径
QStringList pathComponents;
// 基本层级:电网、区域、站点、电压等级、间隔
pathComponents << property.grid_name;
pathComponents << property.zone_name;
pathComponents << property.station_name;
pathComponents << property.currentLevel;
pathComponents << bayDisplayName;
// 如果有设备信息,添加设备层级
if (hasDevice) {
QString deviceDisplayName = property.component_name.isEmpty() ?
property.component_uuid.toString() :
property.component_name;
pathComponents << deviceDisplayName;
}
// 构建路径字符串作为唯一标识
QString pathKey = pathComponents.join("|");
// 查找或创建节点路径
QStandardItem* currentNode = root;
QString currentPath = "";
for (int i = 0; i < pathComponents.size(); i++) {
currentPath += (i > 0 ? "|" : "") + pathComponents[i];
// 查找是否已存在该节点
QStandardItem* existingNode = nodeMap.value(currentPath);
if (!existingNode) {
// 在当前父节点下查找
for (int row = 0; row < currentNode->rowCount(); row++) {
QStandardItem* child = currentNode->child(row, 0);
if (child && child->text() == pathComponents[i]) {
QVariantMap childData = child->data(Qt::UserRole + 1).toMap();
QString childPath = childData.value("fullPath").toString();
if (childPath == currentPath) {
existingNode = child;
nodeMap[currentPath] = child;
break;
}
}
}
2025-05-23 10:30:52 +08:00
}
2026-03-02 20:15:22 +08:00
if (existingNode) {
currentNode = existingNode;
} else {
// 创建新节点
QStandardItem* newNode = new QStandardItem(pathComponents[i]);
// 确定节点类型和层级信息
QVariantMap nodeData;
nodeData["fullPath"] = currentPath;
nodeData["level"] = i;
// 根据层级设置节点类型
QString nodeType;
QString levelType;
switch (i) {
case 0: nodeType = "grid"; levelType = "电网"; break;
case 1: nodeType = "zone"; levelType = "区域"; break;
case 2: nodeType = "station"; levelType = "站点"; break;
case 3: nodeType = "voltage"; levelType = "电压等级"; break;
case 4: nodeType = "bay"; levelType = "间隔"; break;
case 5:
if (hasDevice) {
nodeType = "device";
levelType = "设备";
// 创建设备节点时初始化属性列表
nodeData["properties"] = QVariant::fromValue(QVector<ExtraProperty>());
nodeData["propertyCount"] = 0;
nodeData["deviceId"] = property.component_uuid.toString();
nodeData["deviceName"] = property.component_name;
//nodeData["deviceType"] = property.device_type;
}
break;
}
// 如果是间隔节点第4层也初始化属性列表用于无设备的情况
if (i == 4) {
nodeData["properties"] = QVariant::fromValue(QVector<ExtraProperty>());
nodeData["propertyCount"] = 0;
nodeData["bayName"] = property.bay_name;
nodeData["bayTag"] = property.bay_tag;
}
nodeData["nodeType"] = nodeType;
nodeData["levelType"] = levelType;
newNode->setData(nodeData, Qt::UserRole + 1);
currentNode->appendRow(newNode);
currentNode = newNode;
nodeMap[currentPath] = newNode;
2025-05-23 10:30:52 +08:00
}
}
2026-03-02 20:15:22 +08:00
// 将属性添加到合适的节点
// 如果有设备,添加到设备节点;否则添加到间隔节点
QVariantMap targetNodeData = currentNode->data(Qt::UserRole + 1).toMap();
QVector<ExtraProperty> nodeProperties = targetNodeData["properties"].value<QVector<ExtraProperty>>();
// 检查属性是否已存在
bool propertyExists = false;
for (const auto& existingProp : nodeProperties) {
if (existingProp.code == property.code) {
propertyExists = true;
break;
}
}
if (!propertyExists) {
nodeProperties.append(property);
targetNodeData["properties"] = QVariant::fromValue(nodeProperties);
// 更新属性数量
int propertyCount = targetNodeData["propertyCount"].toInt() + 1;
targetNodeData["propertyCount"] = propertyCount;
// 更新节点显示文本
QString currentText = currentNode->text();
// 移除可能存在的数量后缀
currentText = currentText.replace(QRegularExpression("\\(\\d+\\)$"), "").trimmed();
currentNode->setText(QString("%1 (%2)").arg(currentText).arg(propertyCount));
// 更新工具提示
QString tooltip = QString("%1: %2").arg(targetNodeData["levelType"].toString()).arg(currentText);
if (propertyCount > 0) {
tooltip += QString("\n属性数量: %1").arg(propertyCount);
}
// 添加设备类型信息(如果是设备节点)
if (targetNodeData["nodeType"].toString() == "device") {
tooltip += QString("\n设备类型: %1").arg(targetNodeData["deviceType"].toString());
}
currentNode->setToolTip(tooltip);
// 保存更新后的数据
currentNode->setData(targetNodeData, Qt::UserRole + 1);
2025-05-23 10:30:52 +08:00
}
}
2026-03-02 20:15:22 +08:00
}
// 简化的获取属性列表函数
QVector<ExtraProperty> TopologyView::getPropertiesForNode(QStandardItem* node) {
QVariantMap nodeData = node->data(Qt::UserRole + 1).toMap();
QString nodeType = nodeData.value("nodeType").toString();
if (nodeType == "device" || nodeType == "bay") {
return nodeData["properties"].value<QVector<ExtraProperty>>();
}
return QVector<ExtraProperty>();
}
QString TopologyView::getNodeInfo(QStandardItem* node) {
QVariantMap nodeData = node->data(Qt::UserRole + 1).toMap();
QString nodeType = nodeData.value("nodeType").toString();
QString levelType = nodeData.value("levelType").toString();
QString name = node->text().replace(QRegularExpression("\\(\\d+\\)$"), "").trimmed();
int propertyCount = nodeData.value("propertyCount", 0).toInt();
if (nodeType == "device") {
return QString("%1: %2 (设备类型: %3, 属性数: %4)")
.arg(levelType)
.arg(name)
.arg(nodeData.value("deviceType").toString())
.arg(propertyCount);
} else if (nodeType == "bay") {
return QString("%1: %2 (属性数: %3)")
.arg(levelType)
.arg(name)
.arg(propertyCount);
}
return QString("%1: %2").arg(levelType).arg(name);
}
// 查找或创建电压层级节点
QStandardItem* TopologyView::findOrCreateVoltageLevel(const QString& voltageLevel)
{
if(m_mapVoltageLevels.contains(voltageLevel)){
return m_mapVoltageLevels[voltageLevel];
2025-05-23 10:30:52 +08:00
}
2026-03-02 20:15:22 +08:00
QStandardItem* pVoltageItem = new QStandardItem(voltageLevel);
//pVoltageItem->setCheckable(true);
//pVoltageItem->setCheckState(Qt::Unchecked);
pVoltageItem->setData(-1, Qt::UserRole+1); // 特殊标识,表示电压层级
pVoltageItem->setData(-1, Qt::UserRole+2);
pVoltageItem->setData(QString(), Qt::UserRole+3);
m_mapVoltageLevels[voltageLevel] = pVoltageItem;
_treeModel->appendRow(pVoltageItem);
return pVoltageItem;
}
// 创建间隔节点
QStandardItem* TopologyView::createBayItem(const QString& voltageLevel, const RelationSturctItem& bayInfo)
{
QStandardItem* pBayItem = new QStandardItem(bayInfo.sName);
//pBayItem->setCheckable(true);
//pBayItem->setCheckState(Qt::Unchecked);
pBayItem->setData(bayInfo.nCategory, Qt::UserRole+1);
pBayItem->setData(bayInfo.nEquipType, Qt::UserRole+2);
pBayItem->setData(bayInfo.uid, Qt::UserRole+3);
// 存储到缓存中key 使用"电压层级|间隔名称"确保唯一
QString bayKey = QString("%1|%2").arg(voltageLevel).arg(bayInfo.sName);
m_mapBayItems[bayKey] = pBayItem;
return pBayItem;
2025-05-23 10:30:52 +08:00
}
2026-03-02 20:15:22 +08:00
// 在电压层级下查找间隔节点
QStandardItem* TopologyView::findBayItem(const QString& voltageLevel, const QString& bayName)
{
QString bayKey = QString("%1|%2").arg(voltageLevel).arg(bayName);
// 先从缓存查找
if(m_mapBayItems.contains(bayKey)){
return m_mapBayItems[bayKey];
}
// 在对应电压层级下查找
if(m_mapVoltageLevels.contains(voltageLevel)){
QStandardItem* pVoltageItem = m_mapVoltageLevels[voltageLevel];
for(int i = 0; i < pVoltageItem->rowCount(); ++i){
QStandardItem* pItem = pVoltageItem->child(i);
if(pItem->text() == bayName &&
pItem->data(Qt::UserRole+1).toInt() == 1){
m_mapBayItems[bayKey] = pItem; // 加入缓存
return pItem;
}
}
}
return nullptr;
}
// 创建设备节点
void TopologyView::createDeviceItem(QStandardItem* pParent, const RelationSturctItem& deviceInfo)
{
QStandardItem* pItem = new QStandardItem(deviceInfo.sName);
//pItem->setCheckable(true);
//pItem->setCheckState(Qt::Unchecked);
pItem->setData(deviceInfo.nCategory, Qt::UserRole+1);
pItem->setData(deviceInfo.nEquipType, Qt::UserRole+2);
pItem->setData(deviceInfo.uid, Qt::UserRole+3);
pParent->appendRow(pItem);
}