DiagramDesigner/source/topologyView.cpp

469 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "topologyView.h"
#include "ui_topologyView.h"
#include "tools.h"
#include "topologyTree.h"
#include "dataBase.h"
#include "basePropertyManager.h"
#include "baseProperty.h"
#include "structDataSource.h"
#include "extraPropertyManager.h"
#include <QStandardItemModel>
#include <QMenu>
#include <QUuid>
TopologyView::TopologyView(QWidget *parent)
: QDialog(parent)
, ui(new Ui::topologyView)
,_treeModel(nullptr)
,_treeView(nullptr)
,_pExtraProManager(nullptr)
{
ui->setupUi(this);
//setWindowFlags(windowFlags() | Qt::WindowMinMaxButtonsHint&Qt::WindowCloseButtonHint);
_treeModel = new QStandardItemModel(this);
_treeView = new TopologyTree(this);
ui->verticalLayout->addWidget(_treeView);
_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
}
TopologyView::~TopologyView()
{
delete ui;
}
void TopologyView::initial()
{
connect(_treeView, &QTreeView::clicked, this, &TopologyView::onItemClicked);
connect(_treeModel, &QStandardItemModel::itemChanged, this, &TopologyView::onItemChanged);
m_dataSource = new StructDataSource(this);
_pExtraProManager = new ExtraPropertyManager(this);
_pExtraProManager->initial();
if(_pExtraProManager)
m_dataSource->loadExtrapro(_pExtraProManager->geAlltProperty());
_treeView->setHeaderHidden(true);
// 设置模型的列数
_treeModel->setColumnCount(1);
// 创建树视图
_treeView->setModel(_treeModel);
// 展开所有节点
_treeView->expandAll();
// 显示树视图
_treeView->setWindowTitle(QObject::tr("拓扑树"));
loadTopologyFromDB();
}
void TopologyView::loadTopologyFromDB()
{
if(_pExtraProManager)
{
//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();
}
}
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)
{
QStandardItem* item = _treeModel->itemFromIndex(index);
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);
}
}
}
void TopologyView::onUpdateTopology(QList<RelationItem> lst,bool refresh)
{
if(refresh){
QStandardItem *root = _treeModel->invisibleRootItem();
int rowCount = root->rowCount();
if (rowCount > 0) {
_treeModel->removeRows(0, rowCount);
}
// 清空缓存
m_mapVoltageLevels.clear();
m_mapBayItems.clear();
}
// 第一阶段处理间隔节点nCategory == 1
for(auto &info:lst){
auto curItem = info.item;
if(curItem.nCategory == 1){ // 间隔信息
// 获取间隔的电压层级
QString voltageLevel = curItem.sVoltageLevel;
if(voltageLevel.isEmpty()){
voltageLevel = "未知电压等级"; // 默认值
}
// 查找或创建电压层级节点
QStandardItem* pVoltageItem = findOrCreateVoltageLevel(voltageLevel);
// 创建间隔节点
QStandardItem* pBayItem = createBayItem(voltageLevel, curItem);
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);
}
}
}
}
// 展开所有节点
_treeView->expandAll();
}
void TopologyView::clearItems()
{
if(_treeModel){
QStandardItem *root = _treeModel->invisibleRootItem(); //先清空model
int rowCount = root->rowCount();
if (rowCount > 0) {
_treeModel->removeRows(0, rowCount);
}
}
}
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;
}
}
}
}
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;
}
}
// 将属性添加到合适的节点
// 如果有设备,添加到设备节点;否则添加到间隔节点
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);
}
}
}
// 简化的获取属性列表函数
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];
}
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;
}
// 在电压层级下查找间隔节点
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);
}