DiagramDesigner/source/topologyView.cpp

660 lines
23 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, bool bFull)
{
if(refresh){
QStandardItem *root = _treeModel->invisibleRootItem();
int rowCount = root->rowCount();
if (rowCount > 0) {
_treeModel->removeRows(0, rowCount);
}
// 清空所有缓存
m_mapGrids.clear();
m_mapZones.clear();
m_mapStations.clear();
m_mapVoltageLevels.clear();
m_mapBayItems.clear();
}
if(bFull){
// 完整层级结构grid -> zone -> station -> voltage -> bay -> device
onUpdateTopologyFull(lst, refresh);
} else {
// 简化层级结构voltage -> bay -> device现有逻辑
onUpdateTopologySimple(lst, refresh);
}
// 展开所有节点
_treeView->expandAll();
}
void TopologyView::onMonitorUpdate(QList<QUuid> lst)
{
clearItems();
auto& mapExtra = m_dataSource->allProperties;
QVector<ExtraProperty> vec = QVector<ExtraProperty>::fromList(mapExtra.values());
QVector<ExtraProperty> filteredVec;
for (const auto& property : vec) {
if (lst.contains(property.component_uuid)) {
filteredVec.append(property);
}
}
buildTreeStructure(_treeModel,filteredVec);
_treeView->expandAll();
}
void TopologyView::onUpdateTopologyFull(QList<RelationItem> lst, bool refresh)
{
// 第一阶段处理间隔节点nCategory == 1
for(auto &info:lst){
auto curItem = info.item;
if(curItem.nCategory == 1){ // 间隔信息
// 获取各级参数
QString grid = curItem.grid;
QString zone = curItem.zone;
QString station = curItem.station;
QString voltageLevel = curItem.sVoltageLevel;
// 设置默认值
if(grid.isEmpty()) grid = "未指定电网";
if(zone.isEmpty()) zone = "未指定区域";
if(station.isEmpty()) station = "未指定变电站";
if(voltageLevel.isEmpty()) voltageLevel = "未知电压等级";
// 查找或创建电网节点
QStandardItem* pGridItem = findOrCreateTopLevelItem(grid, 0, m_mapGrids);
// 查找或创建区域节点
QString zoneKey = QString("%1|%2").arg(grid).arg(zone);
QStandardItem* pZoneItem = findOrCreateChildItem(pGridItem, zone, zoneKey, 1, m_mapZones);
// 查找或创建变电站节点
QString stationKey = QString("%1|%2|%3").arg(grid).arg(zone).arg(station);
QStandardItem* pStationItem = findOrCreateChildItem(pZoneItem, station, stationKey, 2, m_mapStations);
// 查找或创建电压层级节点
QString voltageKey = QString("%1|%2|%3|%4").arg(grid).arg(zone).arg(station).arg(voltageLevel);
QStandardItem* pVoltageItem = findOrCreateChildItem(pStationItem, voltageLevel, voltageKey, 3, m_mapVoltageLevels);
// 创建间隔节点
QString bayKey = QString("%1|%2|%3|%4|%5").arg(grid).arg(zone).arg(station).arg(voltageLevel).arg(curItem.sName);
QStandardItem* pBayItem = createBayItem(bayKey, curItem);
pVoltageItem->appendRow(pBayItem);
}
}
// 第二阶段处理设备节点nCategory == 0
for(auto &info:lst){
auto curItem = info.item;
if(curItem.nCategory == 0){ // 设备信息
// 获取父间隔的参数
QString grid = info.parent.grid;
QString zone = info.parent.zone;
QString station = info.parent.station;
QString voltageLevel = info.parent.sVoltageLevel;
QString bayName = info.parent.sName;
if(!grid.isEmpty() && !zone.isEmpty() && !station.isEmpty() &&
!voltageLevel.isEmpty() && !bayName.isEmpty()){
// 构建间隔节点的缓存key
QString bayKey = QString("%1|%2|%3|%4|%5").arg(grid).arg(zone).arg(station).arg(voltageLevel).arg(bayName);
// 查找对应的间隔节点
QStandardItem* pBayItem = nullptr;
if(m_mapBayItems.contains(bayKey)){
pBayItem = m_mapBayItems[bayKey];
} else {
// 如果没有在缓存中,需要从树中查找
pBayItem = findBayItemInFullTree(grid, zone, station, voltageLevel, bayName);
}
if(pBayItem){
// 创建设备节点
createDeviceItem(pBayItem, curItem);
}
}
}
}
}
void TopologyView::onUpdateTopologySimple(QList<RelationItem> lst, bool refresh)
{
// 现有逻辑,只显示 voltage -> bay -> device
// 第一阶段处理间隔节点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);
}
}
}
}
}
QStandardItem* TopologyView::findOrCreateTopLevelItem(const QString& name, int level, QHash<QString, QStandardItem*>& cache)
{
if(cache.contains(name)){
return cache[name];
}
QStandardItem* pItem = new QStandardItem(name);
pItem->setData(level, Qt::UserRole+1); // 存储层级
pItem->setData(-1, Qt::UserRole+2); // 特殊标识
pItem->setData(name, Qt::UserRole+3); // 存储名称
cache[name] = pItem;
_treeModel->appendRow(pItem);
return pItem;
}
QStandardItem* TopologyView::findOrCreateChildItem(QStandardItem* pParent, const QString& name,
const QString& cacheKey, int level,
QHash<QString, QStandardItem*>& cache)
{
if(cache.contains(cacheKey)){
return cache[cacheKey];
}
// 在父节点下查找
for(int i = 0; i < pParent->rowCount(); ++i){
QStandardItem* pChild = pParent->child(i);
if(pChild->text() == name){
cache[cacheKey] = pChild;
return pChild;
}
}
// 创建新节点
QStandardItem* pItem = new QStandardItem(name);
pItem->setData(level, Qt::UserRole+1);
pItem->setData(-1, Qt::UserRole+2);
pItem->setData(cacheKey, Qt::UserRole+3);
cache[cacheKey] = pItem;
pParent->appendRow(pItem);
return pItem;
}
QStandardItem* TopologyView::findBayItemInFullTree(const QString& grid, const QString& zone,
const QString& station, const QString& voltageLevel,
const QString& bayName)
{
// 构建完整的缓存key
QString bayKey = QString("%1|%2|%3|%4|%5").arg(grid).arg(zone).arg(station).arg(voltageLevel).arg(bayName);
// 如果缓存中有,直接返回
if(m_mapBayItems.contains(bayKey)){
return m_mapBayItems[bayKey];
}
// 遍历树查找
for(int i = 0; i < _treeModel->rowCount(); ++i){
QStandardItem* pGridItem = _treeModel->item(i);
if(pGridItem->text() != grid) continue;
for(int j = 0; j < pGridItem->rowCount(); ++j){
QStandardItem* pZoneItem = pGridItem->child(j);
if(pZoneItem->text() != zone) continue;
for(int k = 0; k < pZoneItem->rowCount(); ++k){
QStandardItem* pStationItem = pZoneItem->child(k);
if(pStationItem->text() != station) continue;
for(int l = 0; l < pStationItem->rowCount(); ++l){
QStandardItem* pVoltageItem = pStationItem->child(l);
if(pVoltageItem->text() != voltageLevel) continue;
for(int m = 0; m < pVoltageItem->rowCount(); ++m){
QStandardItem* pBayItem = pVoltageItem->child(m);
if(pBayItem->text() == bayName &&
pBayItem->data(Qt::UserRole+1).toInt() == 4){ // 间隔层级
m_mapBayItems[bayKey] = pBayItem; // 加入缓存
return pBayItem;
}
}
}
}
}
}
return nullptr;
}
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->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& cacheKey, const RelationSturctItem& bayInfo)
{
QStandardItem* pBayItem = new QStandardItem(bayInfo.sName);
pBayItem->setData(bayInfo.nCategory, Qt::UserRole+1);
pBayItem->setData(bayInfo.nEquipType, Qt::UserRole+2);
pBayItem->setData(bayInfo.uid, Qt::UserRole+3);
pBayItem->setData(cacheKey, Qt::UserRole+4); // 存储完整路径
m_mapBayItems[cacheKey] = 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->setData(deviceInfo.nCategory, Qt::UserRole+1);
pItem->setData(deviceInfo.nEquipType, Qt::UserRole+2);
pItem->setData(deviceInfo.uid, Qt::UserRole+3);
pParent->appendRow(pItem);
}