299 lines
8.1 KiB
C++
299 lines
8.1 KiB
C++
|
|
#include <QJsonArray>
|
|||
|
|
#include <QJsonDocument>
|
|||
|
|
#include "topologyManager.h"
|
|||
|
|
#include "powerEntity.h"
|
|||
|
|
|
|||
|
|
TopologyManager& TopologyManager::instance()
|
|||
|
|
{
|
|||
|
|
static TopologyManager instance;
|
|||
|
|
return instance;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
TopologyManager::TopologyManager(QObject* parent)
|
|||
|
|
: QObject(parent) {}
|
|||
|
|
|
|||
|
|
TopologyManager::~TopologyManager() {
|
|||
|
|
clearAllData();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void TopologyManager::clearAllData()
|
|||
|
|
{
|
|||
|
|
// 删除所有连接
|
|||
|
|
qDeleteAll(m_connections);
|
|||
|
|
m_connections.clear();
|
|||
|
|
m_connectionIndex.clear();
|
|||
|
|
|
|||
|
|
// 删除所有实体(自动删除子对象)
|
|||
|
|
qDeleteAll(m_entities);
|
|||
|
|
m_entities.clear();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PowerEntity* TopologyManager::createEntity(EntityType type,const QString& uuid, const QString& name)
|
|||
|
|
{
|
|||
|
|
PowerEntity* entity = nullptr;
|
|||
|
|
switch(type) {
|
|||
|
|
case EntityType::ConfigurationDiagram:
|
|||
|
|
entity = new ConfigurationDiagram(uuid,name);
|
|||
|
|
break;
|
|||
|
|
case EntityType::Grid:
|
|||
|
|
case EntityType::Zone:
|
|||
|
|
case EntityType::Station:
|
|||
|
|
entity = new PowerDivision(type, uuid,name);
|
|||
|
|
default:
|
|||
|
|
entity = new PowerComponent(type, uuid,name);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
m_entities.insert(entity->id(), entity);
|
|||
|
|
emit entityCreated(entity->id()); // 发送信号通知
|
|||
|
|
return entity;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PowerEntity* TopologyManager::findEntity(const QString& id) const
|
|||
|
|
{
|
|||
|
|
return m_entities.value(id, nullptr); // 避免异常的安全查询
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool TopologyManager::deleteEntity(const QString& id)
|
|||
|
|
{
|
|||
|
|
if (!m_entities.contains(id)) return false;
|
|||
|
|
|
|||
|
|
PowerEntity* entity = m_entities[id];
|
|||
|
|
|
|||
|
|
// 步骤1:删除所有相关连接
|
|||
|
|
auto relatedConns = m_connectionIndex.values(id);
|
|||
|
|
for (auto conn : relatedConns) {
|
|||
|
|
removeConnection(conn->id());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 步骤2:从父节点移除(防止悬空指针)
|
|||
|
|
if (PowerEntity* parent = entity->parent()) {
|
|||
|
|
parent->removeChild(entity);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 步骤3:递归删除子实体
|
|||
|
|
auto children = entity->children();
|
|||
|
|
for (auto child : children) {
|
|||
|
|
deleteEntity(child->id()); // 递归删除
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 步骤4:从哈希表移除并释放内存
|
|||
|
|
m_entities.remove(id);
|
|||
|
|
delete entity; // 触发PowerEntity析构函数
|
|||
|
|
|
|||
|
|
emit entityDeleted(id);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
PowerConnection* TopologyManager::createConnection(const QString& connId,const QString& fromId, const QString& toId)
|
|||
|
|
{
|
|||
|
|
// 验证有效性
|
|||
|
|
if (!m_entities.contains(fromId) ||
|
|||
|
|
!m_entities.contains(toId) ||
|
|||
|
|
fromId == toId)
|
|||
|
|
{
|
|||
|
|
qWarning() << "Invalid connection endpoints";
|
|||
|
|
return nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 防止重复连接
|
|||
|
|
foreach (auto conn, m_connections) {
|
|||
|
|
if (conn->fromTerminalId() == fromId &&
|
|||
|
|
conn->toTerminalId() == toId)
|
|||
|
|
{
|
|||
|
|
return conn; // 返回已存在的连接
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建新连接
|
|||
|
|
PowerConnection* conn = new PowerConnection(connId,fromId, toId);
|
|||
|
|
m_connections[connId] = conn;
|
|||
|
|
|
|||
|
|
// 更新索引
|
|||
|
|
m_connectionIndex.insert(fromId, conn);
|
|||
|
|
m_connectionIndex.insert(toId, conn);
|
|||
|
|
|
|||
|
|
emit connectionCreated(connId);
|
|||
|
|
return conn;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<PowerConnection*> TopologyManager::getConnectionsForElement(const QString& elementId) const
|
|||
|
|
{
|
|||
|
|
return m_connectionIndex.values(elementId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void TopologyManager::removeConnection(const QString& connId)
|
|||
|
|
{
|
|||
|
|
if (!m_connections.contains(connId)) return;
|
|||
|
|
|
|||
|
|
PowerConnection* conn = m_connections[connId];
|
|||
|
|
|
|||
|
|
// 更新索引
|
|||
|
|
m_connectionIndex.remove(conn->fromTerminalId(), conn);
|
|||
|
|
m_connectionIndex.remove(conn->toTerminalId(), conn);
|
|||
|
|
|
|||
|
|
// 清理内存
|
|||
|
|
m_connections.remove(connId);
|
|||
|
|
delete conn;
|
|||
|
|
|
|||
|
|
emit connectionRemoved(connId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 连接查询接口
|
|||
|
|
QList<PowerConnection*> TopologyManager::connectionsFrom(const QString& elementId) const
|
|||
|
|
{
|
|||
|
|
QList<PowerConnection*> res;
|
|||
|
|
QList<PowerConnection*> lst = m_connectionIndex.values(elementId);
|
|||
|
|
for(auto &val:lst)
|
|||
|
|
{
|
|||
|
|
if(val->fromTerminalId() == elementId)
|
|||
|
|
res.append(val);
|
|||
|
|
}
|
|||
|
|
return res;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<PowerConnection*> TopologyManager::connectionsTo(const QString& elementId) const
|
|||
|
|
{
|
|||
|
|
QList<PowerConnection*> res;
|
|||
|
|
QList<PowerConnection*> lst = m_connectionIndex.values(elementId);
|
|||
|
|
for(auto &val:lst)
|
|||
|
|
{
|
|||
|
|
if(val->toTerminalId() == elementId)
|
|||
|
|
res.append(val);
|
|||
|
|
}
|
|||
|
|
return res;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<PowerConnection*> TopologyManager::getConnectionsFor(const QString& entityId) const
|
|||
|
|
{
|
|||
|
|
return m_connectionIndex.values(entityId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void TopologyManager::saveToDB(const QString& path)
|
|||
|
|
{
|
|||
|
|
QJsonObject root;
|
|||
|
|
|
|||
|
|
QJsonArray entitiesArray;
|
|||
|
|
for (auto entity : m_entities)
|
|||
|
|
entitiesArray.append(entity->toJson());
|
|||
|
|
root["entities"] = entitiesArray;
|
|||
|
|
|
|||
|
|
QJsonArray connectionsArray;
|
|||
|
|
for (auto conn : m_connections)
|
|||
|
|
connectionsArray.append(conn->toJson());
|
|||
|
|
root["connections"] = connectionsArray;
|
|||
|
|
|
|||
|
|
//todo:写入到数据库
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void TopologyManager::loadFromDB(const QString& path)
|
|||
|
|
{
|
|||
|
|
//todo::将读到的字为json
|
|||
|
|
QString strJson;
|
|||
|
|
QJsonDocument doc = QJsonDocument::fromJson(strJson.toLocal8Bit());
|
|||
|
|
QJsonObject root = doc.object();
|
|||
|
|
|
|||
|
|
clearAllData(); // 清除现有数据
|
|||
|
|
|
|||
|
|
// 阶段1:创建所有实体
|
|||
|
|
QHash<QString, QStringList> pendingChildren;
|
|||
|
|
|
|||
|
|
QJsonArray entities = root["entities"].toArray();
|
|||
|
|
foreach (QJsonValue entVal, entities) {
|
|||
|
|
QJsonObject entObj = entVal.toObject();
|
|||
|
|
|
|||
|
|
// 创建实体
|
|||
|
|
EntityType type = static_cast<EntityType>(entObj["type"].toInt());
|
|||
|
|
QString id = entObj["id"].toString();
|
|||
|
|
QString name = entObj["name"].toString();
|
|||
|
|
|
|||
|
|
PowerEntity* entity = createEntity(type, id, name);
|
|||
|
|
|
|||
|
|
// 记录待处理的子关系
|
|||
|
|
pendingChildren[id] = entObj["children"].toVariant().toStringList();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 阶段2:建立父子关系
|
|||
|
|
QHashIterator<QString, QStringList> it(pendingChildren);
|
|||
|
|
while (it.hasNext()) {
|
|||
|
|
it.next();
|
|||
|
|
PowerEntity* parent = getEntity(it.key());
|
|||
|
|
if (!parent) continue;
|
|||
|
|
|
|||
|
|
foreach (QString childId, it.value()) {
|
|||
|
|
if (PowerEntity* child = getEntity(childId)) {
|
|||
|
|
parent->addChild(child);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 阶段3:创建连接
|
|||
|
|
QJsonArray connections = root["connections"].toArray();
|
|||
|
|
foreach (QJsonValue connVal, connections) {
|
|||
|
|
QJsonObject connObj = connVal.toObject();
|
|||
|
|
createConnection(
|
|||
|
|
connObj["id"].toString(),
|
|||
|
|
connObj["from"].toString(),
|
|||
|
|
connObj["to"].toString()
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PowerEntity* TopologyManager::getEntity(const QString& id) const
|
|||
|
|
{
|
|||
|
|
auto it = m_entities.find(id);
|
|||
|
|
return (it != m_entities.end()) ? it.value() : nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<PowerEntity*> TopologyManager::findEntitiesByName(const QString& name) const
|
|||
|
|
{
|
|||
|
|
QList<PowerEntity*> results;
|
|||
|
|
foreach (auto entity, m_entities) {
|
|||
|
|
if (entity->name() == name) {
|
|||
|
|
results.append(entity);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return results;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PowerTerminal* TopologyManager::createTerminal(const QString& parentEntityId,
|
|||
|
|
TerminalType type,
|
|||
|
|
const QString& name,
|
|||
|
|
const QPointF& relPos) {
|
|||
|
|
if (!m_entities.contains(parentEntityId)) return nullptr;
|
|||
|
|
|
|||
|
|
PowerTerminal* term = new PowerTerminal(parentEntityId, type, name, relPos);
|
|||
|
|
m_allTerminals[term->id()] = term;
|
|||
|
|
m_terminalsByEntity[parentEntityId].append(term);
|
|||
|
|
|
|||
|
|
// 关联到父实体
|
|||
|
|
if (PowerEntity* parent = getEntity(parentEntityId)) {
|
|||
|
|
parent->addTerminal(term);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return term;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool TopologyManager::deleteTerminal(const QString& terminalId) {
|
|||
|
|
if (!m_allTerminals.contains(terminalId)) return false;
|
|||
|
|
|
|||
|
|
PowerTerminal* term = m_allTerminals[terminalId];
|
|||
|
|
QString parentId = term->parentEntityId();
|
|||
|
|
|
|||
|
|
// 从父实体移除
|
|||
|
|
if (PowerEntity* parent = getEntity(parentId)) {
|
|||
|
|
parent->removeTerminal(terminalId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清理全局存储
|
|||
|
|
m_terminalsByEntity[parentId].removeAll(term);
|
|||
|
|
m_allTerminals.remove(terminalId);
|
|||
|
|
//delete term; //在parent中已经delete
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
QList<PowerTerminal*> TopologyManager::getTerminalsForEntity(const QString& entityId) const {
|
|||
|
|
return m_terminalsByEntity.value(entityId);
|
|||
|
|
}
|