diff --git a/common/include/baseProperty.h b/common/include/baseProperty.h index f48b0cd..5214c54 100644 --- a/common/include/baseProperty.h +++ b/common/include/baseProperty.h @@ -121,6 +121,17 @@ protected: bool _prepareDelete; //状态,为真准备删除 }; +class DiagramEditorItemProperty:public ModelProperty //基模编辑中预览元件的属性 +{ +public: + DiagramEditorItemProperty(QObject* parent); + virtual ~DiagramEditorItemProperty(); + void setBlock(const QString& s) {sBlock = s;} + QString getBlock(){return sBlock;} +private: + QString sBlock; //所属的block(跨间隔连线等可能无此值) +}; + class BaseProperty; class BaseModelProperty:public ModelProperty //图像基模属性 { diff --git a/common/include/global.h b/common/include/global.h index 8e4e5a0..1d6c3f2 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -35,6 +35,7 @@ enum GraphicsItemType GIT_link= QGraphicsItem::UserType + 53, GIT_bay= QGraphicsItem::UserType + 54, //间隔 //====================================== + GIT_baseNode = QGraphicsItem::UserType + 199, GIT_baseBus = QGraphicsItem::UserType + 200, GIT_baseLine = QGraphicsItem::UserType + 201, GIT_baseBreaker = QGraphicsItem::UserType + 202 @@ -49,7 +50,9 @@ enum AbstractItemType //工程模关联的对象类型 enum class ModelFunctionType //模型函数的类型 { ProjectModel = 0, - BaseModel + BaseModel, + EditorModel, + BlockEditorModel //模块划分时的连接关系 }; @@ -449,12 +452,17 @@ struct DiagramEditorComponentInfo //组态设备信息 int nType = 0; //类型 1母线2异步电动机3断路器4电缆5电流互感器6电压互感器7隔离开关8接地开关9快速接地开关10双掷接地隔离开关11带电指示器12避雷器13电缆出线套筒14电缆端 QString sBindObj; //所关联的实体名 (母线block,间隔block) QStringList sUsedRoute; //使用设备的线路名 + int nUsedDirection = 0; //被占用的方向 8421 上下左右 + QPoint deltaPos = QPoint(0,0); //相对坐标(相对间隔) }; struct DiagramEditorBayRouteInfo //间隔中单条线路信息 { QString sRouteName; - QMap mapCompo; + bool bMainRoute = false; //主线路(包含设备最多的线路,决定整体布局) + QList lstCompo; + QList lstOrder; //线路顺序容器(计算用) + QList lstReverse; //逆序容器(计算用) }; enum class DiagramEditorStructType diff --git a/common/include/tools.h b/common/include/tools.h index 7f4c070..dbd7a90 100644 --- a/common/include/tools.h +++ b/common/include/tools.h @@ -75,4 +75,5 @@ QStandardItem* deepCloneItem(const QStandardItem* source); // 深拷贝整个模型(不复制表头) QStandardItemModel* deepCloneModel(const QStandardItemModel* source); + #endif // DATABASE_H diff --git a/common/source/baseProperty.cpp b/common/source/baseProperty.cpp index 43a88f0..5bd4b05 100644 --- a/common/source/baseProperty.cpp +++ b/common/source/baseProperty.cpp @@ -25,6 +25,17 @@ ModelProperty::~ModelProperty() } +/*****************************组态编辑预览item*********************************/ +DiagramEditorItemProperty::DiagramEditorItemProperty(QObject* parent) + :ModelProperty(parent) +{ + +} +DiagramEditorItemProperty::~DiagramEditorItemProperty() +{ + +} + /*****************************基模*********************************/ BaseModelProperty::BaseModelProperty(QObject* parent) : ModelProperty(parent) diff --git a/diagramCavas/CMakeLists.txt b/diagramCavas/CMakeLists.txt index f8cce46..ec147f6 100644 --- a/diagramCavas/CMakeLists.txt +++ b/diagramCavas/CMakeLists.txt @@ -43,8 +43,10 @@ set(DIAGRAMCAVAS_HEADER_FILES include/diagramEditor/diagramEditorBayDetailSettingDlg.h include/diagramEditor/diagramEditorBayDetailAddDlg.h include/diagramEditor/diagramEditorTransSettingDlg.h + include/diagramEditor/diagramEditorBayPreviewDlg.h include/graphicsDataModel/baseModel.h include/graphicsDataModel/fixedPortsModel.h + include/graphicsDataModel/diagramEditorModel.h include/graphicsItem/electricConnectLineItem.h include/graphicsItem/electricSvgItem.h include/graphicsItem/electricSvgItemBus.h @@ -62,6 +64,7 @@ set(DIAGRAMCAVAS_HEADER_FILES include/baseModelItem/electricBaseModelSvgItem.h include/baseModelItem/electricBaseModelLineItem.h include/baseModelItem/electricBaseModelSvgBus.h + include/baseModelItem/electricBaseModelPortItem.h include/util/baseSelector.h include/util/connectingSelector.h include/util/creatingSelector.h @@ -123,8 +126,10 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/diagramEditor/diagramEditorBayDetailSettingDlg.cpp source/diagramEditor/diagramEditorBayDetailAddDlg.cpp source/diagramEditor/diagramEditorTransSettingDlg.cpp + source/diagramEditor/diagramEditorBayPreviewDlg.cpp source/graphicsDataModel/baseModel.cpp source/graphicsDataModel/fixedPortsModel.cpp + source/graphicsDataModel/diagramEditorModel.cpp source/graphicsItem/electricConnectLineItem.cpp source/graphicsItem/electricSvgItem.cpp source/graphicsItem/electricSvgItemBus.cpp @@ -142,6 +147,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/baseModelItem/electricBaseModelSvgItem.cpp source/baseModelItem/electricBaseModelLineItem.cpp source/baseModelItem/electricBaseModelSvgBus.cpp + source/baseModelItem/electricBaseModelPortItem.cpp source/util/baseSelector.cpp source/util/connectingSelector.cpp source/util/creatingSelector.cpp diff --git a/diagramCavas/include/baseModelItem/electricBaseModelPortItem.h b/diagramCavas/include/baseModelItem/electricBaseModelPortItem.h new file mode 100644 index 0000000..916b750 --- /dev/null +++ b/diagramCavas/include/baseModelItem/electricBaseModelPortItem.h @@ -0,0 +1,21 @@ +#ifndef ELECTRICBASEMODELPORTITEM_H +#define ELECTRICBASEMODELPORTITEM_H + +#include "graphicsItem/graphicsBaseItem.h" + +class ElectricBaseModelPortItem :public GraphicsBaseModelItem +{ + Q_OBJECT +public: + ElectricBaseModelPortItem(QGraphicsItem *parent = 0); + virtual ~ElectricBaseModelPortItem(); + + void addPort(); +public: + virtual void updateConnectData(); +protected: + virtual QRectF boundingRect() const override; + virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); +}; + +#endif diff --git a/diagramCavas/include/diagramEditor/diagramEditorBayDetailSettingDlg.h b/diagramCavas/include/diagramEditor/diagramEditorBayDetailSettingDlg.h index 5ddff76..57fdfdf 100644 --- a/diagramCavas/include/diagramEditor/diagramEditorBayDetailSettingDlg.h +++ b/diagramCavas/include/diagramEditor/diagramEditorBayDetailSettingDlg.h @@ -11,6 +11,8 @@ QT_END_NAMESPACE class DiagramEditorWizard; class DiagramEditorBayDetailAddDlg; class DiagramEditorBayBlock; +class DiagramEditorBayPreviewDlg; +class DiagramEditorModel; class DiagramEditorBayDetailSettingDlg : public QDialog { @@ -27,6 +29,8 @@ public: QStandardItemModel* getRouteModel() {return _routeModel;} void setRouteMap(QMap map) {_mapRouteInfo = map;} QMap& getRouteMap(){return _mapRouteInfo;} + void setModelDelegate(DiagramEditorModel* p){_pModel = p;} + DiagramEditorModel* getModel() {return _pModel;} public slots: void onAddClicked(); void onOkClicked(); @@ -35,14 +39,17 @@ public slots: void onRouteDeleteClicked(); void onRouteRbtnClicked(const QPoint &pos); //线路右键菜单 void onRouteEditClicked(); + void onPreviewClicked(); //预览间隔 private: Ui::diagramEditorBayDetailSettingDlg *ui; DiagramEditorBayDetailAddDlg* _pAddDlg; + DiagramEditorBayPreviewDlg* _pPreviewDlg; DiagramEditorWizard* _pWizard; DiagramEditorBayBlock* _curOperateObj; //当前加载的block对象 - QStandardItemModel* _compoModel; //设备库model + QStandardItemModel* _compoModel; //设备库model name中的data:1为占用方向,2为相对坐标,3为uuid,4为item创建标志位,5旋转角度 QStandardItemModel* _routeModel; //所有线路model QMap _mapRouteInfo; //所有线路信息 + DiagramEditorModel* _pModel; }; #endif diff --git a/diagramCavas/include/diagramEditor/diagramEditorBayPreviewDlg.h b/diagramCavas/include/diagramEditor/diagramEditorBayPreviewDlg.h new file mode 100644 index 0000000..85e73af --- /dev/null +++ b/diagramCavas/include/diagramEditor/diagramEditorBayPreviewDlg.h @@ -0,0 +1,32 @@ +#ifndef DIAGRAMEDITORBAYPREVIEWDLG_H +#define DIAGRAMEDITORBAYPREVIEWDLG_H +//间隔预览窗口 +#include +#include +#include + +class EditView; +class EditPreviewScene; +class DiagramEditorBayDetailSettingDlg; + +const int g_nVDiagramSpacing = 50; +const int g_nHDiagramSpacing = 50; + +class DiagramEditorBayPreviewDlg : public QDialog +{ + Q_OBJECT +public: + DiagramEditorBayPreviewDlg(QWidget *parent = nullptr); + ~DiagramEditorBayPreviewDlg(); + + void initial(); + void setParent(DiagramEditorBayDetailSettingDlg* p) {_pParent = p;} + void updateModelData(); //根据设置更新data中布局、方向 +private: + EditView* _pView; + EditPreviewScene* _pScene; + QVBoxLayout* _pMainLayout; + DiagramEditorBayDetailSettingDlg* _pParent; +}; + +#endif diff --git a/diagramCavas/include/diagramEditor/editPanel.h b/diagramCavas/include/diagramEditor/editPanel.h index 2fcba07..86f7e4f 100644 --- a/diagramCavas/include/diagramEditor/editPanel.h +++ b/diagramCavas/include/diagramEditor/editPanel.h @@ -18,6 +18,7 @@ class DiagramEditorWizard; class DiagramEditorBaseBlock; class EditBaseItem; class DiagramEditorBayDetailSettingDlg; +class DiagramEditorModel; class EditPanel : public QWidget { @@ -51,6 +52,7 @@ private: QList _lstData; QMap> _mapStruct; QPointer _curWizard; + DiagramEditorModel* _pModel; }; #endif diff --git a/diagramCavas/include/diagramEditor/editScene.h b/diagramCavas/include/diagramEditor/editScene.h index 52743e3..91c252e 100644 --- a/diagramCavas/include/diagramEditor/editScene.h +++ b/diagramCavas/include/diagramEditor/editScene.h @@ -3,7 +3,15 @@ #include -class EditScene : public QGraphicsScene +class EditBaseScene : public QGraphicsScene +{ + Q_OBJECT +public: + EditBaseScene(QObject *parent = 0); + virtual ~EditBaseScene(); +}; + +class EditScene : public EditBaseScene //editor主界面scene { Q_OBJECT public: @@ -11,4 +19,12 @@ public: virtual ~EditScene(); }; +class EditPreviewScene : public EditBaseScene //bay预览scene +{ + Q_OBJECT +public: + EditPreviewScene(QObject *parent = 0); + virtual ~EditPreviewScene(); +}; + #endif diff --git a/diagramCavas/include/graphicsDataModel/baseModel.h b/diagramCavas/include/graphicsDataModel/baseModel.h index 562bc39..3990dc1 100644 --- a/diagramCavas/include/graphicsDataModel/baseModel.h +++ b/diagramCavas/include/graphicsDataModel/baseModel.h @@ -11,40 +11,15 @@ #include "global.h" +class GraphicsBaseItem; -/** - * The central class in the Model-View approach. It delivers all kinds - * of information from the backing user data structures that represent - * the graph. The class allows to modify the graph structure: create - * and remove nodes and connections. - * - * We use two types of the unique ids for graph manipulations: - * - NodeId - * - ConnectionId - */ class BaseModel : public QObject { Q_OBJECT - /// @brief Returns node-related data for requested NodeRole. - /** - * @returns Node Caption, Node Caption Visibility, Node Position etc. - */ - virtual QVariant nodeData(QUuid nodeId, NodeRole role) const = 0; - - /** - * A utility function that unwraps the `QVariant` value returned from the - * standard `QVariant AbstractGraphModel::nodeData(NodeId, NodeRole)` function. - */ - template - T nodeData(QUuid nodeId, NodeRole role) const - { - return nodeData(nodeId, role).value(); - } - - virtual NodeFlags nodeFlags(NodeId nodeId) const - { - Q_UNUSED(nodeId); - return NodeFlag::NoFlags; - } +public: + void createTopoTerminalsByItem(GraphicsBaseItem*,ModelFunctionType funType = ModelFunctionType::ProjectModel); //通过图形对象创建port接线点(新建) + QPointF calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item); //计算母线上接线点位置 + template void establishConnection(GraphicsBaseItem*,GraphicsBaseItem*,TypeLine*,ModelFunctionType); //在两个item之间建立连接 }; + diff --git a/diagramCavas/include/graphicsDataModel/diagramEditorModel.h b/diagramCavas/include/graphicsDataModel/diagramEditorModel.h new file mode 100644 index 0000000..75706d8 --- /dev/null +++ b/diagramCavas/include/graphicsDataModel/diagramEditorModel.h @@ -0,0 +1,36 @@ +#pragma once +/**组态编辑时的数据模型*/ +#include "graphicsDataModel/baseModel.h" + +class GraphicsBaseModelItem; +class DiagramEditorItemProperty; +class GraphicsBaseItem; +class EditPreviewScene; + +class DiagramEditorModel : public BaseModel +{ + Q_OBJECT +public: + DiagramEditorModel(); + ~DiagramEditorModel(); + + bool addTempPreviewItem(QUuid uuid,GraphicsBaseModelItem*); + DiagramEditorItemProperty* addTempPreviewData(QUuid id,int type,QString name,QString metaName,QString sBlock = QString()); //添加图元基模数据 + void createTopoTerminalsByItem(GraphicsBaseItem*,ModelFunctionType funType = ModelFunctionType::ProjectModel); //通过图形对象创建port接线点(新建) + void generateTempBay(); //通过设置生成间隔预览对象 + void generateTempComponent(QUuid uid,QString sName,int nCategory,int nType,QPoint pos,int nRotate = 0); //生成设备 uid,分类(设备、逻辑点),类型,旋转 + void generateTempLine(QUuid uid,QString sName); //生成连线 + + void setCurBayRouteModel(QStandardItemModel* p) {_pCurBayRoute = p;} + QStandardItemModel* getCurBayRouteModel() {return _pCurBayRoute;} + void setCurBayComponentModel(QStandardItemModel* p) {_pCurBayComponent = p;} + QStandardItemModel* getCurBayComponentModel() {return _pCurBayComponent;} + void setCurPreviewScene(EditPreviewScene* p) {_pCurPreviewScene = p;} + QStandardItem* getNameItem(const QString&); //获取返回当前设备模型中的name项 +private: + QMap _tempItem; //临时预览对象 + QStandardItemModel* _pCurBayRoute; //当前使用的间隔路线 + QStandardItemModel* _pCurBayComponent; //当前使用的间隔设备库 + EditPreviewScene* _pCurPreviewScene; //当前预览scene +}; + diff --git a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h index 9c3b050..839462d 100644 --- a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h +++ b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h @@ -42,7 +42,6 @@ public: bool addNodeItem(QUuid uuid,GraphicsProjectModelItem*); void addNodeItem(QUuid id,QPointF pos); GraphicsProjectModelItem* nodeItem(QUuid uuid); - QVariant nodeData(QUuid nodeId, NodeRole role) const; BaseProperty* addNodeData(QUuid id,int type,QString name,QString modelName); //对应component数据,一个data可对应多个item(id,类型,名称,工程模名) void loadNodeDataFromDataBase(); //从数据库加载数据 void addConnectLline(QUuid lineId,QUuid srcId,QUuid destId,QUuid srcPort,QUuid destPort); @@ -55,14 +54,11 @@ public: QWidget* getTopWidget(); QPointF getTerminalPos(const QString& sTerminalId); //获取拓扑接线点在当前diagram中的位置 ElectricConnectLineItem* getLineItemById(const QString& terminalId); - template void establishConnection(GraphicsBaseItem*,GraphicsBaseItem*,TypeLine*); //在两个item之间建立连接 - QPointF calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item); //计算母线上接线点位置 void showModelDlg(const QString&,QUuid,GraphicsProjectModelItem*); //点击时显示指定模型的dlg、指定item的数据(模型名,对象Uuid,触发事件的item) void initialPropertyDlg(); //初始化属性设置dlg,每个模型拥各自的dlg void generatePropertyDlg(const QString&); ConfigurationDiagram* getTopologyDiagram(); //返回当前组态图的拓扑实体 - void createTopoTerminalsByItem(GraphicsBaseItem*,ModelFunctionType funType = ModelFunctionType::ProjectModel); //通过图形对象创建port接线点(新建) void createTopoTerminalsByData(PowerEntity* pParent,QJsonObject componentCon,ModelFunctionType funType = ModelFunctionType::ProjectModel); //通过componet数据创建port接线点(加载) bool isItemValid(GraphicsProjectModelItem*); //判断item是否可以连接 diff --git a/diagramCavas/include/powerEntity.h b/diagramCavas/include/powerEntity.h index 22a0eac..6b5a8a4 100644 --- a/diagramCavas/include/powerEntity.h +++ b/diagramCavas/include/powerEntity.h @@ -44,7 +44,8 @@ public: QString name() const { return m_name; } QList children() const { return m_children; } PowerEntity* parent() const { return m_parent; } - + virtual void setBlock(const QString& s){m_bBlock = s;} + virtual QString block(){return m_bBlock;} // 递归查找 QList getAllDescendants() const { QList descendants; @@ -71,6 +72,7 @@ private: EntityType m_type; QString m_id; // 唯一标识符(可用UUID生成) QString m_name; + QString m_bBlock; //所属区块(编辑时) PowerEntity* m_parent = nullptr; QList m_children; }; diff --git a/diagramCavas/include/topologyManager.h b/diagramCavas/include/topologyManager.h index f4a3ad5..1364cfd 100644 --- a/diagramCavas/include/topologyManager.h +++ b/diagramCavas/include/topologyManager.h @@ -18,9 +18,10 @@ public: static TopologyManager& instance(); // 实体管理 - PowerEntity* createEntity(EntityType type,const QString& uuid,const QString& name,ModelFunctionType tpe = ModelFunctionType::ProjectModel); + PowerEntity* createEntity(EntityType type,const QString& uuid,const QString& name,ModelFunctionType tpe = ModelFunctionType::ProjectModel,const QString& block = QString()); PowerEntity* findEntity(const QString& id,ModelFunctionType = ModelFunctionType::ProjectModel) const; bool deleteEntity(const QString& id,ModelFunctionType = ModelFunctionType::ProjectModel); + QList getEntitiesByBlock(const QString&); //通过名称返回entity中的实体(blockEditor中) // 连接管理 PowerConnection* createConnection(const QString& uuid,const QString& fromTerId, const QString& toTerId,const QString& fromId,const QString& toId,ModelFunctionType tpe = ModelFunctionType::ProjectModel); @@ -29,8 +30,6 @@ public: bool validateConnection(const QString& fromTermId, const QString& toTermId,ModelFunctionType = ModelFunctionType::ProjectModel) const; // 连接查询接口 - //QList connectionsFrom(const QString& elementId) const; - //QList connectionsTo(const QString& elementId) const; QList getConnectionsFor(const QString& entityId,ModelFunctionType tpe = ModelFunctionType::ProjectModel) const; PowerConnection* connection(const QString& conId,ModelFunctionType tpe = ModelFunctionType::ProjectModel) const; PowerConnection* connection(const QString& fromPin,const QString& toPin,ModelFunctionType tpe = ModelFunctionType::ProjectModel); @@ -68,7 +67,6 @@ private: ~TopologyManager(); void clearAllData(); QHash m_entities; // ID到实体映射 - //QHash m_views; // 组态图视图存储 QHash m_diagrams; // 组态图拓扑结构 // 连接存储 @@ -90,6 +88,26 @@ private: QHash> m_baseTerminalsByEntity; // 实体ID到接线点列表(基模) QHash> m_baseEntityConnections; // >(基模) +private: + QHash m_editorEntities; // ID到实体映射(编辑器) + // 连接存储 + QHash m_editorConnections; + QMultiHash m_editorConnectionIndex; // 接线点ID到连接的映射(编辑器) + + QHash m_editorAllTerminals; // ID到接线点映射(编辑器) + QHash> m_editorTerminalsByEntity; // 实体ID到接线点列表(编辑器) + + QHash> m_editorEntityConnections; // >(编辑器) +private: + QHash m_blockEntities; // ID到实体映射(模块编辑) + // 连接存储 + QHash m_blockConnections; + QMultiHash m_blockConnectionIndex; // 接线点ID到连接的映射(模块编辑) + + QHash m_blockAllTerminals; // ID到接线点映射(模块编辑) + QHash> m_blockTerminalsByEntity; // 实体ID到接线点列表(模块编辑) + + QHash> m_blockEntityConnections; // >(模块编辑) }; diff --git a/diagramCavas/source/baseModelItem/electricBaseModelPortItem.cpp b/diagramCavas/source/baseModelItem/electricBaseModelPortItem.cpp new file mode 100644 index 0000000..d3189e2 --- /dev/null +++ b/diagramCavas/source/baseModelItem/electricBaseModelPortItem.cpp @@ -0,0 +1,59 @@ +#include "baseModelItem/electricBaseModelPortItem.h" +#include "graphicsItem/itemPort.h" +#include "baseProperty.h" +#include +#include +#include + +ElectricBaseModelPortItem::ElectricBaseModelPortItem(QGraphicsItem *parent) + : GraphicsBaseModelItem(parent) +{ + m_boundingRect = QRectF(-2,-2,4,4); + m_pen = QPen(Qt::black); + m_brush = QBrush(Qt::black); + setHandleVisible(false); + setFunctionHandleIfShow(false); + setFunctionHandleEnaable(false); +} + +ElectricBaseModelPortItem::~ElectricBaseModelPortItem() +{ + +} + +QRectF ElectricBaseModelPortItem::boundingRect() const +{ + return m_boundingRect; +} + +void ElectricBaseModelPortItem::updateConnectData() +{ + QJsonObject obj; + QJsonArray arr; + if(_property) + { + for(auto ptr:m_mapPort) + { + //if(ptr->connected()) + { + QJsonObject port; + port["portId"] = ptr->getId(); + auto pLine = ptr->getConnectPtr(); + port["x"] = ptr->pos().x(); + port["y"] = ptr->pos().y(); + port["portType"] = ptr->getType(); + arr.push_back(port); + } + } + + obj["port"] = arr; + obj["metaModel"] = _property->metaModelName(); + _property->setContext(obj); + } +} + +void ElectricBaseModelPortItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + painter->setBrush(m_brush); + painter->drawEllipse(m_boundingRect); +} diff --git a/diagramCavas/source/diagramEditor/diagramEditorBayDetailAddDlg.cpp b/diagramCavas/source/diagramEditor/diagramEditorBayDetailAddDlg.cpp index 6625bf7..3df4e7d 100644 --- a/diagramCavas/source/diagramEditor/diagramEditorBayDetailAddDlg.cpp +++ b/diagramCavas/source/diagramEditor/diagramEditorBayDetailAddDlg.cpp @@ -87,7 +87,7 @@ void DiagramEditorBayDetailAddDlg::showDlg(DiagramEditorBayRouteInfo info) _selectedModel->clear(); _selectedModel->setHorizontalHeaderLabels({"分类", "名称", "类型", "关联对象", "引用线路"}); ui->le_routeName->setText(info.sRouteName); - for(auto& component:info.mapCompo){ + for(auto& component:info.lstCompo){ QStandardItem *itemCate = new QStandardItem(); QStandardItem *itemName = new QStandardItem(); @@ -238,8 +238,37 @@ void DiagramEditorBayDetailAddDlg::onSaveClicked() for(int i = 0;i < rowCount;++i){ QStandardItem *item = pCompoModel->item(i, 1); if(item->text() == sName){ - QMessageBox::information(NULL, QString("提示"), QString::fromWCharArray(L"设备名重复")); - return; + QMessageBox msgBox; + msgBox.setText(QString::fromWCharArray(L"提示")); + msgBox.setInformativeText(QString::fromWCharArray(L"设备名已存在,是否覆盖?")); + msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Cancel); + int ret = msgBox.exec(); + + switch (ret) { + case QMessageBox::Ok: //覆盖 + { + QStandardItem *itemCate = pCompoModel->item(i, 0); + QStandardItem *itemType = pCompoModel->item(i, 2); + QStandardItem *itemObj = pCompoModel->item(i, 3); + QStandardItem *itemRoute = pCompoModel->item(i, 4); + + item->setData(0); //覆盖时初始化方向占用 + item->setData(QUuid::createUuid(),Qt::UserRole+3); //初始化时赋予uuid + itemCate->setText(sCategory); + itemType->setText(sType); + itemType->setData(nType); + itemObj->setText(sBindObj); + return; + } + break; + case QMessageBox::Cancel: + // Cancel was clicked + return; + default: + // should never be reached + break; + } } } @@ -250,6 +279,7 @@ void DiagramEditorBayDetailAddDlg::onSaveClicked() QStandardItem *itemRoute = new QStandardItem(); itemCate->setText(sCategory); itemName->setText(sName); + itemName->setData(0); //初始化方向占用 itemType->setText(sType); itemType->setData(nType); itemObj->setText(sBindObj); @@ -298,7 +328,7 @@ void DiagramEditorBayDetailAddDlg::onOkClicked() compoInfo.sBindObj = sBind; compoInfo.sUsedRoute = sAllRoute.split(","); - routeInfo.mapCompo.insert(sName,compoInfo); + routeInfo.lstCompo.append(compoInfo); lstName.append(sName); } @@ -396,7 +426,7 @@ void DiagramEditorBayDetailAddDlg::onComponentDeleteClicked() auto& mapRoute = _pParent->getRouteMap(); //检索所有路线,判断设备占用情况 for(auto& route:mapRoute){ QString sRoute = route.sRouteName; - for(auto& compo:route.mapCompo){ + for(auto& compo:route.lstCompo){ if(compo.sName == sName){ bUsed = true; break; @@ -418,8 +448,14 @@ void DiagramEditorBayDetailAddDlg::onComponentDeleteClicked() { for(auto& route:mapRoute){ QString sRoute = route.sRouteName; - route.mapCompo.remove(sName); + for(int i = 0;i < route.lstCompo.size();++i){ + QString sCompo = route.lstCompo[i].sName; + if(sCompo == sName){ + route.lstCompo.removeAt(i); + } + } } + //todo:刷新主界面 foreach (int row, rowsToRemove) { diff --git a/diagramCavas/source/diagramEditor/diagramEditorBayDetailSettingDlg.cpp b/diagramCavas/source/diagramEditor/diagramEditorBayDetailSettingDlg.cpp index ed93470..8631b17 100644 --- a/diagramCavas/source/diagramEditor/diagramEditorBayDetailSettingDlg.cpp +++ b/diagramCavas/source/diagramEditor/diagramEditorBayDetailSettingDlg.cpp @@ -2,9 +2,11 @@ #include #include "diagramEditor/diagramEditorBayDetailSettingDlg.h" #include "diagramEditor/diagramEditorBayDetailAddDlg.h" +#include "diagramEditor/diagramEditorBayPreviewDlg.h" #include "diagramEditor/diagramEditorWizard.h" #include "ui_diagramEditorBayDetailSettingDlg.h" #include "diagramEditor/diagramEditorBaseBlock.h" +#include "graphicsDataModel/diagramEditorModel.h" DiagramEditorBayDetailSettingDlg::DiagramEditorBayDetailSettingDlg(QWidget *parent) : QDialog(parent) @@ -13,6 +15,8 @@ DiagramEditorBayDetailSettingDlg::DiagramEditorBayDetailSettingDlg(QWidget *pare ,_curOperateObj(nullptr) ,_compoModel(nullptr) ,_routeModel(nullptr) + ,_pPreviewDlg(nullptr) + ,_pModel(nullptr) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint | windowFlags()); @@ -35,6 +39,7 @@ void DiagramEditorBayDetailSettingDlg::initial() connect(ui->btn_add,&QPushButton::clicked,this,&DiagramEditorBayDetailSettingDlg::onAddClicked); connect(ui->btn_ok,&QPushButton::clicked,this,&DiagramEditorBayDetailSettingDlg::onOkClicked); connect(ui->btn_cancel,&QPushButton::clicked,this,&DiagramEditorBayDetailSettingDlg::onCancelClicked); + connect(ui->btn_preview,&QPushButton::clicked,this,&DiagramEditorBayDetailSettingDlg::onPreviewClicked); connect(ui->tableView, &QTableView::customContextMenuRequested, this, &DiagramEditorBayDetailSettingDlg::onRouteRbtnClicked); ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -141,7 +146,7 @@ void DiagramEditorBayDetailSettingDlg::refreshModel() for(auto& route:mapRoute){ QString sRoute = route.sRouteName; QStringList lstComp; - for(auto& comp:route.mapCompo){ + for(auto& comp:route.lstCompo){ lstComp.append(comp.sName); } @@ -188,6 +193,8 @@ void DiagramEditorBayDetailSettingDlg::onOkClicked() QStandardItem *itemType = _compoModel->item(i, 2); QStandardItem *itemBind = _compoModel->item(i, 3); QStandardItem *itemRoute = _compoModel->item(i, 4); + int nDir = itemName->data(Qt::UserRole+1).toInt(); + QPoint deltaPos = itemName->data(Qt::UserRole+2).toPoint(); DiagramEditorComponentInfo compoInfo; if(itemCate->text() == "电气设备"){ @@ -200,6 +207,8 @@ void DiagramEditorBayDetailSettingDlg::onOkClicked() compoInfo.nType = itemType->data().toInt(); compoInfo.sBindObj = itemBind->text(); compoInfo.sUsedRoute = itemRoute->text().split(","); + compoInfo.nUsedDirection = nDir; + compoInfo.deltaPos = deltaPos; mapComponents.insert(compoInfo.sName,compoInfo); } @@ -296,3 +305,25 @@ void DiagramEditorBayDetailSettingDlg::onRouteEditClicked() auto routeInfo = _mapRouteInfo.value(sName); _pAddDlg->showDlg(routeInfo); } + +void DiagramEditorBayDetailSettingDlg::onPreviewClicked() +{ + if(_pPreviewDlg == nullptr){ + _pPreviewDlg = new DiagramEditorBayPreviewDlg(this); + } + if(!_pPreviewDlg->isVisible()){ + + /*int rowCount = _routeModel->rowCount(); + for(int i = 0;i < rowCount;++i){ + QStandardItem *itemComps = _routeModel->item(i, 1); + QString str = itemComps->text(); + QStringList lstComps = str.split(","); + for(auto& sCompName:lstComps){ + QStandardItem* pItemName = _pModel->getNameItem(sCompName); + } + }*/ + + } + else + _pPreviewDlg->hide(); +} diff --git a/diagramCavas/source/diagramEditor/diagramEditorBayPreviewDlg.cpp b/diagramCavas/source/diagramEditor/diagramEditorBayPreviewDlg.cpp new file mode 100644 index 0000000..83cb28c --- /dev/null +++ b/diagramCavas/source/diagramEditor/diagramEditorBayPreviewDlg.cpp @@ -0,0 +1,249 @@ +#include "diagramEditor/diagramEditorBayPreviewDlg.h" +#include "diagramEditor/diagramEditorBayDetailSettingDlg.h" +#include "diagramEditor/editView.h" +#include "diagramEditor/editScene.h" +#include "graphicsDataModel/diagramEditorModel.h" +#include "global.h" + +DiagramEditorBayPreviewDlg::DiagramEditorBayPreviewDlg(QWidget *parent) + : QDialog(parent) + ,_pView(nullptr) + ,_pScene(nullptr) + ,_pMainLayout(nullptr) + ,_pParent(nullptr) +{ + QRect recParent = parent->geometry(); + setGeometry(recParent.right(),recParent.y(),recParent.width(),recParent.height()); + initial(); +} + +DiagramEditorBayPreviewDlg::~DiagramEditorBayPreviewDlg() +{ + +} + +void DiagramEditorBayPreviewDlg::initial() +{ + _pMainLayout = new QVBoxLayout(this); + _pView = new EditView(this); + _pMainLayout->addWidget(_pView); + _pScene = new EditPreviewScene(this); + _pScene->setSceneRect(-g_dGriaphicsScene_Width / 2, -g_dGriaphicsScene_Height / 2, g_dGriaphicsScene_Width, g_dGriaphicsScene_Height); + _pView->setScene(_pScene); + +} + +void DiagramEditorBayPreviewDlg::updateModelData() +{ + auto& mapRoute = _pParent->getRouteMap(); + QString sMainRoute; + int nCount = 0; + for(auto& route:mapRoute){ //寻找包含设备最多的线路 + if(nCount < route.lstCompo.count()){ + nCount = route.lstCompo.count(); + sMainRoute = route.sRouteName; + route.bMainRoute = true; + } + } + + auto& maoCompo = mapRoute[sMainRoute].lstCompo; //假设竖直情况下,上下等分为nSeg段 假设主线路水平居中 + int nSeg = maoCompo.size()*0.5; + int nSegIndex = -nSeg; //计数器,计算deltaY + for(int i = 0;i < maoCompo.size();++i){ //优先遍历主线路,构建主体结构 + int nDir = 0; + if(i == 0){ //队首 + maoCompo[i].nUsedDirection |= 4; //默认向下,队首单向下(单线路记录,不可作为跨线判断依据) + nDir = 4; + } + else if(i == maoCompo.size()-1){ + maoCompo[i].nUsedDirection |= 8; //队尾单向上(单线路记录,不可作为跨线判断依据) + nDir = 8; + } + else{ + maoCompo[i].nUsedDirection |= 12; //其余向上向下都被占用(单线路记录,不可作为跨线判断依据) + nDir = 12; + } + int deltaY = nSegIndex*g_nVDiagramSpacing; + + auto pItemName = _pParent->getModel()->getNameItem(maoCompo[i].sName); + if(pItemName){ + int nVal = pItemName->data().toInt(); + pItemName->setData(QString::number(nVal |= nDir)); //在公用模型中更新设备方向占用(重要) + pItemName->setData(QPoint(0,deltaY),Qt::UserRole+2); //设置相对位置 + } + nSegIndex += 1; + } + + for(auto& route:mapRoute){ //遍历主线路之外的线路 + if(route.sRouteName == sMainRoute){ + continue; + } + + if(!route.lstCompo.isEmpty()){ //拆分线路为以节点为首 + auto pItemFirst = _pParent->getModel()->getNameItem(route.lstCompo.first().sName); + int nFirstVal = pItemFirst->data().toInt(); + auto pItemLast = _pParent->getModel()->getNameItem(route.lstCompo.last().sName); + int nLastVal = pItemLast->data().toInt(); + if(nFirstVal != 0){ //首位为节点 + route.lstOrder = route.lstCompo; + } + else if(nLastVal != 0){ //末位为节点 + for (auto it = route.lstCompo.rbegin(); it != route.lstCompo.rend(); ++it) { + route.lstReverse.append(*it); + } + } + else{ //节点在中间 + int nIndex = 0; + for(int i = 0;i < route.lstCompo.size();++i){ + auto pItem = _pParent->getModel()->getNameItem(route.lstCompo[i].sName); + if(pItem){ + int nVal = pItem->data().toInt(); + if(nVal != 0){ + nIndex = i; + break; + } + } + } + + for(int i = nIndex;i >= 0;--i){ + route.lstReverse.append(route.lstCompo[i]); + } + + for(int i = nIndex;i < route.lstCompo.size();++i){ + route.lstOrder.append(route.lstCompo[i]); + } + } + } + + int nOrderFirstDeltaY = 0; //首节点y偏移量(假设后续节点与头节点水平) + int nXOrderIndex = 1; //横向计数 + int nOrderPolarity = 1; //方向 1右 -1左 + if(route.lstOrder.size() > 1){ + for(int i = 0;i < route.lstOrder.size()-1;++i){ //遍历以节点为首的队列 + auto pItem = _pParent->getModel()->getNameItem(route.lstOrder[i].sName); + int nVal = pItem->data().toInt(); + QPoint deltaP = pItem->data(Qt::UserRole+2).toPoint(); + + auto pNextItem = _pParent->getModel()->getNameItem(route.lstOrder[i+1].sName); //下一个item + int nNextVal = pNextItem->data().toInt(); + if(i == 0){ //首节点 + nOrderFirstDeltaY = deltaP.y(); + if(((nVal & 2) == 1) && ((nVal & 1) == 1)){ + qDebug()<setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); //同时连接下个点的一侧占用 + nOrderPolarity = 1; + } + else if((nVal & 1) == 1){ + //右被占用,左空 + pItem->setData(QString::number(nVal | 2)); + pNextItem->setData(QString::number(nNextVal | 1)); + nOrderPolarity = -1; + } + else{ //左右都没被占,默认放到左边 + pItem->setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); + nOrderPolarity = 1; + } + continue; + } + /*if(i == 0){ //首节点特殊处理 + if(((nVal & 8) == 1) && ((nVal & 4) == 1)){ //上下都被占,在中间 + + } + else if((nVal & 8) == 1 ){ //上被占,在末尾 + + } + else if((nVal & 4) == 1 ){ //下被占,在头部 + + } + } + else{ + + }*/ + + int deltaX = nXOrderIndex*nOrderPolarity*g_nHDiagramSpacing; + if(((nVal & 2) == 1) && ((nVal & 1) == 1)){ + qDebug()<setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); //同时连接下个点的一侧占用 + } + else if((nVal & 1) == 1){ + //右被占用,左空 + pItem->setData(QString::number(nVal | 2)); + pNextItem->setData(QString::number(nNextVal | 1)); + } + else{ //左右都没被占,默认放到左边 + pItem->setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); + } + pNextItem->setData(QPoint(deltaX,nOrderFirstDeltaY),Qt::UserRole + 2); + } + } + + int nReverseFirstDeltaY = 0; //首节点y偏移量(假设后续节点与头节点水平) + int nXReverseIndex = 1; //横向计数 + int nReversePolarity = 1; //方向 1右 -1左 + if(route.lstOrder.size() > 1){ + for(int i = 0;i < route.lstOrder.size()-1;++i){ //遍历以节点为首的队列 + auto pItem = _pParent->getModel()->getNameItem(route.lstOrder[i].sName); + int nVal = pItem->data().toInt(); + QPoint deltaP = pItem->data(Qt::UserRole+2).toPoint(); + + auto pNextItem = _pParent->getModel()->getNameItem(route.lstOrder[i+1].sName); //下一个item + int nNextVal = pNextItem->data().toInt(); + if(i == 0){ //首节点 + nReverseFirstDeltaY = deltaP.y(); + if(((nVal & 2) == 1) && ((nVal & 1) == 1)){ + qDebug()<setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); //同时连接下个点的一侧占用 + nReversePolarity = 1; + } + else if((nVal & 1) == 1){ + //右被占用,左空 + pItem->setData(QString::number(nVal | 2)); + pNextItem->setData(QString::number(nNextVal | 1)); + nReversePolarity = -1; + } + else{ //左右都没被占,默认放到左边 + pItem->setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); + nReversePolarity = 1; + } + continue; + } + + int deltaX = nXReverseIndex*nReversePolarity*g_nHDiagramSpacing; + if(((nVal & 2) == 1) && ((nVal & 1) == 1)){ + qDebug()<setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); //同时连接下个点的一侧占用 + } + else if((nVal & 1) == 1){ + //右被占用,左空 + pItem->setData(QString::number(nVal | 2)); + pNextItem->setData(QString::number(nNextVal | 1)); + } + else{ //左右都没被占,默认放到左边 + pItem->setData(QString::number(nVal | 1)); + pNextItem->setData(QString::number(nNextVal | 2)); + } + pNextItem->setData(QPoint(deltaX,nReverseFirstDeltaY),Qt::UserRole + 2); + } + } + } +} + diff --git a/diagramCavas/source/diagramEditor/editPanel.cpp b/diagramCavas/source/diagramEditor/editPanel.cpp index 1de8c97..c7f61ce 100644 --- a/diagramCavas/source/diagramEditor/editPanel.cpp +++ b/diagramCavas/source/diagramEditor/editPanel.cpp @@ -16,6 +16,7 @@ #include "diagramEditor/diagramEditorBaseBlock.h" #include "diagramEditor/editItems.h" #include "diagramEditor/diagramEditorBayDetailSettingDlg.h" +#include "graphicsDataModel/diagramEditorModel.h" #include "global.h" #include @@ -23,7 +24,9 @@ EditPanel::EditPanel(QWidget *parent) : QWidget(parent) ,_curWizard(nullptr) ,_bayDetailSetting(nullptr) + ,_pModel(nullptr) { + _pModel = new DiagramEditorModel(); _maxWidth = 0; _maxHeight = 0; _layout = new QVBoxLayout(this); @@ -41,7 +44,8 @@ EditPanel::EditPanel(QWidget *parent) EditPanel::~EditPanel() { - + if(_pModel) + delete _pModel; } void EditPanel::initByWizardInfo() diff --git a/diagramCavas/source/diagramEditor/editScene.cpp b/diagramCavas/source/diagramEditor/editScene.cpp index 6d4595c..214dbec 100644 --- a/diagramCavas/source/diagramEditor/editScene.cpp +++ b/diagramCavas/source/diagramEditor/editScene.cpp @@ -1,12 +1,32 @@ #include "diagramEditor/editScene.h" -EditScene::EditScene(QObject *parent) +EditBaseScene::EditBaseScene(QObject *parent) : QGraphicsScene(parent) { +} +EditBaseScene::~EditBaseScene() +{ +} + +/************************editor主界面*********************/ + +EditScene::EditScene(QObject *parent) + : EditBaseScene(parent) +{ + } EditScene::~EditScene() { } +/************************预览*********************/ +EditPreviewScene::EditPreviewScene(QObject *parent) + : EditBaseScene(parent) +{ + +} +EditPreviewScene::~EditPreviewScene() +{ +} diff --git a/diagramCavas/source/graphicsDataModel/NumberDisplayDataModel.cpp b/diagramCavas/source/graphicsDataModel/NumberDisplayDataModel.cpp deleted file mode 100644 index 5086050..0000000 --- a/diagramCavas/source/graphicsDataModel/NumberDisplayDataModel.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "NumberDisplayDataModel.hpp" - -#include - -NumberDisplayDataModel::NumberDisplayDataModel() - : _label{nullptr} -{} - -unsigned int NumberDisplayDataModel::nPorts(PortType portType) const -{ - unsigned int result = 1; - - switch (portType) { - case PortType::In: - result = 1; - break; - - case PortType::Out: - result = 0; - - default: - break; - } - - return result; -} - -NodeDataType NumberDisplayDataModel::dataType(PortType, PortIndex) const -{ - return DecimalData().type(); -} - -std::shared_ptr NumberDisplayDataModel::outData(PortIndex) -{ - std::shared_ptr ptr; - return ptr; -} - -void NumberDisplayDataModel::setInData(std::shared_ptr data, PortIndex portIndex) -{ - _numberData = std::dynamic_pointer_cast(data); - - if (!_label) - return; - - if (_numberData) { - _label->setText(_numberData->numberAsText()); - } else { - _label->clear(); - } - - _label->adjustSize(); -} - -QWidget *NumberDisplayDataModel::embeddedWidget() -{ - if (!_label) { - _label = new QLabel(); - _label->setMargin(3); - } - - return _label; -} - -double NumberDisplayDataModel::number() const -{ - if (_numberData) - return _numberData->number(); - - return 0.0; -} diff --git a/diagramCavas/source/graphicsDataModel/baseModel.cpp b/diagramCavas/source/graphicsDataModel/baseModel.cpp index a35c5c3..63ef469 100644 --- a/diagramCavas/source/graphicsDataModel/baseModel.cpp +++ b/diagramCavas/source/graphicsDataModel/baseModel.cpp @@ -1,3 +1,135 @@ - #include "graphicsDataModel/baseModel.h" +#include "graphicsItem/itemPort.h" +#include "graphicsItem/graphicsBaseItem.h" +#include "baseProperty.h" +#include "topologyManager.h" +#include "powerEntity.h" +#include "baseModelItem/electricBaseModelLineItem.h" +void BaseModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem,ModelFunctionType funType) +{ + PowerEntity* pEntity = pItem->entity(); + + if(pEntity) + { + QMap mapPorts = pItem->getPorts(); //创建实体port对应的拓扑port + 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; + } + QPointF f = port->pos(); + TopologyManager::instance().createTerminal(pEntity->id(),terType,"",port->pos(),port->getId(),funType); + } + } +} + +QPointF BaseModel::calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item) +{ + return QPointF(item->pos().x(),pBus->pos().y()); +} + +template void BaseModel::establishConnection(GraphicsBaseItem* pSrc,GraphicsBaseItem* pDest,TypeLine* pItem,ModelFunctionType nType) +{ + ItemPort* pSrcPort = nullptr; + ItemPort* pDestPort = nullptr; + int nTypeSrc = pSrc->getProperty()->type(); + int nTypeDest = pDest->getProperty()->type(); + //if(pSrc->getItemType() == GIT_baseBus) + if(nTypeSrc == 1 || nTypeSrc == 14) //母线或节点 + { + int index = 0; + if(nTypeSrc == 1 ) + index = pSrc->addPort(p_movable,pSrc->mapFromScene(calculateBusPortPos(pSrc,pDest))); + else + index = pSrc->addPort(p_movable,QPoint(0,0)); //节点port与自身坐标重合 + createTopoTerminalsByItem(pSrc,nType); + pSrcPort = pSrc->getPortPtr(index); + + QMap mapPorts = pDest->getPorts(); + + for(auto& port:mapPorts) + { + if(port->getType() == T_lineIn) + { + pDestPort = port; + break; + } + } + + } + //else if(pDest->getItemType() == GIT_baseBus) + else if(nTypeDest == 1 || nTypeDest == 14) //母线或节点 + { + int index = 0; + if(nTypeDest == 1 ) + index = pDest->addPort(p_movable,pDest->mapFromScene(calculateBusPortPos(pDest,pSrc))); + else + index = pDest->addPort(p_movable,QPoint(0,0)); //节点port与自身坐标重合 + createTopoTerminalsByItem(pDest,nType); + pDestPort = pDest->getPortPtr(index); + + QMap mapPorts = pSrc->getPorts(); + + for(auto& port:mapPorts) + { + if(port->getType() == T_lineOut) + { + pSrcPort = port; + break; + } + } + } + else + { + QMap mapSrc = pSrc->getPorts(); + pSrcPort = nullptr; + for(auto& port:mapSrc) + { + if(port->getType() == T_lineOut) + { + pSrcPort = port; + break; + } + } + + QMap mapDest = pDest->getPorts(); + pDestPort = nullptr; + for(auto& port:mapDest) + { + if(port->getType() == T_lineIn) + { + pDestPort = port; + break; + } + } + } + if(pSrcPort && pDestPort) + { + QPointF srcPortPos = pSrcPort->scenePos(); + QPointF destPortPos = pDestPort->scenePos(); + pItem->setStartPoint(srcPortPos); + pItem->setEndPoint(destPortPos); + pItem->calculatePath(); + + PowerConnection* pCon = TopologyManager::instance().createConnection(pItem->itemId().toString(),pSrcPort->getId(),pDestPort->getId(),pSrc->itemId().toString(),pDest->itemId().toString(),nType); //创建拓扑连接(逻辑) + if(pCon) + pCon->setState(DataState::changed); + pItem->getProperty()->setConnection(Connection(pSrc->itemId(),QUuid(pSrcPort->getId()),pSrcPort->getType(),pSrcPort->portPos(),pDest->itemId(),QUuid(pDestPort->getId()),pDestPort->getType(),pDestPort->portPos())); + } +} + +template void BaseModel::establishConnection(GraphicsBaseItem*,GraphicsBaseItem*,ElectricBaseModelLineItem*,ModelFunctionType); diff --git a/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp b/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp new file mode 100644 index 0000000..5c56dce --- /dev/null +++ b/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp @@ -0,0 +1,241 @@ +#include "graphicsDataModel/diagramEditorModel.h" +#include "basePropertyManager.h" +#include "baseProperty.h" +#include "powerEntity.h" +#include "graphicsItem/graphicsBaseItem.h" +#include "powerTerminal.h" +#include "graphicsItem/itemPort.h" +#include "topologyManager.h" +#include "baseModelItem/electricBaseModelSvgItem.h" +#include "dataBase.h" +#include "diagramEditor/editScene.h" +#include "baseModelItem/electricBaseModelPortItem.h" +#include "baseModelItem/electricBaseModelSvgBus.h" +#include "baseModelItem/electricBaseModelLineItem.h" + +DiagramEditorModel::DiagramEditorModel() + :_pCurBayRoute(nullptr) + ,_pCurBayComponent(nullptr) + ,_pCurPreviewScene(nullptr) +{ + +} + +DiagramEditorModel::~DiagramEditorModel() +{ + +} + +bool DiagramEditorModel::addTempPreviewItem(QUuid uuid,GraphicsBaseModelItem* pItem) +{ + if(_tempItem.contains(uuid)) + return false; + else + { + _tempItem.insert(uuid,pItem); + return true; + } +} + +DiagramEditorItemProperty* DiagramEditorModel::addTempPreviewData(QUuid id,int type,QString name,QString metaName,QString sBlock) +{ + DiagramEditorItemProperty* pData = BasePropertyManager::instance().findTempEditorData(id); //已存在不不创建 + if(pData != nullptr) + return pData; + + DiagramEditorItemProperty* itemData = new DiagramEditorItemProperty(this); + + if(itemData) + { + itemData->setUuid(id); + itemData->setMetaModelName(metaName); + itemData->setType(type); + itemData->setTag(name); + itemData->setName(name); + if(!sBlock.isEmpty()) + itemData->setBlock(sBlock); + BasePropertyManager::instance().insertTempEditorData(id,itemData); + } + return itemData; +} + +void DiagramEditorModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem,ModelFunctionType funType) +{ + PowerEntity* pEntity = pItem->entity(); + + if(pEntity) + { + QMap mapPorts = pItem->getPorts(); //创建实体port对应的拓扑port + 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; + } + QPointF f = port->pos(); + TopologyManager::instance().createTerminal(pEntity->id(),terType,"",port->pos(),port->getId(),funType); + } + } +} + +void DiagramEditorModel::generateTempBay() +{ + int rowCount = _pCurBayRoute->rowCount(); + for(int i = 0;i < rowCount;++i){ + QStandardItem *itemComps = _pCurBayRoute->item(i, 1); + QString sComps = itemComps->text(); + QStringList lst = sComps.split(","); + for(auto& name:lst){ //第一次循环生成item + QStandardItem* pItem = getNameItem(name); + if(pItem){ + QModelIndex index = pItem->index(); + QModelIndex indexCate = index.sibling(index.row(),0); + QModelIndex indexType = index.sibling(index.row(),2); + if(!pItem->data(Qt::UserRole+4).isValid()){ //未初始化,新建item + pItem->setData(1,Qt::UserRole+4); + int nCate = indexCate.data().toInt(); //0设备1连接 + int nType = indexType.data().toInt(); + int nDir = pItem->data().toInt(); + int nRotate = 0; + if(nDir == 12 || nDir == 8 || nDir == 4){ //垂直连接 + pItem->setData(0,Qt::UserRole+5); //垂直不旋转 + nRotate = 0; + } + else if(nDir == 2 || nDir == 1){ //水平 + pItem->setData(90,Qt::UserRole+5); //水平的item旋转 + nRotate = 90; + } + else{ + pItem->setData(0,Qt::UserRole+5); //全被连不旋转 + nRotate = 0; + } + QPoint pos = pItem->data(Qt::UserRole+2).toPoint(); + QUuid uid = pItem->data(Qt::UserRole+3).toUuid(); + generateTempComponent(uid,name,nCate,nType,pos,nRotate); + } + } + } + + for(int i = 0;i < lst.size() -1;++i){ + + } + } +} + +void DiagramEditorModel::generateTempComponent(QUuid uid,QString sName,int nCategory,int nType,QPoint pos,int nRotate) +{ + GraphicsBaseModelItem* pItem = nullptr; + if(nCategory == 0) + { + QByteArray byte; + if(nType == 1){ //母线 + byte = DataBase::GetInstance()->ModelType()[nType].icon; + auto pBus = new ElectricBaseModelSvgBus(QRect(-200, -3, 400, 6)); + pBus->loadSvg(byte); + pItem->setItemType(GIT_baseBus); + } + else if(nType == 2){ //异步电动机 + } + else if(nType == 3){ //断路器 + byte = DataBase::GetInstance()->ModelType()[nType].icon; + auto pBreaker = new ElectricBaseModelSvgItem(QRect(-15, -15, 30, 30)); + pBreaker->loadSvg(byte); + pItem->setItemType(GIT_baseBreaker); + pItem->initialPortsByDatabase(); + } + else if(nType == 4){ //电缆 + } + else if(nType == 5){ //电流互感器 + } + else if(nType == 6){ //电压互感器 + } + else if(nType == 7){ //隔离开关 + } + else if(nType == 8){ //接地开关 + } + else if(nType == 9){ //快速接地开关 + } + else if(nType == 10){ //双掷接地隔离开关 + } + else if(nType == 11){ //带电指示器 + } + else if(nType == 12){ //避雷器 + } + else if(nType == 13){ //电缆出线套筒 + } + else if(nType == 14){ //电缆端 + } + } + else if(nCategory == 1){ + if(nType == 1){ //节点 + pItem = new ElectricBaseModelPortItem(); + pItem->setItemType(GIT_baseNode); + } + } + + if(pItem){ + pItem->setItemId(uid); + pItem->setRotation(nRotate); + PowerEntity* pEntityData = TopologyManager::instance().createEntity(EntityType::Component,uid.toString(),sName,ModelFunctionType::BlockEditorModel); + if(pEntityData) + pItem->setEntity(pEntityData); + DiagramEditorItemProperty* pData = nullptr; + if(nCategory == 1){ + pData = addTempPreviewData(uid,0,sName,"node"); + } + else if(nCategory == 0){ //设备 + pData = addTempPreviewData(uid,nType,sName,DataBase::GetInstance()->ModelType()[nType].modelType); + pData->setGraphicsType(pItem->getItemType()); + } + if(pData) + { + pItem->setProperty(pData); + createTopoTerminalsByItem(pItem,ModelFunctionType::BlockEditorModel); + pData->setDataChanged(true); //数据状态改变 + } + addTempPreviewItem(uid,pItem); + _pCurPreviewScene->addItem(pItem); + pItem->setPos(pos); + } +} + +void DiagramEditorModel::generateTempLine(QUuid uid,QString sName) +{ + ElectricBaseModelLineItem* pLine = new ElectricBaseModelLineItem(); + pLine->setItemId(uid); + pLine->setItemType(GIT_baseLine); + DiagramEditorItemProperty* pData = addTempPreviewData(uid,4,sName,DataBase::GetInstance()->ModelType()[4].modelType); + pData->setGraphicsType(GIT_baseLine); + if(pData) + { + pLine->setProperty(pData); + pData->setDataChanged(true); //数据状态改变 + } + addTempPreviewItem(uid,pLine); + //establishConnection(pBreaker,pBus,pLine,ModelFunctionType::BaseModel); + _pCurPreviewScene->addItem(pLine); +} + +QStandardItem* DiagramEditorModel::getNameItem(const QString& sName) +{ + int nRowCount = _pCurBayComponent->rowCount(); + for(int i = 0;i < nRowCount;++i){ + QStandardItem *itemName = _pCurBayComponent->item(i, 1); + if(sName == itemName->text()){ + return itemName; + } + } + return nullptr; +} diff --git a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp index f87f7de..109ddbd 100644 --- a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp +++ b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp @@ -409,94 +409,6 @@ void FixedPortsModel::deleteNodeItem(GraphicsProjectModelItem* pItem) } } -QVariant FixedPortsModel::nodeData(QUuid nodeId, NodeRole role) const -{ - QVariant result; - switch(role) - { - case NodeRole::Position: - result = _nodeItem[nodeId]->pos(); - break; - } - - /*auto it = _models.find(nodeId); - if (it == _models.end()) - return result; - - auto &model = *it; - - switch (role) { - case NodeRole::Type: - result = model->name(); - break; - - case NodeRole::Position: - result = _nodeGeometryData[nodeId].pos; - break; - - case NodeRole::Size: - result = _nodeGeometryData[nodeId].size; - break; - - case NodeRole::CaptionVisible: - result = model->captionVisible(); - break; - - case NodeRole::Caption: - result = model->caption(); - break; - - case NodeRole::Style: { - //auto style = StyleCollection::nodeStyle(); - //result = style.toJson().toVariantMap(); - } break; - - case NodeRole::InternalData: { - QJsonObject nodeJson; - - //nodeJson["internal-data"] = _models[nodeId]->save(); - - result = nodeJson.toVariantMap(); - break; - } - - case NodeRole::InPortCount: - result = model->nPorts(PortType::In); - break; - - case NodeRole::OutPortCount: - result = model->nPorts(PortType::Out); - break; - - case NodeRole::Widget: { - auto w = model->embeddedWidget(); - result = QVariant::fromValue(w); - } break; - }*/ - - return result; -} - -/*QJsonObject FixedPortsModel::saveNode(QUuid const nodeId) const -{ - QJsonObject nodeJson; - - nodeJson["id"] = nodeId.toString(); - - nodeJson["type"] = _nodeItem[nodeId]->getItemType(); - - { - QPointF const pos = nodeData(nodeId, NodeRole::Position).value(); - - QJsonObject posJson; - posJson["x"] = pos.x(); - posJson["y"] = pos.y(); - nodeJson["position"] = posJson; - } - - return nodeJson; -}*/ - void FixedPortsModel::saveNode(int nPageId) { for(auto& bay:_bayItem) @@ -846,89 +758,6 @@ ElectricConnectLineItem* FixedPortsModel::getLineItemById(const QString& termina return nullptr; } -template void FixedPortsModel::establishConnection(GraphicsBaseItem* pSrc,GraphicsBaseItem* pDest,TypeLine* pItem) -{ - ItemPort* pSrcPort = nullptr; - ItemPort* pDestPort = nullptr; - if(pSrc->getItemType() == GIT_baseBus) - { - int index = pSrc->addPort(p_movable,pSrc->mapFromScene(calculateBusPortPos(pSrc,pDest))); - createTopoTerminalsByItem(pSrc,ModelFunctionType::BaseModel); - pSrcPort = pSrc->getPortPtr(index); - - QMap mapPorts = pDest->getPorts(); - - for(auto& port:mapPorts) - { - if(port->getType() == T_lineIn) - { - pDestPort = port; - break; - } - } - - } - else if(pDest->getItemType() == GIT_baseBus) - { - int index = pDest->addPort(p_movable,pDest->mapFromScene(calculateBusPortPos(pDest,pSrc))); - createTopoTerminalsByItem(pDest,ModelFunctionType::BaseModel); - pDestPort = pDest->getPortPtr(index); - - QMap mapPorts = pSrc->getPorts(); - - for(auto& port:mapPorts) - { - if(port->getType() == T_lineOut) - { - pSrcPort = port; - break; - } - } - } - else - { - QMap mapSrc = pSrc->getPorts(); - pSrcPort = nullptr; - for(auto& port:mapSrc) - { - if(port->getType() == T_lineOut) - { - pSrcPort = port; - break; - } - } - - QMap mapDest = pDest->getPorts(); - pDestPort = nullptr; - for(auto& port:mapDest) - { - if(port->getType() == T_lineIn) - { - pDestPort = port; - break; - } - } - } - if(pSrcPort && pDestPort) - { - QPointF srcPortPos = pSrcPort->scenePos(); - QPointF destPortPos = pDestPort->scenePos(); - pItem->setStartPoint(srcPortPos); - pItem->setEndPoint(destPortPos); - pItem->calculatePath(); - - PowerConnection* pCon = TopologyManager::instance().createConnection(pItem->itemId().toString(),pSrcPort->getId(),pDestPort->getId(),pSrc->itemId().toString(),pDest->itemId().toString(),ModelFunctionType::BaseModel); //创建拓扑连接(逻辑) - if(pCon) - pCon->setState(DataState::changed); - pItem->getProperty()->setConnection(Connection(pSrc->itemId(),QUuid(pSrcPort->getId()),pSrcPort->getType(),pSrcPort->portPos(),pDest->itemId(),QUuid(pDestPort->getId()),pDestPort->getType(),pDestPort->portPos())); - } -} - -QPointF FixedPortsModel::calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item) -{ - return QPointF(item->pos().x(),pBus->pos().y()); -} - void FixedPortsModel::showModelDlg(const QString& sName,QUuid uuid,GraphicsProjectModelItem* pItem) { modelStateInfo stateInfo = _modelStateInfo[sName]; @@ -973,37 +802,6 @@ ConfigurationDiagram* FixedPortsModel::getTopologyDiagram() return dynamic_cast(_pEntity); } -void FixedPortsModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem,ModelFunctionType funType) -{ - PowerEntity* pEntity = pItem->entity(); - - if(pEntity) - { - QMap mapPorts = pItem->getPorts(); //创建实体port对应的拓扑port - 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; - } - QPointF f = port->pos(); - TopologyManager::instance().createTerminal(pEntity->id(),terType,"",port->pos(),port->getId(),funType); - } - } -} - void FixedPortsModel::createTopoTerminalsByData(PowerEntity* pParent,QJsonObject componentCon,ModelFunctionType funType) { QJsonArray portsArray = componentCon["port"].toArray(); @@ -1604,7 +1402,7 @@ void FixedPortsModel::addTestData() pLineData->setDataChanged(true); //数据状态改变 } addBaseItem(lineId,pLine); - establishConnection(pBreaker,pBus,pLine); + establishConnection(pBreaker,pBus,pLine,ModelFunctionType::BaseModel); _scene->addItem(pLine); QList lst; diff --git a/diagramCavas/source/topologyManager.cpp b/diagramCavas/source/topologyManager.cpp index c020363..4ceda5a 100644 --- a/diagramCavas/source/topologyManager.cpp +++ b/diagramCavas/source/topologyManager.cpp @@ -23,15 +23,31 @@ void TopologyManager::clearAllData() qDeleteAll(m_connections); m_connections.clear(); m_connectionIndex.clear(); - // 删除所有实体(自动删除子对象) qDeleteAll(m_entities); m_entities.clear(); - m_allTerminals.clear(); //端点由父亲entity释放 + + // 删除所有连接 + qDeleteAll(m_baseConnections); + m_baseConnections.clear(); + m_baseConnectionIndex.clear(); + // 删除所有实体(自动删除子对象) + qDeleteAll(m_baseEntities); + m_baseEntities.clear(); + m_baseAllTerminals.clear(); //端点由父亲entity释放 + + // 删除所有连接 + qDeleteAll(m_editorConnections); + m_editorConnections.clear(); + m_editorConnectionIndex.clear(); + // 删除所有实体(自动删除子对象) + qDeleteAll(m_editorEntities); + m_editorEntities.clear(); + m_editorAllTerminals.clear(); //端点由父亲entity释放 } -PowerEntity* TopologyManager::createEntity(EntityType type,const QString& uuid, const QString& name,ModelFunctionType funType) +PowerEntity* TopologyManager::createEntity(EntityType type,const QString& uuid, const QString& name,ModelFunctionType funType,const QString& block) { if(funType == ModelFunctionType::ProjectModel) { @@ -45,6 +61,9 @@ PowerEntity* TopologyManager::createEntity(EntityType type,const QString& uuid, entity = new PowerComponent(type, uuid,name); } + if(entity == nullptr) + return nullptr; + m_entities.insert(entity->id(), entity); emit entityCreated(entity->id()); // 发送信号通知 return entity; @@ -58,6 +77,23 @@ PowerEntity* TopologyManager::createEntity(EntityType type,const QString& uuid, emit entityCreated(entity->id()); // 发送信号通知 return entity; } + else if(funType == ModelFunctionType::EditorModel) + { + PowerEntity* entity = nullptr; + entity = new PowerComponent(type, uuid,name); + + m_editorEntities.insert(entity->id(), entity); + return entity; + } + else if(funType == ModelFunctionType::BlockEditorModel) + { + PowerEntity* entity = nullptr; + entity = new PowerComponent(type, uuid,name); + entity->setBlock(block); + + m_blockEntities.insert(entity->id(), entity); + return entity; + } return nullptr; } @@ -67,6 +103,10 @@ PowerEntity* TopologyManager::findEntity(const QString& id,ModelFunctionType fun return m_entities.value(id, nullptr); // 避免异常的安全查询 else if(funType == ModelFunctionType::BaseModel) return m_baseEntities.value(id, nullptr); + else if(funType == ModelFunctionType::EditorModel) + return m_editorEntities.value(id, nullptr); + else if(funType == ModelFunctionType::BlockEditorModel) + return m_blockEntities.value(id, nullptr); return nullptr; } @@ -132,9 +172,77 @@ bool TopologyManager::deleteEntity(const QString& id,ModelFunctionType funType) emit entityDeleted(id); return true; } + else if(funType == ModelFunctionType::EditorModel) + { + if (!m_editorEntities.contains(id)) return false; + PowerEntity* entity = m_editorEntities[id]; + + // 步骤1:删除所有相关连接 + auto relatedConns = getConnectionsFor(id,funType); + for (auto conn : relatedConns) { + removeConnection(conn->id(),funType); + } + + // 步骤2:从父节点移除(防止悬空指针) + if (PowerEntity* parent = entity->parent()) { + parent->removeChild(entity); + } + + // 步骤3:递归删除子实体 + auto children = entity->children(); + for (auto child : children) { + deleteEntity(child->id(),funType); // 递归删除 + } + + // 步骤4:从哈希表移除并释放内存 + m_editorEntities.remove(id); + delete entity; // 触发PowerEntity析构函数 + + emit entityDeleted(id); + return true; + } + else if(funType == ModelFunctionType::BlockEditorModel) + { + if (!m_blockEntities.contains(id)) return false; + PowerEntity* entity = m_blockEntities[id]; + + // 步骤1:删除所有相关连接 + auto relatedConns = getConnectionsFor(id,funType); + for (auto conn : relatedConns) { + removeConnection(conn->id(),funType); + } + + // 步骤2:从父节点移除(防止悬空指针) + if (PowerEntity* parent = entity->parent()) { + parent->removeChild(entity); + } + + // 步骤3:递归删除子实体 + auto children = entity->children(); + for (auto child : children) { + deleteEntity(child->id(),funType); // 递归删除 + } + + // 步骤4:从哈希表移除并释放内存 + m_blockEntities.remove(id); + delete entity; // 触发PowerEntity析构函数 + + emit entityDeleted(id); + return true; + } return false; } +QList TopologyManager::getEntitiesByBlock(const QString& str) +{ + QList lst; + for(auto& entity:m_blockEntities){ + if(entity->block() == str){ + lst.append(entity); + } + } + return lst; +} PowerConnection* TopologyManager::createConnection(const QString& connId,const QString& fromTerId, const QString& toTerId,const QString& fromId,const QString& toId,ModelFunctionType funType) { @@ -199,6 +307,66 @@ PowerConnection* TopologyManager::createConnection(const QString& connId,const Q emit connectionCreated(connId); } + else if(funType == ModelFunctionType::EditorModel) + { + // 验证有效性 + if (!m_editorAllTerminals.contains(fromTerId) || + !m_editorAllTerminals.contains(toTerId) || + fromTerId == toTerId) + { + qWarning() << "Invalid connection endpoints"; + return nullptr; + } + + // 防止重复连接 + foreach (auto conn, m_editorConnections) { + if (conn->fromTerminalId() == fromTerId && + conn->toTerminalId() == toTerId) + { + return conn; // 返回已存在的连接 + } + } + + // 创建新连接 + conn = new PowerConnection(connId,fromTerId, toTerId,fromId,toId); + m_editorConnections[connId] = conn; + + // 更新索引 + m_editorConnectionIndex.insert(fromTerId, conn); + m_editorConnectionIndex.insert(toTerId, conn); + + emit connectionCreated(connId); + } + else if(funType == ModelFunctionType::BlockEditorModel) + { + // 验证有效性 + if (!m_blockAllTerminals.contains(fromTerId) || + !m_blockAllTerminals.contains(toTerId) || + fromTerId == toTerId) + { + qWarning() << "Invalid connection endpoints"; + return nullptr; + } + + // 防止重复连接 + foreach (auto conn, m_blockConnections) { + if (conn->fromTerminalId() == fromTerId && + conn->toTerminalId() == toTerId) + { + return conn; // 返回已存在的连接 + } + } + + // 创建新连接 + conn = new PowerConnection(connId,fromTerId, toTerId,fromId,toId); + m_blockConnections[connId] = conn; + + // 更新索引 + m_blockConnectionIndex.insert(fromTerId, conn); + m_blockConnectionIndex.insert(toTerId, conn); + + emit connectionCreated(connId); + } return conn; } @@ -208,6 +376,10 @@ QList TopologyManager::getConnectionsForTerminal(const QString return m_connectionIndex.values(terminalId); else if(funType == ModelFunctionType::BaseModel) return m_baseConnectionIndex.values(terminalId); + else if(funType == ModelFunctionType::EditorModel) + return m_editorConnectionIndex.values(terminalId); + else if(funType == ModelFunctionType::BlockEditorModel) + return m_blockConnectionIndex.values(terminalId); return QList(); } @@ -241,92 +413,84 @@ void TopologyManager::removeConnection(const QString& connId,ModelFunctionType f m_baseConnections.remove(connId); delete conn; + emit connectionRemoved(connId); + } + else if(funType == ModelFunctionType::EditorModel){ + if (!m_editorConnections.contains(connId)) return; + + PowerConnection* conn = m_editorConnections[connId]; + + // 更新索引 + m_editorConnectionIndex.remove(conn->fromTerminalId(), conn); + m_editorConnectionIndex.remove(conn->toTerminalId(), conn); + + // 清理内存 + m_editorConnections.remove(connId); + delete conn; + + emit connectionRemoved(connId); + } + else if(funType == ModelFunctionType::BlockEditorModel){ + if (!m_blockConnections.contains(connId)) return; + + PowerConnection* conn = m_blockConnections[connId]; + + // 更新索引 + m_blockConnectionIndex.remove(conn->fromTerminalId(), conn); + m_blockConnectionIndex.remove(conn->toTerminalId(), conn); + + // 清理内存 + m_blockConnections.remove(connId); + delete conn; + emit connectionRemoved(connId); } } bool TopologyManager::validateConnection(const QString& fromTermId, const QString& toTermId,ModelFunctionType funType) const { + PowerTerminal* fromTerm = nullptr; + PowerTerminal* toTerm = nullptr; if(funType == ModelFunctionType::ProjectModel){ - 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; - } - - // 禁止自连接 - return (fromTerm->parentEntityId() != toTerm->parentEntityId()); + fromTerm = getTerminal(fromTermId); + toTerm = getTerminal(toTermId); } else if(funType == ModelFunctionType::BaseModel){ - PowerTerminal* fromTerm = getTerminal(fromTermId,funType); - PowerTerminal* toTerm = getTerminal(toTermId,funType); - - 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; - } - - // 禁止自连接 - return (fromTerm->parentEntityId() != toTerm->parentEntityId()); + fromTerm = getTerminal(fromTermId,funType); + toTerm = getTerminal(toTermId,funType); } - return false; + else if(funType == ModelFunctionType::EditorModel){ + fromTerm = getTerminal(fromTermId,funType); + toTerm = getTerminal(toTermId,funType); + } + else if(funType == ModelFunctionType::BlockEditorModel){ + fromTerm = getTerminal(fromTermId,funType); + toTerm = getTerminal(toTermId,funType); + } + + 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; + } + + // 禁止自连接 + return (fromTerm->parentEntityId() != toTerm->parentEntityId()); + } -// 连接查询接口 -/*QList TopologyManager::connectionsFrom(const QString& elementId) const -{ - QList res; - 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); - for(auto &val:lst) - { - if(val->toTerminalId() == elementId) - res.append(val); - } - return res; -}*/ - QList TopologyManager::getConnectionsFor(const QString& entityId,ModelFunctionType funType) const { QList lst; @@ -350,6 +514,26 @@ QList TopologyManager::getConnectionsFor(const QString& entity lst.append(con); } } + else if(funType == ModelFunctionType::EditorModel) + { + QList lstTerminal = getTerminalsForEntity(entityId,funType); + for(auto &terminal:lstTerminal) + { + PowerConnection* con = getConnectionContainsTerminal(terminal->id(),funType); + if(con) + lst.append(con); + } + } + else if(funType == ModelFunctionType::BlockEditorModel) + { + QList lstTerminal = getTerminalsForEntity(entityId,funType); + for(auto &terminal:lstTerminal) + { + PowerConnection* con = getConnectionContainsTerminal(terminal->id(),funType); + if(con) + lst.append(con); + } + } return lst; } @@ -359,6 +543,10 @@ PowerConnection* TopologyManager::connection(const QString& conId,ModelFunctionT return m_connections.value(conId,nullptr); else if(funType == ModelFunctionType::BaseModel) return m_baseConnections.value(conId,nullptr); + else if(funType == ModelFunctionType::EditorModel) + return m_editorConnections.value(conId,nullptr); + else if(funType == ModelFunctionType::BlockEditorModel) + return m_blockConnections.value(conId,nullptr); return nullptr; } @@ -378,7 +566,20 @@ PowerConnection* TopologyManager::connection(const QString& fromPin,const QStrin return con; } } - + else if(funType == ModelFunctionType::EditorModel){ + for(auto &con:m_editorConnections) + { + if(con->fromTerminalId() == fromPin && con->toTerminalId() == toPin) + return con; + } + } + else if(funType == ModelFunctionType::BlockEditorModel){ + for(auto &con:m_blockConnections) + { + if(con->fromTerminalId() == fromPin && con->toTerminalId() == toPin) + return con; + } + } return nullptr; } @@ -388,6 +589,10 @@ QHash TopologyManager::getAllConnections(ModelFunction return m_connections; else if(funType == ModelFunctionType::BaseModel) return m_baseConnections; + else if(funType == ModelFunctionType::EditorModel) + return m_editorConnections; + else if(funType == ModelFunctionType::BlockEditorModel) + return m_blockConnections; return QHash(); } @@ -401,6 +606,14 @@ PowerEntity* TopologyManager::getEntity(const QString& id,ModelFunctionType funT auto it = m_baseEntities.find(id); return (it != m_baseEntities.end()) ? it.value() : nullptr; } + else if(funType == ModelFunctionType::EditorModel){ + auto it = m_editorEntities.find(id); + return (it != m_editorEntities.end()) ? it.value() : nullptr; + } + else if(funType == ModelFunctionType::BlockEditorModel){ + auto it = m_blockEntities.find(id); + return (it != m_blockEntities.end()) ? it.value() : nullptr; + } return nullptr; } @@ -421,6 +634,20 @@ QList TopologyManager::findEntitiesByName(const QString& name,Mode } } } + else if(funType == ModelFunctionType::EditorModel){ + foreach (auto entity, m_editorEntities) { + if (entity->name() == name) { + results.append(entity); + } + } + } + else if(funType == ModelFunctionType::BlockEditorModel){ + foreach (auto entity, m_blockEntities) { + if (entity->name() == name) { + results.append(entity); + } + } + } return results; } @@ -539,6 +766,34 @@ PowerTerminal* TopologyManager::createTerminal(const QString& parentEntityId, return term; } + else if(funType == ModelFunctionType::EditorModel){ + if (!m_editorEntities.contains(parentEntityId)) return nullptr; + + PowerTerminal* term = new PowerTerminal(parentEntityId, type, name, relPos, uuid); + m_editorAllTerminals[term->id()] = term; + m_editorTerminalsByEntity[parentEntityId].append(term); + + // 关联到父实体 + if (PowerEntity* parent = getEntity(parentEntityId,funType)) { + parent->addTerminal(term); + } + + return term; + } + else if(funType == ModelFunctionType::BlockEditorModel){ + if (!m_blockEntities.contains(parentEntityId)) return nullptr; + + PowerTerminal* term = new PowerTerminal(parentEntityId, type, name, relPos, uuid); + m_blockAllTerminals[term->id()] = term; + m_blockTerminalsByEntity[parentEntityId].append(term); + + // 关联到父实体 + if (PowerEntity* parent = getEntity(parentEntityId,funType)) { + parent->addTerminal(term); + } + + return term; + } return nullptr; } @@ -577,6 +832,40 @@ bool TopologyManager::deleteTerminal(const QString& terminalId,ModelFunctionType return true; } + else if(funType == ModelFunctionType::EditorModel){ + if (!m_editorAllTerminals.contains(terminalId)) return false; + + PowerTerminal* term = m_editorAllTerminals[terminalId]; + QString parentId = term->parentEntityId(); + + // 从父实体移除 + if (PowerEntity* parent = getEntity(parentId,funType)) { + parent->removeTerminal(terminalId); + } + + // 清理全局存储 + m_editorTerminalsByEntity[parentId].removeAll(term); + m_editorAllTerminals.remove(terminalId); + + return true; + } + else if(funType == ModelFunctionType::BlockEditorModel){ + if (!m_blockAllTerminals.contains(terminalId)) return false; + + PowerTerminal* term = m_blockAllTerminals[terminalId]; + QString parentId = term->parentEntityId(); + + // 从父实体移除 + if (PowerEntity* parent = getEntity(parentId,funType)) { + parent->removeTerminal(terminalId); + } + + // 清理全局存储 + m_blockTerminalsByEntity[parentId].removeAll(term); + m_blockAllTerminals.remove(terminalId); + + return true; + } return false; } @@ -590,6 +879,14 @@ PowerTerminal* TopologyManager::getTerminal(const QString& terminalId,ModelFunct auto it = m_baseAllTerminals.find(terminalId); return (it != m_baseAllTerminals.end()) ? it.value() : nullptr; } + else if(funType == ModelFunctionType::EditorModel){ + auto it = m_editorAllTerminals.find(terminalId); + return (it != m_editorAllTerminals.end()) ? it.value() : nullptr; + } + else if(funType == ModelFunctionType::BlockEditorModel){ + auto it = m_blockAllTerminals.find(terminalId); + return (it != m_blockAllTerminals.end()) ? it.value() : nullptr; + } return nullptr; } @@ -598,6 +895,10 @@ QList TopologyManager::getTerminalsForEntity(const QString& enti return m_terminalsByEntity.value(entityId); else if(funType == ModelFunctionType::BaseModel) return m_baseTerminalsByEntity.value(entityId); + else if(funType == ModelFunctionType::EditorModel) + return m_editorTerminalsByEntity.value(entityId); + else if(funType == ModelFunctionType::BlockEditorModel) + return m_blockTerminalsByEntity.value(entityId); return QList(); } @@ -629,6 +930,32 @@ PowerEntity* TopologyManager::getEntityByTerminal(const QString& terminalId,Mode } } } + else if(funType == ModelFunctionType::EditorModel){ + QHash>::ConstIterator iter; + for(iter = m_editorTerminalsByEntity.begin();iter != m_editorTerminalsByEntity.end();++iter) + { + for(auto &terminal:iter.value()) + { + if(terminal->id() == terminalId) + { + return m_editorEntities[iter.key()]; + } + } + } + } + else if(funType == ModelFunctionType::BlockEditorModel){ + QHash>::ConstIterator iter; + for(iter = m_blockTerminalsByEntity.begin();iter != m_blockTerminalsByEntity.end();++iter) + { + for(auto &terminal:iter.value()) + { + if(terminal->id() == terminalId) + { + return m_blockEntities[iter.key()]; + } + } + } + } return nullptr; } @@ -653,5 +980,23 @@ PowerConnection* TopologyManager::getConnectionContainsTerminal(const QString& t } } } + else if(funType == ModelFunctionType::EditorModel){ + for(auto &con:m_editorConnections) + { + if(con->fromTerminalId() == terminalId || con->toTerminalId() == terminalId) + { + return con; + } + } + } + else if(funType == ModelFunctionType::BlockEditorModel){ + for(auto &con:m_blockConnections) + { + if(con->fromTerminalId() == terminalId || con->toTerminalId() == terminalId) + { + return con; + } + } + } return nullptr; } diff --git a/diagramUtils/include/basePropertyManager.h b/diagramUtils/include/basePropertyManager.h index 824ef58..85268b8 100644 --- a/diagramUtils/include/basePropertyManager.h +++ b/diagramUtils/include/basePropertyManager.h @@ -9,6 +9,7 @@ class BaseProperty; class BaseModelProperty; class BayProperty; +class DiagramEditorItemProperty; class DIAGRAM_DESIGNER_PUBLIC BasePropertyManager : public QObject { @@ -35,6 +36,11 @@ public: BayProperty* findBayData(QUuid); void deleteBayData(QUuid); QMap getBayData() const; + + void insertTempEditorData(QUuid,DiagramEditorItemProperty*); //临时预览对象数据 + DiagramEditorItemProperty* findTempEditorData(QUuid); + void deleteTempEditorData(QUuid); + QMap getTempEditorData() const; signals: void dataCreated(QString uuid); void dataChanged(QString uuid); @@ -44,5 +50,6 @@ private: QMap m_entityData; //工程模实例化元件的唯一数据 QMap m_baseEntityData; //基模实例元件数据 QMap m_bayData; //间隔数据 + QMap m_editorTempData; //编辑时临时预览对象 }; #endif // BASEPROPERTYMANAGER_H diff --git a/diagramUtils/source/basePropertyManager.cpp b/diagramUtils/source/basePropertyManager.cpp index 88201ef..f521917 100644 --- a/diagramUtils/source/basePropertyManager.cpp +++ b/diagramUtils/source/basePropertyManager.cpp @@ -71,7 +71,7 @@ QMap BasePropertyManager::getBaseEntityData() const return m_baseEntityData; } -/************************************************************/ +/*****************************间隔数据*******************************/ void BasePropertyManager::insertBayData(QUuid id,BayProperty* p) { if(!m_bayData.contains(id)) @@ -94,3 +94,27 @@ QMap BasePropertyManager::getBayData() const { return m_bayData; } + +/*****************************临时预览数据*******************************/ +void BasePropertyManager::insertTempEditorData(QUuid id,DiagramEditorItemProperty* p) +{ + if(!m_editorTempData.contains(id)) + m_editorTempData.insert(id,p); +} + +DiagramEditorItemProperty* BasePropertyManager::findTempEditorData(QUuid id) +{ + return m_editorTempData.value(id,nullptr); +} + +void BasePropertyManager::deleteTempEditorData(QUuid id) +{ + DiagramEditorItemProperty* pData = m_editorTempData.value(id,nullptr); + if(pData) + delete pData; +} + +QMap BasePropertyManager::getTempEditorData() const +{ + return m_editorTempData; +}