diff --git a/CMakeLists.txt b/CMakeLists.txt index 2889cc4..f81def0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(H_HEADER_FILES include/projectModelDlg.h include/projectTableDelegate.h include/selectorDialog.h + include/topologyView.h common/include/global.h common/include/tools.h @@ -71,15 +72,18 @@ set(CPP_SOURCE_FILES source/projectModelDlg.cpp source/projectTableDelegate.cpp source/selectorDialog.cpp + source/topologyView.cpp common/source/httpInterface.cpp common/source/global.cpp + common/source/tools.cpp ) set(UI_FILES ui/mainwindow.ui ui/graphicElementsPanel.ui ui/loadPageDlg.ui ui/projectModelDlg.ui + ui/topologyView.ui ) # 包含源文件目录 diff --git a/common/include/global.h b/common/include/global.h index 580f6d6..aa89f4d 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -7,6 +7,7 @@ #include #include #include +#include const double g_dGriaphicsScene_Width = 800; const double g_dGriaphicsScene_Height = 600; @@ -78,13 +79,19 @@ enum TableItemState //工程模table操作的对象状态 TS_edit = 4 }; +enum class AlertInfo //警告提示信息 +{ + success = 1, + fail = 2, + exist = 4 +}; struct attributeGroup //属性组(元模) { int id = 0; QString groupType; QString groupName; - int isPublic = -1; + int ispublic = -1; QString remark; }; @@ -131,6 +138,13 @@ struct modelAttribute //模型属性表(所有模型属性的索引) qint64 attributeId = 0; }; +struct modelAttributePublic //公共属性表 +{ + int id = 0; + qint64 attributeGroupId = 0; + qint64 attributeId = 0; +}; + struct modelConnectivity //模型连接性表(元模是否可以连接) { int id = 0; @@ -176,6 +190,7 @@ struct groupStateInfo //属性组(结构信息) { QString groupName; //组名 QString tableName; //表名 + bool isPublic = false;; PropertyValueInfo info; //属性信息 }; @@ -192,6 +207,11 @@ struct modelStateInfo //模型结构信息 int modelType; QWidget* _PropertyDlg = NULL; //属性设置界面,每个模型维护一种界面 QMap groupInfo; //属性组信息 + void release() + { + if(_PropertyDlg) + delete _PropertyDlg; + } }; struct modelDataInfo //模型数据信息 @@ -208,6 +228,35 @@ struct propertyContentInfo //单个属性结构 QWidget* proEditer = NULL; //编辑窗口对象 }; +//==================组态拓扑结构====================== +/*struct diagramInfo +{ + QString name; + QString uuid; + QMap childMap; +}; + +struct stationInfo +{ + QString stationName; + QString uuid; + QMap diagramMap; +}; + +struct zoneInfo +{ + QString zoneName; + QString uuid; + QMap stationMap; +}; + +struct gridInfo //grid +{ + QString gridName; + QString uuid; + QMap zoneMap; +};*/ + //==================组态图使用===================== // 基础实体类型(电力元素或组态图) enum class EntityType { @@ -219,6 +268,14 @@ enum class EntityType { BusBar, CircuitBreaker }; +struct EntityInfo +{ + QString sName; + QString sUuid; + QString sParentId; + EntityType eType; +}; + struct DiagramView { QString diagramId; // 对应的PowerEntity ID diff --git a/common/include/tools.h b/common/include/tools.h index f95cd8c..87d5f06 100644 --- a/common/include/tools.h +++ b/common/include/tools.h @@ -2,6 +2,7 @@ #define TOOLS_H #include +#include template //双向map工具类,实现key->value,value->key的映射 class BiDirectionalMap { @@ -64,4 +65,6 @@ private: QHash m_keyToValue; // 键 → 值 QHash m_valueToKey; // 值 → 键 }; + +int getLevel(QStandardItem *item); #endif // DATABASE_H diff --git a/common/source/tools.cpp b/common/source/tools.cpp new file mode 100644 index 0000000..701b25d --- /dev/null +++ b/common/source/tools.cpp @@ -0,0 +1,17 @@ +#include "tools.h" + +int getLevel(QStandardItem *item) { + int level = 0; + QStandardItem *parent = item->parent(); + if(parent) + { + while (parent) { + level++; + parent = parent->parent(); + } + return level; + } + else{ + return -1; + } +} diff --git a/diagramCavas/include/diagramCavas.h b/diagramCavas/include/diagramCavas.h index 2bacdc7..19610ab 100644 --- a/diagramCavas/include/diagramCavas.h +++ b/diagramCavas/include/diagramCavas.h @@ -10,6 +10,7 @@ namespace Ui { class diagramCavas; } QT_END_NAMESPACE class DrawingPanel; +class PowerEntity; class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea { @@ -22,19 +23,26 @@ public: public: void initial(); public slots: - void onSignal_addDrawingPanel(const QString& sTitile,DiagramMode = DM_edit); + void onSignal_addDrawingPanel(PowerEntity* p,DiagramMode = DM_edit); void onSignal_addGraphicsItem(modelStateInfo&); void onSignal_addPage(); void onSignal_savePage(); - void onSignal_loadPage(const QString&); + void onSignal_loadPage(PowerEntity* p); void runPage(const QString); //运行时 void onSignal_runPage(); void onSignal_deletePage(); void onSignal_activatePage(const QString& name); void onSignal_panelDelete(const QString& name); + + void onSignal_createEntity(EntityInfo); + void onSignal_changeEntity(EntityInfo); + void onSignal_deleteEntity(EntityInfo); + void onSignal_selectEntity(EntityInfo); private: - QMap m_mapDrawPanel; + void removePanel(PowerEntity*); +private: + QMap> m_mapDrawPanel; int _pageIndex; QString _curPage; }; diff --git a/diagramCavas/include/drawingPanel.h b/diagramCavas/include/drawingPanel.h index e86b3be..b88950b 100644 --- a/diagramCavas/include/drawingPanel.h +++ b/diagramCavas/include/drawingPanel.h @@ -14,13 +14,14 @@ class DesignerScene; class SelectorManager; class GraphicsItemGroup; class StatusBar; +class PowerEntity; class DrawingPanel : public QWidget { Q_OBJECT public: - DrawingPanel(QWidget *parent = nullptr,DiagramMode mode = DM_edit); + DrawingPanel(PowerEntity* pEntity,QWidget *parent = nullptr,DiagramMode mode = DM_edit); ~DrawingPanel(); QGraphicsScene* getQGraphicsScene(); @@ -59,6 +60,7 @@ private: FixedPortsModel* _pModel; DiagramMode _mode; QString _name; + PowerEntity* _pEntity; //组态图拓扑对象 }; #endif diff --git a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h index 11a0147..2360dfe 100644 --- a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h +++ b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h @@ -2,6 +2,7 @@ #include "graphicsDataModel/baseModel.h" #include "serializable.h" +#include "powerEntity.h" #include #include @@ -14,12 +15,15 @@ class DesignerScene; class HttpInterface; struct Connection; +class PowerEntity; +class ElectricConnectLineItem; + class FixedPortsModel : public BaseModel, public Serializable { Q_OBJECT public: - FixedPortsModel(); + FixedPortsModel(PowerEntity*); ~FixedPortsModel(); public: QMap allNodePos() const; @@ -37,10 +41,13 @@ public: void setScene(DesignerScene* p){_scene = p;} void setTopWidget(DrawingPanel* p) {_widget = p;} QWidget* getTopWidget(); + QPointF getTerminalPos(const QString& sTerminalId); //获取拓扑接线点在当前diagram中的位置 + ElectricConnectLineItem* getLineItemById(const QString& terminalId); void showModelDlg(const QString&,QUuid,GraphicsBaseItem*); //点击时显示指定模型的dlg、指定item的数据(模型名,对象Uuid,触发事件的item) void initialPropertyDlg(); //初始化属性设置dlg,每个模型拥各自的dlg void generatePropertyDlg(const QString&); + ConfigurationDiagram* getTopologyDiagram(); //返回当前组态图的拓扑实体 Q_SIGNALS: void activatePage(const QString&); //激活当前model所在page public: @@ -62,6 +69,7 @@ private: DrawingPanel* _widget; //顶层widget HttpInterface* _Interface; QTimer* _timer; + PowerEntity* _pEntity; //拓扑实体 QMap _modelStateInfo; //模型结构信息 QMap _modelDataInfo; //模型数据信息 diff --git a/diagramCavas/include/graphicsItem/electricConnectLineItem.h b/diagramCavas/include/graphicsItem/electricConnectLineItem.h index 10393e9..ef5c065 100644 --- a/diagramCavas/include/graphicsItem/electricConnectLineItem.h +++ b/diagramCavas/include/graphicsItem/electricConnectLineItem.h @@ -88,10 +88,10 @@ public: bool addConnection(); void resetCurLine(){_curLine = QPoint();} - void updateConnection(QUuid callerId,QPointF pos); //外部调用的更新函数,id为调用者id + //void updateConnection(QUuid callerId,QPointF pos); //外部调用的更新函数,id为调用者id void setConnection(Connection con){m_connectState = con;} Connection getConnection() const {return m_connectState;} - QUuid getOppositeId(QUuid); //获取另一端点id + //QUuid getOppositeId(QUuid); //获取另一端点id protected: virtual QPainterPath shape() const override; virtual QRectF boundingRect() const override; diff --git a/diagramCavas/include/graphicsItem/graphicsBaseItem.h b/diagramCavas/include/graphicsItem/graphicsBaseItem.h index f59977c..25aaca0 100644 --- a/diagramCavas/include/graphicsItem/graphicsBaseItem.h +++ b/diagramCavas/include/graphicsItem/graphicsBaseItem.h @@ -437,6 +437,7 @@ protected: class ItemPort; class BaseProperty; +class PowerEntity; typedef AbstractShapeType AbstractShape; @@ -464,7 +465,7 @@ public: virtual QString getLabelCurrent() const; virtual void setLabelVoltage(const QString& str); //设置电压标签 virtual QString getLabelVoltage() const; - virtual int addPort(PortState typ,QPointF vec); //新建,返回-1失败 + virtual int addPort(PortState typ,QPointF vec,QString id = "",HandleType hType = T_lineInOut,PortPos pos = P_top); //新建,返回-1失败 virtual void addPort(PortState typ,int ntagId,QPointF vec); //载入 PortState为P_const时,QPointF中为(0~1,0~1)的相对位置;PortState为p_movable时,QPointF为坐标值 virtual QUuid itemId() const {return m_itemId;} virtual void setItemId(QUuid n){m_itemId = n;} @@ -477,7 +478,7 @@ public: virtual int getLastPort() const {return _lastPort;} virtual ItemPort* getPortPtr(int) const; virtual ItemControlHandle* getHandlePtr(int) const; - virtual QMap& getPorts() {return m_mapPort;} + virtual QMap getPorts() {return m_mapPort;} virtual void setProperty(BaseProperty* p); virtual BaseProperty* getProperty() {return _property;} virtual void unbindProperty(); //断开图元与数据的绑定 @@ -487,6 +488,8 @@ public: virtual bool itemChanged() const {return _itemChanged;} virtual void setModelName(QString sName){_modelName = sName;} virtual QString getModelName() const {return _modelName;} + virtual void setEntity(PowerEntity*); //设置当前图元的拓扑数据 + virtual PowerEntity* entity(); protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&); virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*); @@ -507,6 +510,7 @@ protected: BaseProperty* _property; bool _itemChanged; //图元变化标志,判断是否需要保存 QString _modelName; //当前图元使用的模型名,用来在model中检索属性信息 + PowerEntity* _pEntity; //图元拓扑 }; class BaseProperty:public QObject //属性类,存放电路元件属性 diff --git a/diagramCavas/include/graphicsItem/itemPort.h b/diagramCavas/include/graphicsItem/itemPort.h index eed5b09..b15da57 100644 --- a/diagramCavas/include/graphicsItem/itemPort.h +++ b/diagramCavas/include/graphicsItem/itemPort.h @@ -10,7 +10,7 @@ class ItemPort : public HandleRect Q_OBJECT public: - ItemPort(QGraphicsItem *parent); + ItemPort(QGraphicsItem *parent,QString uuid = ""); virtual ~ItemPort(); public: @@ -20,10 +20,16 @@ public: void disConnect(){_ptr = nullptr;} bool connected() const {return _ptr == nullptr?false:true;} ElectricConnectLineItem* getConnectPtr() const {return _ptr;} + void setId(const QString& id){_uuid = id;} + QString getId() {return _uuid;} + void setName(const QString& str) {_name = str;} + QString getName() const {return _name;} protected: virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override; private: + QString _uuid; + QString _name; PortPos _pos; ElectricConnectLineItem* _ptr; }; diff --git a/diagramCavas/include/powerEntity.h b/diagramCavas/include/powerEntity.h index a6ed2c5..22a0eac 100644 --- a/diagramCavas/include/powerEntity.h +++ b/diagramCavas/include/powerEntity.h @@ -17,7 +17,7 @@ public: : m_type(type), m_id(id), m_name(name) {} virtual ~PowerEntity() { - qDeleteAll(m_children); + //qDeleteAll(m_children); } // 添加/删除子元素 diff --git a/diagramCavas/include/powerTerminal.h b/diagramCavas/include/powerTerminal.h index 91ce230..efcfda2 100644 --- a/diagramCavas/include/powerTerminal.h +++ b/diagramCavas/include/powerTerminal.h @@ -11,6 +11,7 @@ enum class TerminalType { PowerInput, PowerOutput, + PowerConnect, ControlSignal, ProtectiveGround }; @@ -22,6 +23,7 @@ public: TerminalType type, const QString& name, const QPointF& relativePos = QPointF(), + const QString& uuid = "", QObject* parent = nullptr); // 属性访问 diff --git a/diagramCavas/include/topologyManager.h b/diagramCavas/include/topologyManager.h index 8b92b71..acf4d61 100644 --- a/diagramCavas/include/topologyManager.h +++ b/diagramCavas/include/topologyManager.h @@ -27,13 +27,15 @@ public: // 连接管理 PowerConnection* createConnection(const QString& uuid,const QString& fromId, const QString& toId); - QList getConnectionsForElement(const QString& elementId) const; + QList getConnectionsForTerminal(const QString& terminalId) const; void removeConnection(const QString& connId); + bool validateConnection(const QString& fromTermId, const QString& toTermId) const; // 连接查询接口 QList connectionsFrom(const QString& elementId) const; QList connectionsTo(const QString& elementId) const; QList getConnectionsFor(const QString& entityId) const; + PowerConnection* connection(const QString& conId) const; void saveToDB(const QString& path); void loadFromDB(const QString& path); @@ -46,10 +48,13 @@ public: PowerTerminal* createTerminal(const QString& parentEntityId, TerminalType type, const QString& name, - const QPointF& relPos = QPointF()); + const QPointF& relPos = QPointF(), + const QString& uuid = ""); bool deleteTerminal(const QString& terminalId); PowerTerminal* getTerminal(const QString& terminalId) const; QList getTerminalsForEntity(const QString& entityId) const; + PowerEntity* getEntityByTerminal(const QString& terminalId) const; //返回terminal所在的entity实体 + PowerConnection* getConnectionContainsTerminal(const QString& terminalId) const; //返回包含terminal的connection signals: void entityCreated(const QString&); void entityDeleted(const QString&); @@ -65,10 +70,12 @@ private: // 连接存储 QHash m_connections; - QMultiHash m_connectionIndex; // 元素ID到连接的映射 + QMultiHash m_connectionIndex; // 接线点ID到连接的映射 private: QHash m_allTerminals; // ID到接线点映射 QHash> m_terminalsByEntity; // 实体ID到接线点列表 + + QHash> m_entityConnections; // > }; #endif diff --git a/diagramCavas/include/util/baseSelector.h b/diagramCavas/include/util/baseSelector.h index 4ea9ca7..8bb8e95 100644 --- a/diagramCavas/include/util/baseSelector.h +++ b/diagramCavas/include/util/baseSelector.h @@ -64,6 +64,9 @@ public: void setSceneName(const QString& str) {m_sceneName = str;} QString sceneName() const {return m_sceneName;} + FixedPortsModel* getModel() {return _model;} + void createTopoTerminals(GraphicsBaseItem*); + void updateConnectLineByTopology(QList); //通过拓扑关系更新位置 signals: void setWorkingSelector(SelectorType); diff --git a/diagramCavas/include/util/creatingSelector.h b/diagramCavas/include/util/creatingSelector.h index 7570bbc..0289f17 100644 --- a/diagramCavas/include/util/creatingSelector.h +++ b/diagramCavas/include/util/creatingSelector.h @@ -36,7 +36,6 @@ public: virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*, DesignerScene*); void setCreatingItem(modelStateInfo& info) { m_creatingItemInfo=info; } - private: CreatingMethod m_creatingMethod; modelStateInfo m_creatingItemInfo; diff --git a/diagramCavas/include/util/movingSelector.h b/diagramCavas/include/util/movingSelector.h index b3eb5ff..c7dafa3 100644 --- a/diagramCavas/include/util/movingSelector.h +++ b/diagramCavas/include/util/movingSelector.h @@ -19,7 +19,7 @@ public: explicit MovingSelector(FixedPortsModel* model,QObject *parent = 0); virtual ~MovingSelector(); - void updateConnectLine(QList); + //void updateConnectLine(QList); public: void mousePressEvent(QGraphicsSceneMouseEvent*, DesignerScene*); void mouseMoveEvent(QGraphicsSceneMouseEvent*, DesignerScene*); diff --git a/diagramCavas/source/diagramCavas.cpp b/diagramCavas/source/diagramCavas.cpp index c166ca2..6a7d1e0 100644 --- a/diagramCavas/source/diagramCavas.cpp +++ b/diagramCavas/source/diagramCavas.cpp @@ -3,6 +3,8 @@ #include "mainwindow.h" #include "dataBase.h" #include "graphicsItem/graphicsBaseItem.h" +#include "topologyManager.h" +#include "powerEntity.h" #include #include #include @@ -24,14 +26,15 @@ void DiagramCavas::initial() //onSignal_addDrawingPanel(QString("electricElements")); } -void DiagramCavas::onSignal_addDrawingPanel(const QString& sTitile,DiagramMode mode) +void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode) { - DrawingPanel* pPanel = new DrawingPanel(this,mode); - _curPage = sTitile; - pPanel->setPageName(sTitile); - m_mapDrawPanel.insert(sTitile,pPanel); - pPanel->setWindowTitle(sTitile); - this->addSubWindow(pPanel); + DrawingPanel* pPanel = new DrawingPanel(pItem,this,mode); + _curPage = pItem->name(); + pPanel->setPageName(_curPage); + pPanel->setWindowTitle(_curPage); + //->setAttribute(Qt::WA_DeleteOnClose); + QMdiSubWindow* pSub = this->addSubWindow(pPanel); + m_mapDrawPanel.insert(_curPage,qMakePair(pPanel,pSub)); pPanel->show(); FixedPortsModel* pModel = pPanel->getModel(); @@ -41,6 +44,9 @@ void DiagramCavas::onSignal_addDrawingPanel(const QString& sTitile,DiagramMode m void DiagramCavas::onSignal_addGraphicsItem(modelStateInfo& info) { + QMdiSubWindow* actWindow = activeSubWindow(); + if(!actWindow) + return; QWidget* pWindow= currentSubWindow()->widget(); DrawingPanel* pPanel = dynamic_cast(pWindow); @@ -50,7 +56,7 @@ void DiagramCavas::onSignal_addGraphicsItem(modelStateInfo& info) void DiagramCavas::onSignal_addPage() { - onSignal_addDrawingPanel(QString("Page_")+QString::number(++_pageIndex)); + //onSignal_addDrawingPanel(QString("Page_")+QString::number(++_pageIndex)); } void DiagramCavas::onSignal_savePage() @@ -105,18 +111,18 @@ void DiagramCavas::onSignal_savePage() } } -void DiagramCavas::onSignal_loadPage(const QString& sName) +void DiagramCavas::onSignal_loadPage(PowerEntity* p) { - if(!m_mapDrawPanel.contains(sName)) + if(!m_mapDrawPanel.contains(p->name())) { //todo:加载数据 - onSignal_addDrawingPanel(sName); - QJsonObject context = DataBase::GetInstance()->getPageContextByName(sName); - m_mapDrawPanel[sName]->loadNodes(context); + onSignal_addDrawingPanel(p); + QJsonObject context = DataBase::GetInstance()->getPageContextByName(p->name()); + m_mapDrawPanel[p->name()].first->loadNodes(context); } else //已存在 { - m_mapDrawPanel[sName]->show(); + m_mapDrawPanel[p->name()].first->show(); } } @@ -125,13 +131,13 @@ void DiagramCavas::runPage(const QString sName) QString pageName = sName+QString("_run"); if(!m_mapDrawPanel.contains(pageName)) { - onSignal_addDrawingPanel(pageName,DM_run); + //onSignal_addDrawingPanel(pageName,DM_run); QJsonObject context = DataBase::GetInstance()->getPageContextByName(sName); - m_mapDrawPanel[pageName]->loadNodes(context); + //m_mapDrawPanel[pageName]->loadNodes(context); } else //已存在 { - m_mapDrawPanel[pageName]->show(); + //m_mapDrawPanel[pageName]->show(); } } @@ -152,7 +158,7 @@ void DiagramCavas::onSignal_activatePage(const QString& name) void DiagramCavas::onSignal_panelDelete(const QString& name) { - DrawingPanel* pPanel = m_mapDrawPanel.take(name); + DrawingPanel* pPanel = m_mapDrawPanel.take(name).first; if(m_mapDrawPanel.isEmpty()) { /*for(auto it = FixedPortsModel::_nodeData.begin();it!=FixedPortsModel::_nodeData.end();) @@ -166,3 +172,103 @@ void DiagramCavas::onSignal_panelDelete(const QString& name) this->removeSubWindow(pPanel); delete pPanel; } + +void DiagramCavas::onSignal_createEntity(EntityInfo info) +{ + PowerEntity* pEntity; + pEntity = TopologyManager::instance().findEntity(info.sUuid); + if(!pEntity) //不存在创建 + { + pEntity = TopologyManager::instance().createEntity(info.eType,info.sUuid,info.sName); + PowerEntity* pParent = TopologyManager::instance().findEntity(info.sParentId); + if(pParent) //构建父子关系 + { + pParent->addChild(pEntity); + } + + switch (info.eType){ + case EntityType::Grid: + case EntityType::Zone: + case EntityType::Station: + break; + case EntityType::ConfigurationDiagram: + onSignal_addDrawingPanel(pEntity); + break; + default: + break; + } + } + +} + +void DiagramCavas::onSignal_changeEntity(EntityInfo info) +{ + +} + +void DiagramCavas::onSignal_deleteEntity(EntityInfo info) +{ + PowerEntity* pEntity = TopologyManager::instance().findEntity(info.sUuid); + if(pEntity) + { + switch (info.eType){ + case EntityType::Grid: + case EntityType::Zone: + case EntityType::Station: + TopologyManager::instance().deleteEntity(info.sUuid); + break; + case EntityType::ConfigurationDiagram: + removePanel(pEntity); + TopologyManager::instance().deleteEntity(info.sUuid); + break; + default: + break; + } + } +} + +void DiagramCavas::onSignal_selectEntity(EntityInfo info) +{ + PowerEntity* pEntity = TopologyManager::instance().findEntity(info.sUuid); + if(pEntity) + { + if(info.eType == EntityType::ConfigurationDiagram) + { + PowerEntity* pEntity = TopologyManager::instance().findEntity(info.sUuid); + if(pEntity) + { + switch (info.eType){ + case EntityType::Grid: + case EntityType::Zone: + case EntityType::Station: + break; + case EntityType::ConfigurationDiagram: + onSignal_loadPage(pEntity); + break; + default: + break; + } + } + } + } +} + +void DiagramCavas::removePanel(PowerEntity* pEntity) +{ + QMap>::Iterator iter; + for(iter = m_mapDrawPanel.begin(); iter != m_mapDrawPanel.end();++iter) + { + if(pEntity->name() == iter.value().first->pageName()) + { + DrawingPanel* pPanel = m_mapDrawPanel.take(iter.key()).first; + + QWidget* pWindow = static_cast(pPanel); + setActiveSubWindow(iter->second); + closeActiveSubWindow(); + //removeSubWindow(pPanel); + //todo:记录删除组态图,从数据库中删除 + delete pPanel; + break; + } + } +} diff --git a/diagramCavas/source/drawingPanel.cpp b/diagramCavas/source/drawingPanel.cpp index e7f3b46..948e9ea 100644 --- a/diagramCavas/source/drawingPanel.cpp +++ b/diagramCavas/source/drawingPanel.cpp @@ -2,22 +2,25 @@ #include "drawingPanel.h" #include "ui_drawingPanel.h" #include +#include #include "designerView.h" #include "graphicsDataModel/fixedPortsModel.h" #include "util/selectorManager.h" #include "graphicsItem/electricConnectLineItem.h" #include "statusBar.h" #include "dataBase.h" +#include "powerEntity.h" -DrawingPanel::DrawingPanel(QWidget *parent,DiagramMode mode) +DrawingPanel::DrawingPanel(PowerEntity* pEntity,QWidget *parent,DiagramMode mode) : QWidget(parent) , ui(new Ui::drawingPanel) ,_pModel(nullptr) ,_mode(mode) + ,_pEntity(pEntity) { ui->setupUi(this); - _pModel = new FixedPortsModel(); + _pModel = new FixedPortsModel(pEntity); _pModel->setTopWidget(this); if(mode == DM_edit) m_pSelectorManager = new SelectorManager(_pModel,this); @@ -144,6 +147,8 @@ void DrawingPanel::closeEvent(QCloseEvent *closeEvent) pItem->unbindProperty(); }*/ emit panelDelete(_name); + //closeEvent->ignore(); + //hide(); } void DrawingPanel::onSignal_addGraphicsItem(modelStateInfo& info) diff --git a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp index 08b2f4a..14eb764 100644 --- a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp +++ b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp @@ -11,16 +11,19 @@ #include "drawingPanel.h" #include "itemPropertyDlg.h" #include "dataManager.h" +#include "powerEntity.h" +#include "topologyManager.h" #include #include QMap FixedPortsModel::_nodeData; bool FixedPortsModel::_dataInitialised = false; -FixedPortsModel::FixedPortsModel() +FixedPortsModel::FixedPortsModel(PowerEntity* pEntity) :_scene(nullptr) ,_widget(nullptr) ,_Interface(nullptr) + ,_pEntity(pEntity) { loadNodeDataFromDataBase(); _Interface = new HttpInterface(this); @@ -265,7 +268,7 @@ void FixedPortsModel::deleteNodeItem(GraphicsBaseItem* pItem) auto pLine = dynamic_cast(pItem); if(pLine) { - Connection con = pLine->getConnection(); + /*Connection con = pLine->getConnection(); GraphicsBaseItem* srcItem = _nodeItem[con.nSrcNodeId]; if(srcItem) { @@ -287,12 +290,30 @@ void FixedPortsModel::deleteNodeItem(GraphicsBaseItem* pItem) QUuid lineId = pLine->itemId(); _nodeItem.take(lineId); _scene->removeItem(pLine); + delete pLine;*/ + + QUuid conId = pLine->itemId(); + TopologyManager::instance().removeConnection(conId.toString()); + + PowerConnection* pCon = TopologyManager::instance().connection(conId.toString()); + if(pCon){ + PowerEntity* itemFrom = TopologyManager::instance().getEntityByTerminal(pCon->fromTerminalId()); + PowerEntity* itemTo = TopologyManager::instance().getEntityByTerminal(pCon->toTerminalId()); + if(itemFrom && itemTo) + { + _nodeItem.value(QUuid(itemFrom->id()))->setItemChanged(true); + _nodeItem.value(QUuid(itemTo->id()))->setItemChanged(true); + } + } + + _nodeItem.take(conId); + _scene->removeItem(pLine); delete pLine; } } else { - QMap ports = pItem->getPorts(); + /*QMap ports = pItem->getPorts(); for(auto port:ports) { if(port->connected()) @@ -307,7 +328,6 @@ void FixedPortsModel::deleteNodeItem(GraphicsBaseItem* pItem) ItemPort* ptOppo = oppositeItem->getPortPtr(oppositePort); ptOppo->disConnect(); oppositeItem->setItemChanged(true); - //oppositeItem->updateConnectData(); } QUuid lineId = pLine->itemId(); @@ -317,10 +337,26 @@ void FixedPortsModel::deleteNodeItem(GraphicsBaseItem* pItem) port->disConnect(); } - } + }*/ QUuid srcId = pItem->itemId(); + QList lstCon = TopologyManager::instance().getConnectionsFor(srcId.toString()); + for(auto &con:lstCon) + { + PowerEntity* pFrom = TopologyManager::instance().getEntityByTerminal(con->fromTerminalId()); + PowerEntity* pTo = TopologyManager::instance().getEntityByTerminal(con->toTerminalId()); + if(pFrom && pTo) + { + if(srcId.toString() == pFrom->id()) //对象是srcItem + _nodeItem.value(QUuid(pTo->id()))->setItemChanged(true); + else //对象是toItem + _nodeItem.value(QUuid(pFrom->id()))->setItemChanged(true); + } + + //TopologyManager::instance().removeConnection(con->id()); //删除entity时会同时删除相关连接,无需手动删除 + } + TopologyManager::instance().deleteEntity(srcId.toString()); + pItem->setItemChanged(true); - //pItem->updateConnectData(); _nodeItem.take(srcId); _scene->removeItem(pItem); delete pItem; @@ -549,6 +585,49 @@ QWidget* FixedPortsModel::getTopWidget() return dynamic_cast(_widget); } +QPointF FixedPortsModel::getTerminalPos(const QString& sTerminalId) +{ + PowerEntity* pParent = TopologyManager::instance().getEntityByTerminal(sTerminalId); + if(pParent) + { + for(auto &item:_nodeItem) + { + if(pParent->id() == item->itemId().toString()) //找到terminal父图元 + { + for(auto &pPort:item->getPorts()) + { + if(pPort->getId() == sTerminalId) + { + return pPort->scenePos(); + } + } + } + } + } + return QPointF(0,0); +} + +ElectricConnectLineItem* FixedPortsModel::getLineItemById(const QString& terminalId) +{ + for(auto iter:_nodeItem) //获取id所在的lineitem + { + auto item = dynamic_cast(iter); + if(item) + { + if(item->getItemType() == GIT_link) + { + PowerConnection* pCon = TopologyManager::instance().getConnectionContainsTerminal(terminalId); + if(pCon) + { + if(item->itemId().toString() == pCon->id()) + return dynamic_cast(item); + } + } + } + } + return nullptr; +} + void FixedPortsModel::showModelDlg(const QString& sName,QUuid uuid,GraphicsBaseItem* pItem) { modelStateInfo stateInfo = _modelStateInfo[sName]; @@ -586,3 +665,8 @@ void FixedPortsModel::generatePropertyDlg(const QString& sModel) } } } + +ConfigurationDiagram* FixedPortsModel::getTopologyDiagram() +{ + return dynamic_cast(_pEntity); +} diff --git a/diagramCavas/source/graphicsItem/electricConnectLineItem.cpp b/diagramCavas/source/graphicsItem/electricConnectLineItem.cpp index 3e735f4..667ec2d 100644 --- a/diagramCavas/source/graphicsItem/electricConnectLineItem.cpp +++ b/diagramCavas/source/graphicsItem/electricConnectLineItem.cpp @@ -376,7 +376,7 @@ void ElectricConnectLineItem::calculatePath() m_boundingRect = m_points.boundingRect(); } -void ElectricConnectLineItem::updateConnection(QUuid callerId,QPointF pos) +/*void ElectricConnectLineItem::updateConnection(QUuid callerId,QPointF pos) { //qDebug()<connected()) { QJsonObject port; - port["portId"] = ptr->getTag(); + port["portId"] = ptr->getId(); auto pLine = ptr->getConnectPtr(); - port["connectedItem"] = pLine->getOppositeId(m_itemId).toString(); + //port["connectedItem"] = pLine->getOppositeId(m_itemId).toString(); port["x"] = ptr->pos().x(); port["y"] = ptr->pos().y(); arr.push_back(port); diff --git a/diagramCavas/source/graphicsItem/electricSvgItemRect.cpp b/diagramCavas/source/graphicsItem/electricSvgItemRect.cpp index c57bed1..745165e 100644 --- a/diagramCavas/source/graphicsItem/electricSvgItemRect.cpp +++ b/diagramCavas/source/graphicsItem/electricSvgItemRect.cpp @@ -1,5 +1,6 @@ #include "graphicsItem/electricSvgItemRect.h" #include "graphicsItem/itemPort.h" +#include "global.h" #include #include @@ -18,7 +19,7 @@ ElectricSvgItemRect::ElectricSvgItemRect(const QRect &rect, QGraphicsItem *paren setFunctionHandleEnaable(false); //入线口 - ItemPort* pHandle1 = new ItemPort(this); + /*ItemPort* pHandle1 = new ItemPort(this); pHandle1->setType(T_lineIn); pHandle1->setTag(H_connect); pHandle1->setPortPos(P_top); @@ -32,10 +33,13 @@ ElectricSvgItemRect::ElectricSvgItemRect(const QRect &rect, QGraphicsItem *paren pHandle2->setParent(this); m_vecHanle.insert(H_connect+1,pHandle2); + m_mapPort.insert(QString::number(_portId++),pHandle1); + m_mapPort.insert(QString::number(_portId++),pHandle2);*/ + m_dRatioX = 0.5; - m_mapPort.insert(QString::number(_portId++),pHandle1); - m_mapPort.insert(QString::number(_portId++),pHandle2); + addPort(P_const,QPointF(boundingRect().right() - boundingRect().width() * m_dRatioX, boundingRect().top()),QUuid::createUuid().toString(),T_lineIn,P_top); + addPort(P_const,QPointF(boundingRect().right() - boundingRect().width() * m_dRatioX, boundingRect().bottom()),QUuid::createUuid().toString(),T_lineOut,P_down); qRegisterMetaType("PropertyInfo"); //注册自定义数据类型 } @@ -49,7 +53,7 @@ ElectricSvgItemRect::~ElectricSvgItemRect() void ElectricSvgItemRect::updateHandles() { ElectricSvgItem::updateHandles(); - if( m_vecHanle.contains(H_connect)) + /*if( m_vecHanle.contains(H_connect)) { const QRectF& boundingRect = this->boundingRect(); @@ -62,7 +66,7 @@ void ElectricSvgItemRect::updateHandles() { m_vecHanle[H_connect + 1]->move(boundingRect.right() - boundingRect.width() * m_dRatioX, boundingRect.bottom()); } - } + }*/ } void ElectricSvgItemRect::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) diff --git a/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp b/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp index d79b6d2..f40f936 100644 --- a/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp +++ b/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp @@ -11,6 +11,7 @@ GraphicsBaseItem::GraphicsBaseItem(QGraphicsItem *parent) : AbstractShapeType(parent) ,_property(nullptr) + ,_pEntity(nullptr) { m_type = T_item; _portId = 1; @@ -151,6 +152,16 @@ void GraphicsBaseItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) Q_UNUSED(event); } +void GraphicsBaseItem::setEntity(PowerEntity* pEntity) +{ + _pEntity = pEntity; +} + +PowerEntity* GraphicsBaseItem::entity() +{ + return _pEntity; +} + void GraphicsBaseItem::setLabelTag(const QString& name) { m_vecHanle[H_textCaption]->setText(name); @@ -181,7 +192,7 @@ QString GraphicsBaseItem::getLabelVoltage() const return m_vecHanle[h_textVoltage]->getText(); } -int GraphicsBaseItem::addPort(PortState typ,QPointF vec) +int GraphicsBaseItem::addPort(PortState typ,QPointF vec,QString id,HandleType hType,PortPos pos) { int ntagId = -1; for(ntagId = H_connect;ntagId < 999;++ntagId) //添加到未占用位置 @@ -189,17 +200,30 @@ int GraphicsBaseItem::addPort(PortState typ,QPointF vec) if(!m_vecHanle.contains(ntagId)) break; } + ItemPort* pPort = new ItemPort(this); + if(id.isEmpty()) + { + pPort->setId(QUuid::createUuid().toString()); + } + else + { + pPort->setId(id); + } if(typ == p_movable) { - ItemPort* pPort = new ItemPort(this); pPort->setType(T_lineInOut); - pPort->setTag(ntagId); - m_vecHanle.insert(ntagId,pPort); - pPort->setPos(vec); - pPort->setParent(this); - - m_mapPort.insert(QString::number(_portId++),pPort); } + else + { + pPort->setType(hType); + pPort->setPortPos(pos); + } + pPort->setTag(ntagId); + m_vecHanle.insert(ntagId,pPort); + pPort->setPos(vec); + pPort->setParent(this); + + m_mapPort.insert(QString::number(_portId++),pPort); return ntagId; } @@ -275,9 +299,9 @@ void GraphicsBaseItem::updateConnectData() if(ptr->connected()) { QJsonObject port; - port["portId"] = ptr->getTag(); + port["portId"] = ptr->getId(); auto pLine = ptr->getConnectPtr(); - port["connectedItem"] = pLine->getOppositeId(m_itemId).toString(); + //port["connectedItem"] = pLine->getOppositeId(m_itemId).toString(); arr.push_back(port); } } diff --git a/diagramCavas/source/graphicsItem/itemPort.cpp b/diagramCavas/source/graphicsItem/itemPort.cpp index d3e92a2..ff05a14 100644 --- a/diagramCavas/source/graphicsItem/itemPort.cpp +++ b/diagramCavas/source/graphicsItem/itemPort.cpp @@ -2,8 +2,8 @@ #include "graphicsItem/itemPort.h" #include "graphicsItem/handleRect.h" -ItemPort::ItemPort(QGraphicsItem *parent) - : HandleRect(parent) +ItemPort::ItemPort(QGraphicsItem *parent,QString uuid) + : HandleRect(parent),_uuid(uuid) { _pos = P_top; _ptr = nullptr; diff --git a/diagramCavas/source/itemPropertyDlg.cpp b/diagramCavas/source/itemPropertyDlg.cpp index eb5d4e2..0064e26 100644 --- a/diagramCavas/source/itemPropertyDlg.cpp +++ b/diagramCavas/source/itemPropertyDlg.cpp @@ -40,7 +40,10 @@ void ItemPropertyDlg::loadGroupButton(QMap map) btn->setCheckable(true); btnGroup_->addButton(btn); btnMap_.insert(info.groupName, btn); - layout_->addWidget(btn); + if(info.isPublic) //公共属性组置顶 + layout_->insertWidget(0,btn); + else + layout_->addWidget(btn); connect(btn, &QAbstractButton::clicked, [this, info](){ onGroupSelected(info.groupName); diff --git a/diagramCavas/source/powerTerminal.cpp b/diagramCavas/source/powerTerminal.cpp index 6a5c1ca..afa012c 100644 --- a/diagramCavas/source/powerTerminal.cpp +++ b/diagramCavas/source/powerTerminal.cpp @@ -4,13 +4,18 @@ PowerTerminal::PowerTerminal(const QString& parentEntityId, TerminalType type, const QString& name, const QPointF& relativePos, + const QString& uuid, QObject* parent) : QObject(parent), - m_id(QUuid::createUuid().toString()), + m_id(uuid), m_parentEntityId(parentEntityId), m_type(type), m_name(name), - m_relativePosition(relativePos) {} + m_relativePosition(relativePos) +{ + if(m_id.isEmpty()) + m_id = QUuid::createUuid().toString(); +} void PowerTerminal::setRelativePosition(const QPointF& newPos) { if (m_relativePosition != newPos) { @@ -38,7 +43,7 @@ PowerTerminal* PowerTerminal::fromJson(const QJsonObject& json, QObject* parent) qreal x = json["relX"].toDouble(); qreal y = json["relY"].toDouble(); - PowerTerminal* term = new PowerTerminal(parentId, type, name, QPointF(x, y), parent); + PowerTerminal* term = new PowerTerminal(parentId, type, name, QPointF(x, y),id, parent); term->m_id = id; // 注意:需要修改m_id为可写,或使用其他机制保持ID一致 return term; } diff --git a/diagramCavas/source/topologyManager.cpp b/diagramCavas/source/topologyManager.cpp index 2e9eadf..412e1ed 100644 --- a/diagramCavas/source/topologyManager.cpp +++ b/diagramCavas/source/topologyManager.cpp @@ -26,6 +26,8 @@ void TopologyManager::clearAllData() // 删除所有实体(自动删除子对象) qDeleteAll(m_entities); m_entities.clear(); + + m_allTerminals.clear(); //端点由父亲entity释放 } PowerEntity* TopologyManager::createEntity(EntityType type,const QString& uuid, const QString& name) @@ -60,7 +62,8 @@ bool TopologyManager::deleteEntity(const QString& id) PowerEntity* entity = m_entities[id]; // 步骤1:删除所有相关连接 - auto relatedConns = m_connectionIndex.values(id); + auto relatedConns = getConnectionsFor(id); + for (auto conn : relatedConns) { removeConnection(conn->id()); } @@ -88,8 +91,8 @@ bool TopologyManager::deleteEntity(const QString& id) PowerConnection* TopologyManager::createConnection(const QString& connId,const QString& fromId, const QString& toId) { // 验证有效性 - if (!m_entities.contains(fromId) || - !m_entities.contains(toId) || + if (!m_allTerminals.contains(fromId) || + !m_allTerminals.contains(toId) || fromId == toId) { qWarning() << "Invalid connection endpoints"; @@ -117,9 +120,9 @@ PowerConnection* TopologyManager::createConnection(const QString& connId,const Q return conn; } -QList TopologyManager::getConnectionsForElement(const QString& elementId) const +QList TopologyManager::getConnectionsForTerminal(const QString& terminalId) const { - return m_connectionIndex.values(elementId); + return m_connectionIndex.values(terminalId); } void TopologyManager::removeConnection(const QString& connId) @@ -139,44 +142,96 @@ void TopologyManager::removeConnection(const QString& connId) emit connectionRemoved(connId); } +bool TopologyManager::validateConnection(const QString& fromTermId, const QString& toTermId) const +{ + PowerTerminal* fromTerm = getTerminal(fromTermId); + PowerTerminal* toTerm = getTerminal(toTermId); + + if (!fromTerm || !toTerm) return false; + + // 类型兼容性检查(示例规则) + switch(fromTerm->type()) { + case TerminalType::PowerOutput: + if (toTerm->type() != TerminalType::PowerInput && toTerm->type() != TerminalType::PowerConnect) return false; + break; + case TerminalType::PowerInput: + if (toTerm->type() != TerminalType::PowerOutput && toTerm->type() != TerminalType::PowerConnect) return false; + break; + case TerminalType::PowerConnect: + break; + case TerminalType::ControlSignal: + if (toTerm->type() != TerminalType::ControlSignal) return false; + break; + default: + return false; + } + + int a =1; + // 禁止自连接 + return (fromTerm->parentEntityId() != toTerm->parentEntityId()); +} + // 连接查询接口 QList TopologyManager::connectionsFrom(const QString& elementId) const { QList res; - QList lst = m_connectionIndex.values(elementId); + /*QList lst = m_connectionIndex.values(elementId); for(auto &val:lst) { if(val->fromTerminalId() == elementId) res.append(val); - } + }*/ return res; } QList TopologyManager::connectionsTo(const QString& elementId) const { QList res; - QList lst = m_connectionIndex.values(elementId); + /*QList lst = m_connectionIndex.values(elementId); for(auto &val:lst) { if(val->toTerminalId() == elementId) res.append(val); - } + }*/ return res; } QList TopologyManager::getConnectionsFor(const QString& entityId) const { - return m_connectionIndex.values(entityId); + QList lst; + QList lstTerminal = getTerminalsForEntity(entityId); + for(auto &terminal:lstTerminal) + { + PowerConnection* con = getConnectionContainsTerminal(terminal->id()); + if(con) + lst.append(con); + } + return lst; +} + +PowerConnection* TopologyManager::connection(const QString& conId) const +{ + return m_connections.value(conId,nullptr); } void TopologyManager::saveToDB(const QString& path) { QJsonObject root; - QJsonArray entitiesArray; - for (auto entity : m_entities) - entitiesArray.append(entity->toJson()); - root["entities"] = entitiesArray; + // 序列化实体(含接线点) + QJsonArray entities; + foreach (auto entity, m_entities) { + QJsonObject entObj = entity->toJson(); + + QJsonArray terminalsArray; + foreach (auto term, entity->terminals()) { + terminalsArray.append(term->toJson()); + } + entObj["terminals"] = terminalsArray; + + entities.append(entObj); + } + root["entities"] = entities; QJsonArray connectionsArray; for (auto conn : m_connections) @@ -209,6 +264,12 @@ void TopologyManager::loadFromDB(const QString& path) PowerEntity* entity = createEntity(type, id, name); + foreach (auto termJson, entObj["terminals"].toArray()) { + PowerTerminal* term = PowerTerminal::fromJson(termJson.toObject(), entity); + m_allTerminals[term->id()] = term; + m_terminalsByEntity[entity->id()].append(term); + } + // 记录待处理的子关系 pendingChildren[id] = entObj["children"].toVariant().toStringList(); } @@ -259,10 +320,11 @@ QList TopologyManager::findEntitiesByName(const QString& name) con PowerTerminal* TopologyManager::createTerminal(const QString& parentEntityId, TerminalType type, const QString& name, - const QPointF& relPos) { + const QPointF& relPos, + const QString& uuid) { if (!m_entities.contains(parentEntityId)) return nullptr; - PowerTerminal* term = new PowerTerminal(parentEntityId, type, name, relPos); + PowerTerminal* term = new PowerTerminal(parentEntityId, type, name, relPos, uuid); m_allTerminals[term->id()] = term; m_terminalsByEntity[parentEntityId].append(term); @@ -293,6 +355,40 @@ bool TopologyManager::deleteTerminal(const QString& terminalId) { return true; } +PowerTerminal* TopologyManager::getTerminal(const QString& terminalId) const +{ + auto it = m_allTerminals.find(terminalId); + return (it != m_allTerminals.end()) ? it.value() : nullptr; +} + QList TopologyManager::getTerminalsForEntity(const QString& entityId) const { return m_terminalsByEntity.value(entityId); } + +PowerEntity* TopologyManager::getEntityByTerminal(const QString& terminalId) const +{ + QHash>::ConstIterator iter; + for(iter = m_terminalsByEntity.begin();iter != m_terminalsByEntity.end();++iter) + { + for(auto &terminal:iter.value()) + { + if(terminal->id() == terminalId) + { + return m_entities[iter.key()]; + } + } + } + return nullptr; +} + +PowerConnection* TopologyManager::getConnectionContainsTerminal(const QString& terminalId) const +{ + for(auto &con:m_connections) + { + if(con->fromTerminalId() == terminalId || con->toTerminalId() == terminalId) + { + return con; + } + } + return nullptr; +} diff --git a/diagramCavas/source/util/baseSelector.cpp b/diagramCavas/source/util/baseSelector.cpp index 71aee88..8f89b05 100644 --- a/diagramCavas/source/util/baseSelector.cpp +++ b/diagramCavas/source/util/baseSelector.cpp @@ -4,8 +4,11 @@ #include #include "graphicsItem/graphicsBaseItem.h" #include "graphicsItem/handleText.h" - - +#include "powerEntity.h" +#include "topologyManager.h" +#include "graphicsItem/itemPort.h" +#include "graphicsItem/electricConnectLineItem.h" +#include "topologyManager.h" QPointF BaseSelector::ms_ptMouseDown(0.0,0.0); QPointF BaseSelector::ms_ptMouseLast(0.0,0.0); @@ -386,3 +389,68 @@ void BaseSelector::setCursor(DesignerScene *scene, const QCursor &cursor) view->setCursor(cursor); } +void BaseSelector::createTopoTerminals(GraphicsBaseItem* pItem) +{ + PowerEntity* pEntity = pItem->entity(); + + if(pEntity) + { + QMap mapPorts = pItem->getPorts(); //创建对应 + for(auto &port:mapPorts) + { + TerminalType terType; + + HandleType tpe = port->getType(); + switch (tpe) { + case T_lineIn: + terType = TerminalType::PowerInput; + break; + case T_lineOut: + terType = TerminalType::PowerOutput; + break; + case T_lineInOut: + terType = TerminalType::PowerConnect; + break; + default: + break; + } + TopologyManager::instance().createTerminal(pEntity->id(),terType,"",port->pos(),port->getId()); + } + } +} + +void BaseSelector::updateConnectLineByTopology(QList lst) +{ + for(auto iter:lst) //更新连接线 + { + auto item = dynamic_cast(iter); + if(item) + { + if(item->getItemType() != GIT_link) //获取非电缆对象 + { + QUuid nId = item->itemId(); + auto lstConnect = TopologyManager::instance().getConnectionsFor(nId.toString()); + for(auto &pConnect:lstConnect) + { + if(pConnect) + { + QString fromTerminalId = pConnect->fromTerminalId(); //connect自身包含头尾巴顺序 + QString toTerminalId = pConnect->toTerminalId(); + + QPointF fromPos = _model->getTerminalPos(fromTerminalId); + QPointF toPos = _model->getTerminalPos(toTerminalId); + + ElectricConnectLineItem* connectItem = _model->getLineItemById(fromTerminalId); + if(connectItem) + { + connectItem->setStartPoint(fromPos); + connectItem->setEndPoint(toPos); + //qDebug()<calculatePath(); + } + } + } + } + } + } +} diff --git a/diagramCavas/source/util/connectingSelector.cpp b/diagramCavas/source/util/connectingSelector.cpp index e5e7f4f..97be142 100644 --- a/diagramCavas/source/util/connectingSelector.cpp +++ b/diagramCavas/source/util/connectingSelector.cpp @@ -2,6 +2,7 @@ #include "graphicsItem/itemControlHandle.h" #include "graphicsItem/itemPort.h" #include "graphicsItem/electricConnectLineItem.h" +#include "topologyManager.h" #include #include #include @@ -88,18 +89,20 @@ void ConnectingSelector::setTargetHighLight(bool val) void ConnectingSelector::createConnectLline(GraphicsBaseItem* connectingItem,GraphicsBaseItem* touchedItem,DesignerScene* scene) { + QUuid uid = QUuid::createUuid(); ElectricConnectLineItem* pItem = new ElectricConnectLineItem(); - pItem->setItemId(QUuid::createUuid()); + pItem->setItemId(uid); pItem->setItemType(GIT_link); scene->addItem(pItem); ItemPort* ptSrc = connectingItem->getPortPtr(ms_nDragHandle); - QUuid srcId = connectingItem->itemId(); - int srcPort = ptSrc->getTag(); - HandleType srcType = ptSrc->getType(); - PortPos srcPos = ptSrc->portPos(); + //QUuid srcId = connectingItem->itemId(); + //int srcPort = ptSrc->getTag(); + //HandleType srcType = ptSrc->getType(); + //PortPos srcPos = ptSrc->portPos(); pItem->setStartPoint(ptSrc->scenePos()); ptSrc->setConnect(pItem); + QString srcPortId = ptSrc->getId(); //port自身id ItemPort* ptDest = nullptr; if(touchedItem->getItemType() == GIT_bus) //母线动态创建port @@ -110,6 +113,8 @@ void ConnectingSelector::createConnectLline(GraphicsBaseItem* connectingItem,Gra ptDest = touchedItem->getPortPtr(nId); pItem->setEndPoint(ptDest->scenePos()); } + + createTopoTerminals(touchedItem); //创建port时创建对应的terminal } else { @@ -120,14 +125,18 @@ void ConnectingSelector::createConnectLline(GraphicsBaseItem* connectingItem,Gra if(ptDest != nullptr) { - QUuid destId = touchedItem->itemId(); - int destPort = ptDest->getTag(); - HandleType destType = ptDest->getType(); - PortPos destPos = ptDest->portPos(); + //QUuid destId = touchedItem->itemId(); + //int destPort = ptDest->getTag(); + //HandleType destType = ptDest->getType(); + //PortPos destPos = ptDest->portPos(); + QString destPortId = ptDest->getId(); //port自身id - pItem->calculatePath(); - pItem->setConnection(Connection(srcId,srcPort,srcType,srcPos,destId,destPort,destType,destPos)); - ptDest->setConnect(pItem); + //pItem->calculatePath(); + //pItem->setConnection(Connection(srcId,srcPort,srcType,srcPos,destId,destPort,destType,destPos)); + //ptDest->setConnect(pItem); + + if(TopologyManager::instance().validateConnection(srcPortId,destPortId)) + TopologyManager::instance().createConnection(uid.toString(),srcPortId,destPortId); //创建拓扑连接(逻辑) _model->addNodeItem(pItem->itemId(),pItem); auto srcParent = ptSrc->getParentPtr(); @@ -135,9 +144,6 @@ void ConnectingSelector::createConnectLline(GraphicsBaseItem* connectingItem,Gra srcParent->setItemChanged(true); destParent->setItemChanged(true); - //srcParent->updateConnectData(); - //destParent->updateConnectData(); - //m_graphicsItem[sceneName()].insert(QString::number(pItem->itemId()),pItem); //插入连接线到总表 } } @@ -152,7 +158,7 @@ void ConnectingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, Designe GraphicsBaseItem* item = qgraphicsitem_cast(items.first()); if(item) { - if(ms_nDragHandle >= H_connect) + if(ms_nDragHandle >= H_connect) //操作的是port端点 { ItemPort* pt = item->getPortPtr(ms_nDragHandle); if(pt) @@ -215,6 +221,10 @@ void ConnectingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Desi if(m_pConnectingItem && m_pTouchedItem) { createConnectLline(m_pConnectingItem,m_pTouchedItem,scene); + auto obj = dynamic_cast(m_pConnectingItem); + QList lst; + lst.append(obj); + updateConnectLineByTopology(lst); } } diff --git a/diagramCavas/source/util/creatingSelector.cpp b/diagramCavas/source/util/creatingSelector.cpp index c2c15c4..89e439b 100644 --- a/diagramCavas/source/util/creatingSelector.cpp +++ b/diagramCavas/source/util/creatingSelector.cpp @@ -4,6 +4,9 @@ #include "graphicsItem/electricSvgItemBus.h" #include "graphicsItem/electricSvgItemRect.h" #include "graphicsItem/electricSvgItemTriangle.h" +#include "graphicsItem/itemPort.h" +#include "topologyManager.h" +#include "global.h" #include #include #include @@ -30,6 +33,8 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer ms_ptMouseDown = event->scenePos(); ms_ptMouseLast = event->scenePos(); + QUuid uuid = QUuid::createUuid(); + EntityInfo info; if(m_pCreatingItem == nullptr) { scene->clearSelection(); @@ -58,27 +63,29 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer { m_creatingMethod = CM_click; m_pCreatingItem = new ElectricSvgItemBus(QRect(-100, -3, 200, 6)); - m_pCreatingItem->setItemId(QUuid::createUuid()); + m_pCreatingItem->setItemId(uuid); m_pCreatingItem->setItemType(GIT_bus); m_pCreatingItem->editShape(ms_nDragHandle, ms_ptMouseLast); emit setWorkingSelector(ST_base); + info.eType = EntityType::BusBar; } break; case GIT_itemRect: { m_creatingMethod = CM_click; m_pCreatingItem = new ElectricSvgItemRect(QRect(-15, -15, 30, 30)); - m_pCreatingItem->setItemId(QUuid::createUuid()); + m_pCreatingItem->setItemId(uuid); m_pCreatingItem->setItemType(GIT_itemRect); m_pCreatingItem->editShape(ms_nDragHandle, ms_ptMouseLast); emit setWorkingSelector(ST_base); + info.eType = EntityType::CircuitBreaker; } break; case GIT_itemTri: { m_creatingMethod = CM_click; m_pCreatingItem = new ElectricSvgItemTriangle(QRect(-15, -15, 30, 30)); - m_pCreatingItem->setItemId(QUuid::createUuid()); + m_pCreatingItem->setItemId(uuid); m_pCreatingItem->setItemType(GIT_itemTri); m_pCreatingItem->editShape(ms_nDragHandle, ms_ptMouseLast); emit setWorkingSelector(ST_base); @@ -103,6 +110,17 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer else if(m_creatingMethod == CM_click) m_pCreatingItem->addPoint(ms_ptMouseDown); } + else{ + qDebug()<<"item type error"; + return; + } + + info.sUuid = uuid.toString(); + + PowerEntity* pEntity = TopologyManager::instance().createEntity(info.eType,info.sUuid,info.sName); + if(pEntity) + m_pCreatingItem->setEntity(pEntity); + createTopoTerminals(m_pCreatingItem); } if(m_pCreatingItem && m_creatingMethod == CM_click) diff --git a/diagramCavas/source/util/movingSelector.cpp b/diagramCavas/source/util/movingSelector.cpp index 9891a9b..39b57b3 100644 --- a/diagramCavas/source/util/movingSelector.cpp +++ b/diagramCavas/source/util/movingSelector.cpp @@ -3,7 +3,6 @@ #include #include #include -#include "graphicsItem/electricConnectLineItem.h" MovingSelector::MovingSelector(FixedPortsModel* model,QObject *parent) : BaseSelector(model,parent) @@ -20,7 +19,8 @@ void MovingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerSc ms_ptMouseLast = event->scenePos(); QList items = scene->selectedItems(); - updateConnectLine(items); + //updateConnectLine(items); + updateConnectLineByTopology(items); } void MovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) @@ -45,14 +45,15 @@ void MovingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designer if(item) item->removeOperationCopy(); } - updateConnectLine(items); + //updateConnectLine(items); + updateConnectLineByTopology(items); setCursor(scene, Qt::ArrowCursor); scene->callParentEvent(event); emit setWorkingSelector(ST_base); } -void MovingSelector::updateConnectLine(QList lst) +/*void MovingSelector::updateConnectLine(QList lst) { for(auto iter:lst) //更新连接线 { @@ -73,5 +74,5 @@ void MovingSelector::updateConnectLine(QList lst) } } } -} +}*/ diff --git a/diagramCavas/ui/drawingPanel.ui b/diagramCavas/ui/drawingPanel.ui index d70447e..617a57c 100644 --- a/diagramCavas/ui/drawingPanel.ui +++ b/diagramCavas/ui/drawingPanel.ui @@ -34,8 +34,6 @@ - - - + diff --git a/diagramUtils/include/dataBase.h b/diagramUtils/include/dataBase.h index d6e55bc..5303421 100644 --- a/diagramUtils/include/dataBase.h +++ b/diagramUtils/include/dataBase.h @@ -64,6 +64,7 @@ public: bool getModelGroup(); //获取模型组 bool getAttribute(); //获取属性 bool getModelAttribute(); //获取模型-属性对照组 + bool getModelAttributePublic(); //获取公共属性组 bool getModelConnectivity(); //获取连接性 QMap AttributeGroup() const {return _attributeGroup;} @@ -72,16 +73,19 @@ public: QMap ModelGroup() const {return _modelGroup;} QMap Attribute() const {return _attribute;} QMap ModelAttribute() const {return _modelAttribute;} + QMap ModelAttributePublic() const {return _modelAttributePublic;} QMap ModelConnectivity() const {return _modelConnectivity;} //***********工程模 bool createProjectManager(); //生成记录表,包含工程模名称,属性组名,启用和关闭的属性字段(json类型)[一个属性组建一个表] - bool insertProjectManager(const QString& name,const QString& tag,const QString& metaModel,const QString& groupName,int linkType,QJsonObject checkState); + bool insertProjectManager(const QString& name,const QString& tag,const QString& metaModel,const QString& groupName,int linkType,QJsonObject checkState,bool isPublic = false); bool updateCheckState(const QString& tableName,QJsonObject checkState); //更新属性选中状态 QMap getProjectFromManager(const QString& sMeta); //返回元模下已创建的工程名 QMap getCheckStateFromManager(const QString& sProject); //获取当前工程模型所有属性的选择状态 <属性名,选择状态> + QMap getPublicStateFromManager(); //获取公共属性组 QMap getProjectTableName(const QString& sProject); //获取当前工程模型下所有表信息 bool createDynamicTable(const QString&, const QStringList&); bool deleteProjectModel(const QString&); + bool ifDynamicTableExist(const QString&); //动态表是否存在 bool updateProjectName(const QString& newTable,const QString& newPro,const QString& oldTable); //更新mangager工程模名称 bool alterTableName(const QString& oldTable,const QString& newTable); //修改表名 bool updateComponentModelName(const QString& strOld,const QString& strNew); //修改component中的模型名 @@ -94,6 +98,7 @@ public: //**********使用工程模 QMap getAllProjectModel(); //获取所有工程模<名称,图元类型> QMap getModelInfo(const QString&); //获取模型信息 + QMap getPublicInfo(); //获取公共属性组信息 QMap getProjectModelGroupInfo(const QString&); //获取指定工程模所有属性组信息<属性组名,属性信息> QMap selectGroupProperty(const QString& tableName,QMap mapPro); //返回属性组表中的信息 private: @@ -103,6 +108,7 @@ private: QMap _modelGroup; //模型组 QMap _attribute; //属性组 QMap _modelAttribute; //模型-属性对照组 + QMap _modelAttributePublic; //公共属性组 QMap _modelConnectivity; //连接性组 private: void initial(); diff --git a/diagramUtils/include/dataManager.h b/diagramUtils/include/dataManager.h index 0822dbc..874fcae 100644 --- a/diagramUtils/include/dataManager.h +++ b/diagramUtils/include/dataManager.h @@ -20,8 +20,8 @@ public: static DataManager& instance(); public: - void initialModelState(); - void initialModelData(); + void initialModelState(bool refresh = false); + void initialModelData(bool refresh = false); void updateModelData(const QString& sModel,QUuid uuid,const QString& sGroup,QMap mapPro); diff --git a/diagramUtils/include/logger.h b/diagramUtils/include/logger.h index a9dd5f6..4be132a 100644 --- a/diagramUtils/include/logger.h +++ b/diagramUtils/include/logger.h @@ -4,6 +4,7 @@ #include #include #include +#include "export.hpp" // 日志宏定义 #define LOG(level, module, message) Logger::instance().log(Logger::level, module, message) @@ -13,7 +14,7 @@ #define LOG_ERROR(module, message) LOG(ERROR, module, message) #define LOG_FATAL(module, message) LOG(FATAL, module, message) -class Logger : public QObject +class DIAGRAM_DESIGNER_PUBLIC Logger : public QObject { Q_OBJECT diff --git a/diagramUtils/source/dataBase.cpp b/diagramUtils/source/dataBase.cpp index 41eec7b..a077d72 100644 --- a/diagramUtils/source/dataBase.cpp +++ b/diagramUtils/source/dataBase.cpp @@ -56,6 +56,7 @@ void DataBase::initial() getModelGroup(); //获取模型组 getAttribute(); //获取属性 getModelAttribute(); + getModelAttributePublic(); //获取公共属性组 getModelConnectivity(); //获取连接性 } @@ -966,7 +967,7 @@ bool DataBase::getAttributeGroup() int id = query.value(0).toInt(); QString groupType = query.value(1).toString(); QString groupName = query.value(2).toString(); - int isPublic = query.value(3).toInt(); + int ispublic = query.value(3).toInt(); QString remark = query.value(4).toString(); if(!_attributeGroup.contains(id)) @@ -975,7 +976,7 @@ bool DataBase::getAttributeGroup() ag.id = id; ag.groupType = groupType; ag.groupName = groupName; - ag.isPublic = isPublic; + ag.ispublic = ispublic; ag.remark = remark; _attributeGroup.insert(id,ag); } @@ -1120,6 +1121,38 @@ bool DataBase::getModelAttribute() } } +bool DataBase::getModelAttributePublic() +{ + QString strSQL = "SELECT * FROM basic.model_attribute_public"; + + try + { + QSqlQuery query = executeSQL(strSQL); + while (query.next()) + { + int id = query.value(0).toInt(); + qint64 agi = query.value(1).toLongLong(); + qint64 ai = query.value(2).toLongLong(); + + if(!_modelAttributePublic.contains(id)) + { + modelAttributePublic ma; + ma.id = id; + ma.attributeGroupId = agi; + ma.attributeId = ai; + + _modelAttributePublic.insert(id,ma); + } + } + query.finish(); + return true; + } + catch (const std::exception& e) + { + return false; + } +} + bool DataBase::getAttribute() { QString strSQL = "SELECT * FROM basic.attribute"; @@ -1208,7 +1241,8 @@ bool DataBase::createProjectManager() meta_model VARCHAR(64) NOT NULL, group_name VARCHAR(64) NOT NULL, link_type integer NOT NULL DEFAULT 0, - check_state JSONB NOT NULL DEFAULT '{}'::jsonb + check_state JSONB NOT NULL DEFAULT '{}'::jsonb, + "ispublic" boolean NOT NULL DEFAULT false ); )"; @@ -1245,9 +1279,9 @@ bool DataBase::createProjectManager() }*/ } -bool DataBase::insertProjectManager(const QString& name,const QString& tag,const QString& metaModel,const QString& groupName,int linkType,QJsonObject checkState) +bool DataBase::insertProjectManager(const QString& name,const QString& tag,const QString& metaModel,const QString& groupName,int linkType,QJsonObject checkState,bool ispublic) { - QString strSQL = "INSERT INTO project_manager(name, tag, meta_model, group_name, link_type, check_state) VALUES (?, ?, ?, ?, ?, ?)"; + QString strSQL = "INSERT INTO project_manager(name, tag, meta_model, group_name, link_type, check_state, ispublic) VALUES (?, ?, ?, ?, ?, ?, ?)"; QJsonDocument checkDoc(checkState); QString strCheck = checkDoc.toJson(QJsonDocument::Compact); @@ -1258,6 +1292,7 @@ bool DataBase::insertProjectManager(const QString& name,const QString& tag,const params.append(groupName); params.append(linkType); params.append(strCheck); + params.append(ispublic); try { executeSQL(strSQL,false,params); @@ -1348,6 +1383,34 @@ QMap DataBase::getCheckStateFromManager(const QString& sPro } } +QMap DataBase::getPublicStateFromManager() +{ + QMap map; + bool ispublic = true; + + QString strSQL = "SELECT group_name, check_state FROM project_manager WHERE ispublic = ?"; + QVariantList params; + params.append(ispublic); + + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) + { + QString group = query.value(0).toString(); + QString state = query.value(1).toString(); + QJsonObject jsonObj = QstringToJson(state); + map.insert(group,jsonObj); + } + query.clear(); + return map; + } + catch (const std::exception& e) + { + return map; + } +} + QMap DataBase::getProjectTableName(const QString& sProject) { QMap map; @@ -1376,7 +1439,7 @@ QMap DataBase::getProjectTableName(const QString& sProject) QMap DataBase::getAllProjectModel() { QMap map; //工程模名,类型 - QString strSQL = "SELECT tag, MAX(link_type) AS link_type FROM project_manager GROUP BY tag"; + QString strSQL = "SELECT tag, MAX(link_type) AS link_type,ispublic FROM project_manager GROUP BY tag,ispublic"; try { @@ -1385,7 +1448,9 @@ QMap DataBase::getAllProjectModel() { QString tableName = query.value(0).toString(); int linkType = query.value(1).toInt(); - map.insert(tableName,linkType); + bool ispublic = query.value(2).toBool(); + if(!ispublic) + map.insert(tableName,linkType); } query.clear(); return map; @@ -1423,6 +1488,34 @@ QMap DataBase::getModelInfo(const QString& sProject) } } +QMap DataBase::getPublicInfo() +{ + QMap map; + bool ispublic = true; + QString strSQL = "SELECT group_name,name,check_state FROM project_manager WHERE ispublic = ?"; + QVariantList params; + params.append(ispublic); + + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) + { + propertyGroupState sta; + sta.groupName = query.value(0).toString(); + sta.tableName = query.value(1).toString(); + sta.propertyState = QstringToJson(query.value(2).toString()); + map.insert(sta.groupName,sta); + } + query.clear(); + return map; + } + catch (const std::exception& e) + { + return map; + } +} + QMap DataBase::getProjectModelGroupInfo(const QString& sTable) { QMap map; @@ -1476,11 +1569,15 @@ QMap DataBase::selectGroupProperty(const QString& table for(auto &proVal:mapPro) { propertyStateInfo pro; - if(proVal.name == "global_uuid") //剔除uuid所属的临时对象 + if(proVal.name == "global_uuid" && tableName != "baseProperty") //除基础属性组,其他组不显示uuid todo:组名适配 { uuid = QUuid(query.value(proVal.name).toString()); continue; } + else if(proVal.name == "global_uuid" && tableName == "baseProperty") + { + uuid = QUuid(query.value(proVal.name).toString()); + } pro.name = proVal.name; pro.type = proVal.type; pro.defaultValue = query.value(proVal.name ); @@ -1583,7 +1680,26 @@ bool DataBase::deleteProjectModel(const QString& sProject) LOG_ERROR("DB", QString("Delete row %1 failed").arg(sProject)); return false; } +} +bool DataBase::ifDynamicTableExist(const QString& sTable) +{ + QStringList lstTable; + QString strSQL = "SELECT name FROM project_manager WHERE name = ?"; + QVariantList params; + params.append(sTable); + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) + { + return true; + } + } + catch (const std::exception& e) + { + return false; + } } bool DataBase::updateProjectName(const QString& newTable,const QString& newPro,const QString& oldTable) diff --git a/diagramUtils/source/dataManager.cpp b/diagramUtils/source/dataManager.cpp index 442b16d..e48bcdf 100644 --- a/diagramUtils/source/dataManager.cpp +++ b/diagramUtils/source/dataManager.cpp @@ -21,10 +21,18 @@ DataManager::~DataManager() } -void DataManager::initialModelState() +void DataManager::initialModelState(bool refresh) { QMap model = DataBase::GetInstance()->getAllProjectModel(); + if(refresh) + { + for(auto &info:_modelStateInfo) + { + info.release(); + } + _modelStateInfo.clear(); + } QMap::Iterator iter; for(iter = model.begin();iter != model.end(); ++iter) //遍历模型 { @@ -33,8 +41,40 @@ void DataManager::initialModelState() modelInfo.modelName = iter.key(); QMap mapState = DataBase::GetInstance()->getModelInfo(iter.key()); + QMap mapPublic = DataBase::GetInstance()->getPublicInfo(); //公共属性组 QMap::Iterator it; + for(it = mapPublic.begin();it != mapPublic.end();++it) //遍历公共属性组 + { + groupStateInfo groupInfo; + groupInfo.groupName = it.key(); + groupInfo.tableName = it->tableName; + groupInfo.isPublic = true; + QJsonArray nodesJsonArray = it->propertyState["checkState"].toArray(); + + for (QJsonValueRef nodeJson : nodesJsonArray) //每个属性的状态信息 + { + propertyStateInfo propertyInfo; + + QJsonObject node = nodeJson.toObject(); + QString propertyName = node["name"].toString(); + int nState = node["checked"].toInt(); + QString dataType = node["type"].toString(); + QVariant defaultValue = node["defaultValue"].toVariant(); + int lengthPrecision = node["lengthPrecision"].toInt(); + if(nState) + { + propertyInfo.name = propertyName; + propertyInfo.type = dataType; + propertyInfo.defaultValue = defaultValue; + propertyInfo.lengthPrecision = lengthPrecision; + + groupInfo.info.insert(propertyName,propertyInfo); + } + } + modelInfo.groupInfo.insert(it.key(),groupInfo); + } + for(it = mapState.begin();it != mapState.end();++it) //遍历模型属性组 { groupStateInfo groupInfo; @@ -65,15 +105,19 @@ void DataManager::initialModelState() } modelInfo.groupInfo.insert(it.key(),groupInfo); } + _modelStateInfo.insert(iter.key(),modelInfo); } _stateInitialised = true; } -void DataManager::initialModelData() +void DataManager::initialModelData(bool refresh) { QMap model = DataBase::GetInstance()->getAllProjectModel(); - + if(refresh) + { + _modleDataInfo.clear(); + } QMap::Iterator iter; for(iter = model.begin();iter != model.end(); ++iter) //遍历模型 { @@ -82,8 +126,46 @@ void DataManager::initialModelData() modelInfo.modelName = iter.key(); QMap mapState = DataBase::GetInstance()->getModelInfo(iter.key()); - + QMap mapPublic = DataBase::GetInstance()->getPublicInfo(); //公共属性组 QMap::Iterator it; + + for(it = mapPublic.begin();it != mapPublic.end();++it) //遍历公共属性组 + { + groupStateValue groupValue; + groupValue.groupName = it.key(); + groupValue.tableName = it->tableName; + QJsonArray nodesJsonArray = it->propertyState["checkState"].toArray(); + + QMap mapPro; + for (QJsonValueRef nodeJson : nodesJsonArray) //每个属性的状态信息 + { + propertyStateInfo propertyInfo; + + QJsonObject node = nodeJson.toObject(); + QString propertyName = node["name"].toString(); + int nState = node["checked"].toInt(); + QString dataType = node["type"].toString(); + QVariant defaultValue = node["defaultValue"].toVariant(); + + propertyInfo.name = propertyName; + propertyInfo.type = dataType; + if(nState) + { + mapPro.insert(propertyName,propertyInfo); + } + } + if(!mapPro.contains("global_uuid")) //不包含uuid则手动添加 + { + propertyStateInfo uuidInfo; + uuidInfo.name = "global_uuid"; //全局id未添加到属性状态中,手动添加 + mapPro.insert("global_uuid",uuidInfo); + } + + groupValue.mapInfo = DataBase::GetInstance()->selectGroupProperty(it->tableName,mapPro); //返回表中属性值 + + modelInfo.groupInfo.insert(it.key(),groupValue); + } + for(it = mapState.begin();it != mapState.end();++it) //遍历模型属性组 { groupStateValue groupValue; @@ -135,6 +217,8 @@ ModleStateMap& DataManager::modelState() { if(!_stateInitialised) initialModelState(); + else + initialModelState(true); return _modelStateInfo; } @@ -142,5 +226,7 @@ ModelDataMap& DataManager::modelData() { if(!_dataInitialised) initialModelData(); + else + initialModelData(true); return _modleDataInfo; } diff --git a/include/electricElementsBox.h b/include/electricElementsBox.h index 95b2ab2..3a5ae10 100644 --- a/include/electricElementsBox.h +++ b/include/electricElementsBox.h @@ -26,6 +26,7 @@ signals: void addEletricItem(modelStateInfo&); public slots: void onSignal_addEletricItem(modelStateInfo&); + void onSignal_modelChanged(); private: ToolBox* m_pToolBox; QMap m_mapPanels; diff --git a/include/mainwindow.h b/include/mainwindow.h index 8359d76..fd651a5 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -19,6 +19,7 @@ class DiagramCavas; class ElectricElementsBox; class LoadPageDlg; class projectModelDlg; +class TopologyView; class CMainWindow : public QMainWindow { @@ -66,6 +67,7 @@ private: DiagramCavas* m_pDiagramCavas; DrawingPanel* m_pDrawingPanel; ElectricElementsBox* m_pElectricElementsBox; + TopologyView* m_pTopologyView; GraphicElementsPanel* m_pGraphicElementsPanel; LoadPageDlg* m_pLoadPageDlg; projectModelDlg* m_pProjectModelDlg; diff --git a/include/projectModelDlg.h b/include/projectModelDlg.h index d1fd740..a9db8e9 100644 --- a/include/projectModelDlg.h +++ b/include/projectModelDlg.h @@ -30,11 +30,13 @@ struct PropertyState //每个属性的状态 { bool checkState = false; QString dataType; + bool editable = true; //可勾选状态 }; struct PropertyPage //属性信息 { QMap mCheckState; //属性选择状态 + bool isPublic = false; }; typedef QMap MapProperty; //属性组 @@ -85,7 +87,9 @@ public slots: public: QStringList getModelList() const; //获取元模型列表 QStringList getGroupList(const QString& model) const; //返回该元模下的属性组列表 + QStringList getPublicGroupList() const; //返回公共属性组列表 QStringList getAttributeList(const QString& model,const QString& group) const; //根据元模名和组名返回属性列表 + QStringList getPublicAttributeList(const QString& group); //返回公共属性组的属性列表 void setItemAttribute(const QString&,QStandardItem*); //设置item的属性(数据库表字段名) QPair combinePropertySql(const QStandardItem*); //根据item属性生成sql QString getProjectName() const; //返回当前选择项目的名称 @@ -94,21 +98,25 @@ public: QString modifyProjectModel(QMap); //修改工程模 bool renameProjectModel(const QString& strCur,QMap datas); //重命名工程模 void updateComponentModelName(const QString& strOld,const QString& strNew); //更新component中的工程模 +signals: + void modelChange(); //模型改变信号 private: //void updateIconList(); //选择工程模后刷新关联图标 void removeProjectData(const QString&,const QString&,int role); //移除对应的project层级结构 QString getItemDataType(const QStandardItem* pItem); //返回数据类型 - bool createPropertyTable(const QString& sProject,const QString& sGroup,QList lstSelect,QList lstBase,int nLinkType); //创建属性组表并插入记录到管理表(工程名,当前项迭代器,关联图元类型) + int createPropertyTable(const QString& sProject,const QString& sGroup,QList lstSelect,QList lstBase,int nLinkType,bool isPublic = false); //创建属性组表并插入记录到管理表(工程名,当前项迭代器,关联图元类型) QJsonObject getSelectedState(QList select,QList base); //返回json格式的选中状态 QList getGroupSub(QStandardItemModel*,const QString&); //返回指定组下的属性(如果存在) void setupUI(); void initialTypeMap(); - int getLevel(QStandardItem *item); //返回当前item所在层级,0为根 + projectState couldSave(); void setTableItemState(int row,TableItemState state); //设置状态 int getModelEditState(); //返回工程模编辑状态(选择、编辑、新建) + + bool ifProjectExsit(const QString&); //判断工程模存在 private: Ui::projectModelDlg *ui; MapMeta m_mapTotal; diff --git a/include/topologyView.h b/include/topologyView.h new file mode 100644 index 0000000..628be5b --- /dev/null +++ b/include/topologyView.h @@ -0,0 +1,36 @@ +#ifndef TOPOLOGYVIEW_H +#define TOPOLOGYVIEW_H + +#include +#include +#include "global.h" + +QT_BEGIN_NAMESPACE +namespace Ui { class topologyView; } +QT_END_NAMESPACE + + +class TopologyView : public QDialog +{ + Q_OBJECT + +public: + TopologyView(QWidget *parent = nullptr); + ~TopologyView(); + + void initial(); +signals: + void entityCreate(EntityInfo); + void entityChange(EntityInfo); + void entityDelete(EntityInfo); + void entitySelected(EntityInfo); +public slots: + void onIndexRbtnClicked(const QPoint &pos); //索引列表右键菜单 + void onItemChanged(QStandardItem *item); + void onItemClicked(const QModelIndex &index); +private: + Ui::topologyView *ui; + QStandardItemModel* _pModel; +}; + +#endif diff --git a/source/electricElementsBox.cpp b/source/electricElementsBox.cpp index 44e87de..8dceaff 100644 --- a/source/electricElementsBox.cpp +++ b/source/electricElementsBox.cpp @@ -59,11 +59,26 @@ void ElectricElementsBox::updateModelList() for(auto &model:_modelInfo) { GraphicsItemType localType = corresbondItem::linkType[(AbstractItemType)model.modelType]; + model.modelType = localType; + } + + if(!m_mapPanels.isEmpty()) //暂时1个类别 + { + QMap::iterator it = m_mapPanels.begin(); + if(it != m_mapPanels.end()) + { + it.value()->setData(_modelInfo); + } } } void ElectricElementsBox::onSignal_addEletricItem(modelStateInfo& info) { emit addEletricItem(info); - +} + +void ElectricElementsBox::onSignal_modelChanged() +{ + getModelInfo(); + updateModelList(); } diff --git a/source/electricElementsPanel.cpp b/source/electricElementsPanel.cpp index d2ad596..590665d 100644 --- a/source/electricElementsPanel.cpp +++ b/source/electricElementsPanel.cpp @@ -39,6 +39,8 @@ void ElectricElementsPanel::initial() void ElectricElementsPanel::setData(QMap map) { + if(m_pListWidget->count() != 0) + m_pListWidget->clear(); m_mapEleData = map; initial(); } diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 1257bc1..ca01e71 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -23,6 +23,7 @@ #include "toolBox.h" #include "loadPageDlg.h" #include "projectModelDlg.h" +#include "topologyView.h" //using namespace ads; @@ -34,6 +35,7 @@ CMainWindow::CMainWindow(QWidget *parent) ui->setupUi(this); m_pUndoStack = nullptr; m_pLoadPageDlg = nullptr; + m_pTopologyView = nullptr; initializeDockUi(); initializeAction(); @@ -72,12 +74,21 @@ void CMainWindow::initializeDockUi() ElectricElementsDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); this->addDockWidget(Qt::RightDockWidgetArea,ElectricElementsDock); + m_pTopologyView = new TopologyView(this); + m_pTopologyView->initial(); + QDockWidget* topologyDock = new QDockWidget(QString::fromWCharArray(L"拓扑关系"),this); + topologyDock->setWidget(m_pTopologyView); + topologyDock->setMinimumSize(120,550); + topologyDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); + this->addDockWidget(Qt::LeftDockWidgetArea,topologyDock); + m_pDiagramCavas = new DiagramCavas(); m_pDiagramCavas->initial(); this->setCentralWidget(m_pDiagramCavas); connect(m_pElectricElementsBox,&ElectricElementsBox::addEletricItem,m_pDiagramCavas,&DiagramCavas::onSignal_addGraphicsItem); m_pProjectModelDlg = new projectModelDlg(this); + connect(m_pProjectModelDlg,&projectModelDlg::modelChange,m_pElectricElementsBox,&ElectricElementsBox::onSignal_modelChanged); } void CMainWindow::initializeAction() @@ -104,6 +115,11 @@ void CMainWindow::initializeAction() connect(ui->actionGroup, SIGNAL(triggered()), this, SLOT(onAction_createGroup())); connect(ui->actionUngroup, SIGNAL(triggered()), this, SLOT(onAction_destroyGroup())); + connect(m_pTopologyView,&TopologyView::entityCreate,m_pDiagramCavas,&DiagramCavas::onSignal_createEntity); + connect(m_pTopologyView,&TopologyView::entityChange,m_pDiagramCavas,&DiagramCavas::onSignal_changeEntity); + connect(m_pTopologyView,&TopologyView::entityDelete,m_pDiagramCavas,&DiagramCavas::onSignal_deleteEntity); + connect(m_pTopologyView,&TopologyView::entitySelected,m_pDiagramCavas,&DiagramCavas::onSignal_selectEntity); + connect(ui->actionNew,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onSignal_addPage); connect(ui->actionOpen,&QAction::triggered,this,&CMainWindow::onSignal_loadPage); connect(ui->actionSave,&QAction::triggered,m_pDiagramCavas,&DiagramCavas::onSignal_savePage); @@ -191,7 +207,7 @@ void CMainWindow::onSignal_loadPage() if(m_pLoadPageDlg == nullptr) { m_pLoadPageDlg = new LoadPageDlg(this); - connect(m_pLoadPageDlg,&LoadPageDlg::selectedPage,m_pDiagramCavas,&DiagramCavas::onSignal_loadPage); + //connect(m_pLoadPageDlg,&LoadPageDlg::selectedPage,m_pDiagramCavas,&DiagramCavas::onSignal_loadPage); } m_pLoadPageDlg->updateList(); m_pLoadPageDlg->show(); diff --git a/source/projectModelDlg.cpp b/source/projectModelDlg.cpp index 341008e..cc3548d 100644 --- a/source/projectModelDlg.cpp +++ b/source/projectModelDlg.cpp @@ -7,6 +7,7 @@ #include "dataBase.h" #include "global.h" #include "projectTableDelegate.h" +#include "logger.h" const QSet stringDataTypes = {"varchar", "char", "text", "date", "time", "timestamp"}; @@ -54,6 +55,7 @@ MapProperty projectModelDlg::addNewProject(const QString& sMeta,const QString& s { MapProperty mt; QStringList lstProperty = getGroupList(sMeta); //返回元模下的属性组名 + QStringList lstProPublic = getPublicGroupList(); //返回公共属性组 //lstProperty< mapCheckState = DataBase::GetInstance()->getCheckStateFromManager(sProject); //获取选择状态 @@ -140,7 +142,39 @@ MapProperty projectModelDlg::addNewProject(const QString& sMeta,const QString& s mt.insert(property,struProperty); } - return mt; + MapProperty pubMap; + for(auto &pro:lstProPublic) //公共属性组 + { + PropertyPage struProperty; + struProperty.isPublic = true; + + QStandardItem* pGroup = nullptr; + pGroup = new QStandardItem(pro); + //model.pSelect->appendRow(pGroup); //公共属性组默认都包含 + model.pSelect->insertRow(0,pGroup); + + QStringList lstName = getPublicAttributeList(pro); + for(auto &name:lstName) + { + QStandardItem* pItem = new QStandardItem(name); + pItem->setData(QColor(60,140,180,180), Qt::BackgroundRole); + setItemAttribute(name,pItem); + pGroup->appendRow(pItem); + QString dataType = getItemDataType(pItem); + PropertyState sta; + sta.dataType = dataType; + sta.checkState = true; + sta.editable = false; + struProperty.mCheckState.insert(name,sta); //初始都已经选择 + } + pubMap.insert(pro,struProperty); + } + + for (auto it = mt.begin(); it != mt.end(); ++it) { //将正常属性添到公共属性后 + pubMap.insert(it.key(), it.value()); + } + + return pubMap; } void projectModelDlg::initialModel() @@ -155,7 +189,7 @@ void projectModelDlg::initialModel() QMap::Iterator iter; for(iter = mapProject.begin();iter != mapProject.end(); ++iter) { - QStandardItem* propertyItem = new QStandardItem(iter.key()); + //QStandardItem* propertyItem = new QStandardItem(iter.key()); PropertyModel pm; pm.pBase = new QStandardItemModel(this); @@ -223,30 +257,38 @@ void projectModelDlg::generate(const QString& str) { MapProperty mapProperty = ite.value().mapProperty; - bool createRes = true; //动态表生成结果 + int createRes = 0; //动态表生成结果 for(MapProperty::Iterator it = mapProperty.begin();it != mapProperty.end();++it){ //每个属性组单独生成表 int nType = ite.value().nType; QStandardItemModel* pSelectModel = ite->pSelect; QStandardItemModel* pBaseModel = ite->pBase; - /*QStandardItem *rootItem = pSelectModel->invisibleRootItem(); - if(rootItem->rowCount() == 0) //修改逻辑,未勾选的属性组不生成表 by/20250311 - continue;*/ + QList lstSelected = getGroupSub(pSelectModel,it.key()); QList lstBase = getGroupSub(pBaseModel,it.key()); if(!lstSelected.isEmpty()) { - bool res = createPropertyTable(str,it.key(),lstSelected,lstBase,nType); - createRes = createRes && res; + bool isPub = it->isPublic; + int res = createPropertyTable(str,it.key(),lstSelected,lstBase,nType,isPub); + switch (res){ + case int(AlertInfo::success): + LOG_INFO("DB", QString("create %1 dynamicTable success").arg(str)); + break; + case int(AlertInfo::fail): + LOG_WARN("DB", QString("create %1 dynamicTable fail").arg(str)); + break; + case int(AlertInfo::exist): + LOG_WARN("DB", QString("%1 dynamicTable exist").arg(str)); + break; + default: + break; + } + createRes = createRes | res; } } - if(createRes) + if(!(createRes & int(AlertInfo::fail))) //结果不含失败就成功 { - /*PropertyModel pm = m_mapTotal[_curMeta].take(_curProject); //取出要保存的对象,另存为新索引 - m_mapTotal[_curMeta].insert(str,pm); - - _curProject = str;*/ QMessageBox::information(NULL, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"创建表成功")); - + emit modelChange(); } else //创建失败 { @@ -347,6 +389,7 @@ void projectModelDlg::onSaveClicked() { QMessageBox::information(NULL, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"修改模型成功")); setTableItemState(_curRow,TS_select); + emit modelChange(); } else { @@ -378,6 +421,7 @@ void projectModelDlg::onSaveClicked() { QMessageBox::information(NULL, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"修改模型成功")); setTableItemState(_curRow,TS_select); + emit modelChange(); } else { @@ -497,6 +541,7 @@ void projectModelDlg::onApplyClicked() void projectModelDlg::onRevokeClicked() { + QStringList lstPub = getPublicGroupList(); MapMeta::Iterator iter = m_mapTotal.find(_curMeta); if(iter != m_mapTotal.end()) { @@ -510,6 +555,10 @@ void projectModelDlg::onRevokeClicked() if(pItem) { + if(lstPub.contains(pItem->parent()->text())){ + QMessageBox::information(NULL, QString("提示"), QString::fromWCharArray(L"公共属性无法编辑")); + return; + } int nLevel = getLevel(pItem); if(nLevel != 1) //不是二级节点就返回 return; @@ -937,6 +986,14 @@ void projectModelDlg::onDelegateFinishEdit(const QModelIndex &index, const QStri int col = index.column(); if(col == TD_ProjectModel) { + if(ifProjectExsit(value)) + { + QMessageBox::information(NULL, QString::fromWCharArray(L"提示"), QString::fromWCharArray(L"模型名已存在")); + QTableWidgetItem* pItem = ui->tableWidget_model->item(index.row(),index.column()); + if(pItem) + pItem->setText(QString::fromWCharArray(L"未命名")); + return; + } if(m_mapTotal.contains(_curMeta)) //判断元模存在 { if(m_mapTotal[_curMeta].contains(_curProject)) //已经存在 @@ -1120,6 +1177,25 @@ QStringList projectModelDlg::getGroupList(const QString& sM) const return groupList; } +QStringList projectModelDlg::getPublicGroupList() const +{ + QMap modelAttPublic = DataBase::GetInstance()->ModelAttributePublic(); + QMap groupMap = DataBase::GetInstance()->AttributeGroup(); + + QSet setGroup; + for(auto &model:modelAttPublic) + { + setGroup.insert(model.attributeGroupId); + } + + QStringList groupList; + for(auto &id:setGroup) + { + groupList.append(groupMap[id].groupType); + } + return groupList; +} + QStringList projectModelDlg::getAttributeList(const QString& sM,const QString& sG) const { QMap modelType = DataBase::GetInstance()->ModelType(); @@ -1160,6 +1236,34 @@ QStringList projectModelDlg::getAttributeList(const QString& sM,const QString& s return lst; } +QStringList projectModelDlg::getPublicAttributeList(const QString& group) +{ + QMap modelAttPublic = DataBase::GetInstance()->ModelAttributePublic(); + QMap groupMap = DataBase::GetInstance()->AttributeGroup(); + QMap attMap = DataBase::GetInstance()->Attribute(); + + int groupId = -1; + for(auto &attGroup:groupMap) + { + if(attGroup.groupType == group) //返回参数属性组名对应的id + { + groupId = attGroup.id; + break; + } + } + + QStringList lst; + for(auto &mt:modelAttPublic) + { + if(mt.attributeGroupId == groupId) + { + lst.append(attMap[mt.attributeId].attribute); + } + } + + return lst; +} + void projectModelDlg::setItemAttribute(const QString& name,QStandardItem* p) { QMap attMap = DataBase::GetInstance()->Attribute(); @@ -1251,6 +1355,8 @@ bool projectModelDlg::ifProjectEqual(QMap map) QMap::Iterator iter; for(iter = curPro.begin();iter != curPro.end();++iter) { + if(iter->isPublic) //公共组跳过判断 + continue; if(!map.contains(iter.key())) //已存在的模型中不包含该属性组 { QMap curCheckState = iter.value().mCheckState; @@ -1437,31 +1543,68 @@ QString projectModelDlg::getItemDataType(const QStandardItem* pItem) return dataTypePart; } -bool projectModelDlg::createPropertyTable(const QString& sProject,const QString& sGroup,QList lstSelect,QList lstBase,int nLinkType) +int projectModelDlg::createPropertyTable(const QString& sProject,const QString& sGroup,QList lstSelect,QList lstBase,int nLinkType,bool isPublic) { - QString sName = _curMeta + QString("_") + sProject + QString("_")+sGroup; - - QStringList fields; - fields.append("id SERIAL NOT NULL PRIMARY KEY"); - fields.append("global_uuid uuid NOT NULL DEFAULT gen_random_uuid()"); - fields.append("attribute_group VARCHAR(64) NOT NULL"); - - for(auto &item:lstSelect) + if(!isPublic) { - QPair pair = combinePropertySql(item); //拼接单句sql - fields.append(pair.first); - } + QString sName = _curMeta + QString("_") + sProject + QString("_")+sGroup; - QJsonObject objState = getSelectedState(lstSelect,lstBase); + QStringList fields; + fields.append("id SERIAL NOT NULL PRIMARY KEY"); + fields.append("global_uuid uuid NOT NULL DEFAULT gen_random_uuid()"); + fields.append("attribute_group VARCHAR(64) NOT NULL"); - if(!DataBase::GetInstance()->createDynamicTable(sName,fields)) - { - return false; + for(auto &item:lstSelect) + { + QPair pair = combinePropertySql(item); //拼接单句sql + fields.append(pair.first); + } + + QJsonObject objState = getSelectedState(lstSelect,lstBase); + + if(!DataBase::GetInstance()->createDynamicTable(sName,fields)) + { + return int(AlertInfo::fail); + } + else + { + DataBase::GetInstance()->insertProjectManager(sName,sProject,_curMeta,sGroup,nLinkType,objState); + return int(AlertInfo::success); + } } else { - DataBase::GetInstance()->insertProjectManager(sName,sProject,_curMeta,sGroup,nLinkType,objState); - return true; + QString sName = sGroup; + + QStringList fields; + fields.append("id SERIAL NOT NULL PRIMARY KEY"); + fields.append("global_uuid uuid NOT NULL DEFAULT gen_random_uuid()"); + fields.append("attribute_group VARCHAR(64) NOT NULL"); + + for(auto &item:lstSelect) + { + QPair pair = combinePropertySql(item); //拼接单句sql + fields.append(pair.first); + } + + QJsonObject objState = getSelectedState(lstSelect,lstBase); + + if(!DataBase::GetInstance()->ifDynamicTableExist(sName)) + { + bool val = DataBase::GetInstance()->createDynamicTable(sName,fields); + if(val) + { + DataBase::GetInstance()->insertProjectManager(sName,sName,"NULL",sGroup,0,objState,true); + return int(AlertInfo::success); + } + else { + return int(AlertInfo::fail); + } + } + else + { + return int(AlertInfo::exist); + } } } @@ -1569,22 +1712,6 @@ void projectModelDlg::initialTypeMap() _mapType.insert(QString::fromWCharArray(L"异步电动机"),3); } -int projectModelDlg::getLevel(QStandardItem *item) { - int level = 0; - QStandardItem *parent = item->parent(); - if(parent) - { - while (parent) { - level++; - parent = parent->parent(); - } - return level; - } - else{ - return -1; - } - -} projectState projectModelDlg::couldSave() { @@ -1632,3 +1759,15 @@ int projectModelDlg::getModelEditState() } return res; } + +bool projectModelDlg::ifProjectExsit(const QString& sPro) +{ + for(auto &meta:m_mapTotal) + { + if(meta.contains(sPro)) + { + return true; + } + } + return false; +} diff --git a/source/topologyView.cpp b/source/topologyView.cpp new file mode 100644 index 0000000..7daee6b --- /dev/null +++ b/source/topologyView.cpp @@ -0,0 +1,243 @@ +#include "topologyView.h" +#include "ui_topologyView.h" +#include "tools.h" +#include +#include +#include + + +TopologyView::TopologyView(QWidget *parent) + : QDialog(parent) + , ui(new Ui::topologyView) + ,_pModel(nullptr) +{ + ui->setupUi(this); + //setWindowFlags(windowFlags() | Qt::WindowMinMaxButtonsHint&Qt::WindowCloseButtonHint); + _pModel = new QStandardItemModel(this); + ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); +} + +TopologyView::~TopologyView() +{ + delete ui; +} + +void TopologyView::initial() +{ + connect(ui->treeView, &QTreeView::customContextMenuRequested, this, &TopologyView::onIndexRbtnClicked); + connect(ui->treeView, &QTreeView::clicked, this, &TopologyView::onItemClicked); + connect(_pModel, &QStandardItemModel::itemChanged, this, &TopologyView::onItemChanged); + ui->treeView->setHeaderHidden(true); + // 设置模型的列数 + _pModel->setColumnCount(1); + + // 设置模型的标题 + //_pModel->setHeaderData(0, Qt::Horizontal, QObject::tr("层级")); + + // 创建根节点 + QStandardItem *rootItem = new QStandardItem("电网"); + rootItem->setFlags(rootItem->flags() & ~Qt::ItemIsEditable); + _pModel->appendRow(rootItem); + + // 创建树视图 + ui->treeView->setModel(_pModel); + + // 展开所有节点 + ui->treeView->expandAll(); + // 显示树视图 + ui->treeView->setWindowTitle(QObject::tr("拓扑树")); +} + +void TopologyView::onIndexRbtnClicked(const QPoint &pos) +{ + // 获取当前点击的位置对应的索引 + QModelIndex index = ui->treeView->indexAt(pos); + if (!index.isValid()) { + return; // 如果点击的是空白区域,直接返回 + } + + QMenu menu; + QStandardItem* item = _pModel->itemFromIndex(index); + + if(item) + { + int nCount = item->rowCount(); + int nLevel = getLevel(item); + if(nLevel == -1) //根节点 + { + QAction *addAction = new QAction("添加电网", this); + + connect(addAction,&QAction::triggered,this,[&](){ + QString uuid = QUuid::createUuid().toString(); + QStandardItem *gridItem = new QStandardItem(QString("电网_")+QString::number(nCount)); + gridItem->setData(uuid,Qt::UserRole+1); + gridItem->setData(int(EntityType::Grid),Qt::UserRole+2); + item->appendRow(gridItem); + + EntityInfo info; + info.eType = EntityType::Grid; + info.sName = gridItem->text(); + info.sUuid = uuid; + emit entityCreate(info); + }); + + menu.addAction(addAction); + } + else if(nLevel == 1) //grid + { + QAction *addAction = new QAction("添加区域", this); + QString sParentid = item->data(Qt::UserRole+1).toString(); + + connect(addAction,&QAction::triggered,this,[&](){ + QString uuid = QUuid::createUuid().toString(); + QStandardItem *zoneItem = new QStandardItem(QString("区域_")+QString::number(nCount)); + zoneItem->setData(uuid,Qt::UserRole+1); + zoneItem->setData(int(EntityType::Zone),Qt::UserRole+2); + item->appendRow(zoneItem); + + EntityInfo info; + info.eType = EntityType::Zone; + info.sName = zoneItem->text(); + info.sParentId = sParentid; + info.sUuid = uuid; + emit entityCreate(info); + + ui->treeView->expandAll(); + }); + + menu.addAction(addAction); + } + else if(nLevel == 2) //zone + { + QAction *addAction = new QAction("添加场站", this); + QString sParentid = item->data(Qt::UserRole+1).toString(); + + connect(addAction,&QAction::triggered,this,[&](){ + QString uuid = QUuid::createUuid().toString(); + QStandardItem *stationItem = new QStandardItem(QString("场站_")+QString::number(nCount)); + stationItem->setData(uuid,Qt::UserRole+1); + stationItem->setData(int(EntityType::Station),Qt::UserRole+2); + item->appendRow(stationItem); + + EntityInfo info; + info.eType = EntityType::Station; + info.sName = stationItem->text(); + info.sUuid = uuid; + info.sParentId = sParentid; + emit entityCreate(info); + + ui->treeView->expandAll(); + }); + + menu.addAction(addAction); + } + else if(nLevel == 3) //station + { + QAction *addAction = new QAction("添加组态图", this); + QString sParentid = item->data(Qt::UserRole+1).toString(); + + connect(addAction,&QAction::triggered,this,[&](){ + QString uuid = QUuid::createUuid().toString(); + QStandardItem *diagramItem = new QStandardItem(QString("组态图_")+QString::number(nCount)); + diagramItem->setData(uuid,Qt::UserRole+1); + diagramItem->setData(int(EntityType::ConfigurationDiagram),Qt::UserRole+2); + item->appendRow(diagramItem); + + EntityInfo info; + info.eType = EntityType::ConfigurationDiagram; + info.sName = diagramItem->text(); + info.sUuid = uuid; + info.sParentId = sParentid; + emit entityCreate(info); + + ui->treeView->expandAll(); + }); + + menu.addAction(addAction); + } + else if(nLevel == 4) //组态图 + { + QAction *addAction = new QAction("添加子组态图", this); + QString sText = item->text(); + QString sParentid = item->data(Qt::UserRole+1).toString(); + connect(addAction,&QAction::triggered,this,[&](){ + QString uuid = QUuid::createUuid().toString(); + QStandardItem *diagramItem = new QStandardItem(sText+QString("_")+QString::number(nCount)); + diagramItem->setData(uuid,Qt::UserRole+1); + diagramItem->setData(int(EntityType::ConfigurationDiagram),Qt::UserRole+2); + item->appendRow(diagramItem); + + EntityInfo info; + info.eType = EntityType::ConfigurationDiagram; + info.sName = diagramItem->text(); + info.sUuid = uuid; + info.sParentId = sParentid; + emit entityCreate(info); + + ui->treeView->expandAll(); + }); + + menu.addAction(addAction); + } + + if(nLevel != -1) //除了根节点其余都能删除 + { + QAction *delAction = new QAction("删除", this); + connect(delAction,&QAction::triggered,this,[&](){ + QModelIndex currentIndex = ui->treeView->currentIndex(); + if(currentIndex.isValid()) + { + QStandardItem* pItem = _pModel->itemFromIndex(currentIndex); + if(pItem) + { + 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 entityDelete(info); + + QStandardItem* pParent = item->parent(); + if(pParent) + { + pParent->removeRow(currentIndex.row()); + } + } + } + }); + menu.addAction(delAction); + } + } + + // 在点击位置显示菜单 + menu.exec(ui->treeView->mapToGlobal(pos)); +} + +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 = _pModel->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); + } + } +} diff --git a/ui/topologyView.ui b/ui/topologyView.ui new file mode 100644 index 0000000..f92ce13 --- /dev/null +++ b/ui/topologyView.ui @@ -0,0 +1,37 @@ + + + topologyView + + + + 0 + 0 + 182 + 442 + + + + + 0 + 0 + + + + Dialog + + + + + + + 170 + 430 + + + + + + + + +