From 8f152e0b15b3701cbdb6ac93d4e43740e36fdd4d Mon Sep 17 00:00:00 2001 From: baiYue Date: Wed, 6 May 2026 19:48:33 +0800 Subject: [PATCH] optimize editor structure --- common/core_model/constants.h | 27 ++ common/core_model/types.cpp | 2 +- diagramCavas/CMakeLists.txt | 18 ++ .../include/diagramEditor/bayItemFactory.h | 12 + .../include/diagramEditor/busItemFactory.h | 13 + .../include/diagramEditor/dataModel.h | 18 ++ .../diagramEditor/diagramEditorWizard.h | 1 - .../include/diagramEditor/editItemFactory.h | 18 ++ .../include/diagramEditor/editPanel.h | 21 +- .../diagramEditor/hierarchyItemBuilder.h | 26 ++ .../include/diagramEditor/layoutBuilder.h | 61 ++++ .../include/diagramEditor/layoutCalculator.h | 51 ++++ .../include/diagramEditor/layoutData.h | 35 +++ .../include/diagramEditor/transItemFactory.h | 12 + .../diagramEditor/transformerBuilder.h | 26 ++ .../include/graphicsDataModel/baseModel.h | 2 +- .../graphicsDataModel/diagramEditorModel.h | 2 + .../source/diagramEditor/bayItemFactory.cpp | 19 ++ .../source/diagramEditor/busItemFactory.cpp | 22 ++ .../source/diagramEditor/editItemFactory.cpp | 24 ++ .../source/diagramEditor/editPanel.cpp | 219 ++++++++++++--- .../diagramEditor/hierarchyItemBuilder.cpp | 64 +++++ .../source/diagramEditor/layoutBuilder.cpp | 158 +++++++++++ .../source/diagramEditor/layoutCalculator.cpp | 265 ++++++++++++++++++ .../source/diagramEditor/transItemFactory.cpp | 19 ++ .../diagramEditor/transformerBuilder.cpp | 50 ++++ .../source/graphicsDataModel/baseModel.cpp | 43 +-- .../graphicsDataModel/diagramEditorModel.cpp | 42 ++- .../graphicsDataModel/fixedPortsModel.cpp | 28 ++ include/mainwindow.h | 2 + source/mainwindow.cpp | 15 +- 31 files changed, 1234 insertions(+), 81 deletions(-) create mode 100644 diagramCavas/include/diagramEditor/bayItemFactory.h create mode 100644 diagramCavas/include/diagramEditor/busItemFactory.h create mode 100644 diagramCavas/include/diagramEditor/dataModel.h create mode 100644 diagramCavas/include/diagramEditor/editItemFactory.h create mode 100644 diagramCavas/include/diagramEditor/hierarchyItemBuilder.h create mode 100644 diagramCavas/include/diagramEditor/layoutBuilder.h create mode 100644 diagramCavas/include/diagramEditor/layoutCalculator.h create mode 100644 diagramCavas/include/diagramEditor/layoutData.h create mode 100644 diagramCavas/include/diagramEditor/transItemFactory.h create mode 100644 diagramCavas/include/diagramEditor/transformerBuilder.h create mode 100644 diagramCavas/source/diagramEditor/bayItemFactory.cpp create mode 100644 diagramCavas/source/diagramEditor/busItemFactory.cpp create mode 100644 diagramCavas/source/diagramEditor/editItemFactory.cpp create mode 100644 diagramCavas/source/diagramEditor/hierarchyItemBuilder.cpp create mode 100644 diagramCavas/source/diagramEditor/layoutBuilder.cpp create mode 100644 diagramCavas/source/diagramEditor/layoutCalculator.cpp create mode 100644 diagramCavas/source/diagramEditor/transItemFactory.cpp create mode 100644 diagramCavas/source/diagramEditor/transformerBuilder.cpp diff --git a/common/core_model/constants.h b/common/core_model/constants.h index 9f763fe..bb18129 100644 --- a/common/core_model/constants.h +++ b/common/core_model/constants.h @@ -12,4 +12,31 @@ const int H_DIAGRAM_SPACING = 80; const int TRANSFORMER_LEVEL = 999; // 层级结构中变压器所处层级 } +/***********布局计算************/ +namespace LayoutConstants { +// 容器参数 +constexpr double CONTAINER_H_SPACING = 100.0; // 容器水平间距 +constexpr double CONTAINER_V_SPACING = 50.0; // 容器垂直基础间距 +constexpr double BUS_V_SPACING = 50.0; // 双母线垂直间距 + +// 设备参数 +constexpr double BLOCK_H_SPACING = 20.0; // 设备水平间距 +constexpr double BLOCK_V_MARGIN = 20.0; // 设备垂直边距 + +// 变压器参数 +constexpr double TRANSFORMER_START_X = 150.0; // 变压器起始X +constexpr double TRANSFORMER_SPACING = 200.0; // 变压器间距 + +// 默认尺寸 +constexpr double DEFAULT_BLOCK_WIDTH = Constants::EDITOR_ITEM_WIDTH; +constexpr double DEFAULT_BLOCK_HEIGHT = Constants::EDITOR_ITEM_HEIGHT; + +// 图层索引 +namespace Layer { +constexpr int TOP_BAYS = 0; // 上间隔层 +constexpr int BUS1 = 1; // 母线1层 +constexpr int BUS2 = 2; // 母线2层 +constexpr int BOTTOM_BAYS = 3; // 下间隔层 +} +} #endif diff --git a/common/core_model/types.cpp b/common/core_model/types.cpp index 3f53f31..2d1c118 100644 --- a/common/core_model/types.cpp +++ b/common/core_model/types.cpp @@ -5,5 +5,5 @@ const QMap linkType = { }; //类型转换 const QMap typeToProGraphic = { - {0,GIT_node},{1,GIT_bus},{3,GIT_itemRect},{4,GIT_ctGroup},{5,GIT_ptGroup},{6,GIT_ES},{7,GIT_FES},{8,GIT_link},{9,GIT_DS},{10,GIT_DTEDS},{11,GIT_PI},{12,GIT_LA},{13,GIT_cableTer},{14,GIT_cableEnd},{15,GIT_2wTransformer},{16,GIT_3wTransformer} + {0,GIT_node},{1,GIT_bus},{3,GIT_itemRect},{4,GIT_ctGroup},{5,GIT_ptGroup},{6,GIT_ES},{7,GIT_FES},{8,GIT_link},{9,GIT_DS},{10,GIT_DTEDS},{11,GIT_PI},{12,GIT_LA},{13,GIT_cableTer},{14,GIT_cableEnd},{15,GIT_2wTransformer},{16,GIT_3wTransformer},{18,GIT_CustomType} }; diff --git a/diagramCavas/CMakeLists.txt b/diagramCavas/CMakeLists.txt index 9d44d9a..508edb5 100644 --- a/diagramCavas/CMakeLists.txt +++ b/diagramCavas/CMakeLists.txt @@ -78,6 +78,16 @@ set(DIAGRAMCAVAS_HEADER_FILES include/diagramEditor/diagramEditorTransPreviewDlg.h include/diagramEditor/diagramEditorPreviewDlg.h include/diagramEditor/confirmEditorDlg.h + include/diagramEditor/dataModel.h + include/diagramEditor/editItemFactory.h + include/diagramEditor/busItemFactory.h + include/diagramEditor/bayItemFactory.h + include/diagramEditor/transItemFactory.h + include/diagramEditor/hierarchyItemBuilder.h + include/diagramEditor/layoutBuilder.h + include/diagramEditor/transformerBuilder.h + include/diagramEditor/layoutData.h + include/diagramEditor/layoutCalculator.h include/graphicsDataModel/baseModel.h include/graphicsDataModel/fixedPortsModel.h include/graphicsDataModel/diagramEditorModel.h @@ -231,6 +241,14 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/diagramEditor/diagramEditorTransPreviewDlg.cpp source/diagramEditor/diagramEditorPreviewDlg.cpp source/diagramEditor/confirmEditorDlg.cpp + source/diagramEditor/editItemFactory.cpp + source/diagramEditor/busItemFactory.cpp + source/diagramEditor/bayItemFactory.cpp + source/diagramEditor/transItemFactory.cpp + source/diagramEditor/hierarchyItemBuilder.cpp + source/diagramEditor/layoutBuilder.cpp + source/diagramEditor/transformerBuilder.cpp + source/diagramEditor/layoutCalculator.cpp source/graphicsDataModel/baseModel.cpp source/graphicsDataModel/fixedPortsModel.cpp source/graphicsDataModel/diagramEditorModel.cpp diff --git a/diagramCavas/include/diagramEditor/bayItemFactory.h b/diagramCavas/include/diagramEditor/bayItemFactory.h new file mode 100644 index 0000000..33da0d0 --- /dev/null +++ b/diagramCavas/include/diagramEditor/bayItemFactory.h @@ -0,0 +1,12 @@ +// BayItemFactory.h +#pragma once +#include "editItemFactory.h" + +class BayItemFactory : public EditItemFactory { +public: + EditBaseItem* createItem(BlockDataPtr blockData) override; + QGraphicsLinearLayout* createLayerLayout() override; + +protected: + void setupItem(EditBaseItem* item, BlockDataPtr blockData) override; +}; diff --git a/diagramCavas/include/diagramEditor/busItemFactory.h b/diagramCavas/include/diagramEditor/busItemFactory.h new file mode 100644 index 0000000..afa11f2 --- /dev/null +++ b/diagramCavas/include/diagramEditor/busItemFactory.h @@ -0,0 +1,13 @@ +// 具体的工厂实现 +// BusItemFactory.h +#pragma once +#include "editItemFactory.h" + +class BusItemFactory : public EditItemFactory { +public: + EditBaseItem* createItem(BlockDataPtr blockData) override; + QGraphicsLinearLayout* createLayerLayout() override; + +protected: + void setupItem(EditBaseItem* item, BlockDataPtr blockData) override; +}; diff --git a/diagramCavas/include/diagramEditor/dataModel.h b/diagramCavas/include/diagramEditor/dataModel.h new file mode 100644 index 0000000..e7d2a18 --- /dev/null +++ b/diagramCavas/include/diagramEditor/dataModel.h @@ -0,0 +1,18 @@ +// dataModel.h +#pragma once +#include +#include +#include +#include +#include "diagramEditor/diagramEditorBaseBlock.h" + +// 原始类的前置声明 +class DiagramEditorBaseBlock; +class DiagramEditorStructContainer; +class HierarchyItem; + +// 类型别名 +using BlockDataPtr = DiagramEditorBaseBlock*; +using ContainerDataPtr = DiagramEditorStructContainer*; +using BlockMap = QMap>; +using ContainerStructMap = QMap>; diff --git a/diagramCavas/include/diagramEditor/diagramEditorWizard.h b/diagramCavas/include/diagramEditor/diagramEditorWizard.h index 3d2911b..3ad8b31 100644 --- a/diagramCavas/include/diagramEditor/diagramEditorWizard.h +++ b/diagramCavas/include/diagramEditor/diagramEditorWizard.h @@ -2,7 +2,6 @@ #define DIAGRAMEDITORWIZARD_H #include -//#include "global.h" #include "tools.h" #include "common/core_model/diagram.h" diff --git a/diagramCavas/include/diagramEditor/editItemFactory.h b/diagramCavas/include/diagramEditor/editItemFactory.h new file mode 100644 index 0000000..046ca63 --- /dev/null +++ b/diagramCavas/include/diagramEditor/editItemFactory.h @@ -0,0 +1,18 @@ +// dataModel.h +#pragma once +#include "diagramEditor/editItems.h" +#include "diagramEditor/dataModel.h" +#include + +class EditItemFactory { +public: + virtual ~EditItemFactory() = default; + + virtual EditBaseItem* createItem(BlockDataPtr blockData) = 0; + virtual QGraphicsLinearLayout* createLayerLayout() = 0; + + static EditItemFactory* getFactory(int itemType); + +protected: + virtual void setupItem(EditBaseItem* item, BlockDataPtr blockData) = 0; +}; diff --git a/diagramCavas/include/diagramEditor/editPanel.h b/diagramCavas/include/diagramEditor/editPanel.h index c7e5d54..e565fdc 100644 --- a/diagramCavas/include/diagramEditor/editPanel.h +++ b/diagramCavas/include/diagramEditor/editPanel.h @@ -3,7 +3,7 @@ //编辑文本项生成组态图 #include #include -//#include "global.h" +#include "dataModel.h" #include "common/core_model/diagram.h" class EditView; @@ -24,6 +24,15 @@ class DiagramEditorModel; class DiagramEditorPreviewDlg; class ConfirmEditorDlg; class DiagramCavas; +struct HierarchyItem; +class LayoutBuilder; + +enum class ConnectionType { + Unknown, + BusBaySameContainer, // 母线-间隔同容器 + BusBayDiffContainer, // 母线-间隔跨容器 + TransBay // 变压器-间隔 +}; class EditPanel : public QWidget { @@ -63,6 +72,14 @@ private: void calculateContainerWidth(EditContainerItem*); //根据间隔数量计算容器宽度 todo:区分上下间隔 int getContainerBusType(QMap>); //返回容器中母线类型(单双) EditBaseItem* getItemByName(const QString&); //根据名称获取指定item + + void performCleanup(); + void initializeSceneLayout(); + void processAllContainerLevels(const ContainerStructMap& containerStruct); + void processNormalContainerLevel(int level, const QList& containers,LayoutBuilder& builder); + void processTransformerLevel(const QList& containers); + void finalizeConstruction(); + void emitTopologySignals(); signals: void panelDelete(const QString&,int); protected: @@ -79,6 +96,8 @@ private: int _maxWidth; int _maxHeight; QList _lstData; + QList _accumulatedBayItems; + QList _accumulatedDeviceItems; QMap> _mapStruct; DiagramEditorModel* _pModel; DiagramEditorPreviewDlg* _pPreview; diff --git a/diagramCavas/include/diagramEditor/hierarchyItemBuilder.h b/diagramCavas/include/diagramEditor/hierarchyItemBuilder.h new file mode 100644 index 0000000..5b4ea2e --- /dev/null +++ b/diagramCavas/include/diagramEditor/hierarchyItemBuilder.h @@ -0,0 +1,26 @@ +// HierarchyItemBuilder.h +#pragma once +#include "common/core_model/topology.h" +#include "dataModel.h" + +class HierarchyItemBuilder { +public: + static HierarchyItemBuilder& instance(); + + // 创建间隔层级项 + HierarchyItem buildBayItem(BlockDataPtr blockData); + + // 创建设备层级项 + HierarchyItem buildDeviceItem(BlockDataPtr blockData, int deviceType); + + // 创建带父间隔的设备项 + HierarchyItem buildDeviceWithParent(BlockDataPtr deviceBlock, + BlockDataPtr parentBlock, + int deviceType); + + // 根据block类型自动创建对应层级项 + HierarchyItem buildAutoFromBlock(BlockDataPtr blockData); + +private: + HierarchyItemBuilder() = default; +}; diff --git a/diagramCavas/include/diagramEditor/layoutBuilder.h b/diagramCavas/include/diagramEditor/layoutBuilder.h new file mode 100644 index 0000000..939767f --- /dev/null +++ b/diagramCavas/include/diagramEditor/layoutBuilder.h @@ -0,0 +1,61 @@ +// LayoutBuilder.h +#pragma once +#include +#include "editContainerItem.h" +#include "dataModel.h" +#include "common/core_model/topology.h" + +class EditPanel; +class EditBaseItem; + +class LayoutBuilder { +public: + struct BuildResult { + EditContainerItem* container = nullptr; + QList bayItems; + QList deviceItems; + }; + + explicit LayoutBuilder(EditPanel* panel); + virtual ~LayoutBuilder() = default; + + // 构建一个容器 + virtual BuildResult buildContainer(const BlockMap& blockMap); + + // 构建行布局 + static QGraphicsLinearLayout* createRowLayout(); + + // 构建垂直布局 + static QGraphicsLinearLayout* createVerticalLayout(); + + // 构建水平布局 + static QGraphicsLinearLayout* createHorizontalLayout(); + + // 添加间隔占位符 + static EditBaseItem* createSpacerItem(); + + // 为垂直布局添加拉伸 + static void addStretchToVerticalLayout(QGraphicsLinearLayout* layout); + +protected: + EditPanel* m_panel = nullptr; + + // 处理一个Block + virtual EditBaseItem* processBlock(BlockDataPtr block, + QList& bayItems, + QList& deviceItems); + + // 处理一个层的所有Blocks + void processLayer(const QList& blocks, + QGraphicsLinearLayout* layerLayout, + QList& bayItems, + QList& deviceItems); + + // 连接信号 + void connectSignals(EditBaseItem* item); + void connectContainerSignals(EditContainerItem* container); + +protected: + static constexpr int TOTAL_LAYERS = 4; // 总共4层 + static constexpr int MIN_CONTAINER_WIDTH = 100; // 最小容器宽度 +}; diff --git a/diagramCavas/include/diagramEditor/layoutCalculator.h b/diagramCavas/include/diagramEditor/layoutCalculator.h new file mode 100644 index 0000000..925125c --- /dev/null +++ b/diagramCavas/include/diagramEditor/layoutCalculator.h @@ -0,0 +1,51 @@ +// LayoutCalculator.h +#pragma once +#include "layoutData.h" +#include "common/core_model/constants.h" + +class DiagramEditorWizard; +class DiagramEditorBaseBlock; +class DiagramEditorStructContainer; + +class FixedLayoutCalculator { +public: + struct LevelLayout { + int level = 0; + double maxUpHeight = 0; // 整行最大上高度 + double maxDownHeight = 0; // 整行最大下高度 + double startY = 0; // 行起始Y + QList containers; + }; + + explicit FixedLayoutCalculator(DiagramEditorWizard* wizard); + + QMap calculateLayout(); + +private: + // 第一阶段:计算尺寸 + void calculateContainerSizes(LevelLayout& levelLayout); + + // 第二阶段:计算位置 + void calculatePositions(LevelLayout& levelLayout, double& deltaY, double& lastMaxDownH); + + // 计算单个容器的设备位置 + void calculateBlockPositionsInContainer(DiagramEditorStructContainer* container, + double startX, + double midUpY, + double midDownY); + + // 计算变压器位置 + void calculateTransformerPositions(const QList& transformers, + double& deltaY, double& lastMaxDownH); + +private: + DiagramEditorWizard* m_wizard = nullptr; + QMap m_blockPositions; + + // 全局常量 + const double BUS_V_SPACING = 50.0; // 母线1和母线2间距 + const double CONTAINER_H_SPACING = 100.0; // 容器水平间距 + const double CONTAINER_START_X = 50.0; // 容器起始X + const double TRANSFORMER_START_X = 150.0; // 变压器起始X + const double TRANSFORMER_SPACING = 200.0; // 变压器间距 +}; diff --git a/diagramCavas/include/diagramEditor/layoutData.h b/diagramCavas/include/diagramEditor/layoutData.h new file mode 100644 index 0000000..6e52a0f --- /dev/null +++ b/diagramCavas/include/diagramEditor/layoutData.h @@ -0,0 +1,35 @@ +// LayoutData.h +#pragma once +#include +#include +#include + +class DiagramEditorBaseBlock; +class DiagramEditorStructContainer; + +struct ContainerLayout { + double width = 0; + double height = 0; + double maxUpHeight = 0; // 上间隔最大高度 + double maxDownHeight = 0; // 下间隔最大高度 + double startX = 0; // 容器起始X + double startY = 0; // 容器起始Y + double midUpY = 0; // 母线1中心Y + double midDownY = 0; // 母线2中心Y + QMap blockPositions; // 设备位置 +}; + +struct RowLayout { + int level = 0; + double topY = 0; // 行顶部Y + double height = 0; // 行高度 + double width = 0; // 行宽度 + QList containers; + bool isTransformerRow = false; +}; + +struct LayoutResult { + QMap rows; // 各层级布局 + QMap allBlockPositions; // 所有设备位置 + QMap containerLayouts; // 容器布局 +}; diff --git a/diagramCavas/include/diagramEditor/transItemFactory.h b/diagramCavas/include/diagramEditor/transItemFactory.h new file mode 100644 index 0000000..28083b2 --- /dev/null +++ b/diagramCavas/include/diagramEditor/transItemFactory.h @@ -0,0 +1,12 @@ +// TransItemFactory.h +#pragma once +#include "editItemFactory.h" + +class TransItemFactory : public EditItemFactory { +public: + EditBaseItem* createItem(BlockDataPtr blockData) override; + QGraphicsLinearLayout* createLayerLayout() override; + +protected: + void setupItem(EditBaseItem* item, BlockDataPtr blockData) override; +}; diff --git a/diagramCavas/include/diagramEditor/transformerBuilder.h b/diagramCavas/include/diagramEditor/transformerBuilder.h new file mode 100644 index 0000000..91ca943 --- /dev/null +++ b/diagramCavas/include/diagramEditor/transformerBuilder.h @@ -0,0 +1,26 @@ +// TransformerBuilder.h +#pragma once +#include "layoutBuilder.h" + +class TransformerBuilder : public LayoutBuilder { +public: + explicit TransformerBuilder(EditPanel* panel); + + // 重写容器构建方法 + BuildResult buildContainer(const BlockMap& blockMap) override; + + // 创建变压器行布局 + QGraphicsLinearLayout* createTransformerRowLayout(); + + // 处理变压器的层级项 + HierarchyItem buildTransformerHierarchyItem(BlockDataPtr blockData); + +private: + // 处理变压器的特殊逻辑 + void processTransformerBlock(BlockDataPtr block, + QList& bayItems, + QList& deviceItems); + + static constexpr int TRANSFORMER_TYPE = 3; + static constexpr int TRANSFORMER_DEVICE_TYPE = 16; +}; diff --git a/diagramCavas/include/graphicsDataModel/baseModel.h b/diagramCavas/include/graphicsDataModel/baseModel.h index 39b9316..38fd2b5 100644 --- a/diagramCavas/include/graphicsDataModel/baseModel.h +++ b/diagramCavas/include/graphicsDataModel/baseModel.h @@ -20,7 +20,7 @@ class BaseModel : public QObject Q_OBJECT public: void createTopoTerminalsByItem(GraphicsBaseItem*,ModelFunctionType funType = ModelFunctionType::ProjectModel); //通过图形对象创建port接线点(新建) - QPointF calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item); //计算母线上接线点位置 + QPointF calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item,QPointF para = QPointF(0,0)); //计算母线上接线点位置 template void establishConnection(GraphicsBaseItem*,GraphicsBaseItem*,TypeLine*,ModelFunctionType,int nMode=0,int nParam = 0); //在两个item之间建立连接 nMode:0正常1变压器中性点2变压器 nParam附加参数:中性点中表示需连接的位置(012高中低) double distanceBetweenItems(QGraphicsItem* item1, QGraphicsItem* item2) { QPointF center1 = item1->mapToScene(item1->boundingRect().center()); diff --git a/diagramCavas/include/graphicsDataModel/diagramEditorModel.h b/diagramCavas/include/graphicsDataModel/diagramEditorModel.h index ac955b2..319ca78 100644 --- a/diagramCavas/include/graphicsDataModel/diagramEditorModel.h +++ b/diagramCavas/include/graphicsDataModel/diagramEditorModel.h @@ -5,6 +5,7 @@ #include #include "common/core_model/diagram.h" #include "common/core_model/topology.h" +#include "diagramEditor/layoutData.h" class GraphicsBaseModelItem; class DiagramEditorItemProperty; @@ -48,6 +49,7 @@ public: void calculateBlockPos(); //重新计算block位置 void setItemInBlockPos(); //设置block中的item位置 void refreshConnection(); //刷新连接线 + void applyLayoutResult(const LayoutResult& result); void setCurBayRouteModel(QStandardItemModel* p) {_pCurBayRoute = p;} QStandardItemModel* getCurBayRouteModel() {return _pCurBayRoute;} diff --git a/diagramCavas/source/diagramEditor/bayItemFactory.cpp b/diagramCavas/source/diagramEditor/bayItemFactory.cpp new file mode 100644 index 0000000..7bf6c58 --- /dev/null +++ b/diagramCavas/source/diagramEditor/bayItemFactory.cpp @@ -0,0 +1,19 @@ +// BusItemFactory.cpp +#include "diagramEditor/bayItemFactory.h" +#include "common/core_model/constants.h" + +EditBaseItem* BayItemFactory::createItem(BlockDataPtr blockData) { + auto pBay = new EditBayItem(); + setupItem(pBay, blockData); + return pBay; +} + +QGraphicsLinearLayout* BayItemFactory::createLayerLayout() { + return new QGraphicsLinearLayout(Qt::Horizontal); +} + +void BayItemFactory::setupItem(EditBaseItem* item, BlockDataPtr blockData) { + item->setType(EditorItemType::bay); + item->setBoundingRect(QRectF(0, 0, + Constants::EDITOR_ITEM_WIDTH, Constants::EDITOR_ITEM_HEIGHT)); +} diff --git a/diagramCavas/source/diagramEditor/busItemFactory.cpp b/diagramCavas/source/diagramEditor/busItemFactory.cpp new file mode 100644 index 0000000..ddd3484 --- /dev/null +++ b/diagramCavas/source/diagramEditor/busItemFactory.cpp @@ -0,0 +1,22 @@ +// BusItemFactory.cpp +#include "diagramEditor/busItemFactory.h" +#include "common/core_model/constants.h" + +EditBaseItem* BusItemFactory::createItem(BlockDataPtr blockData) { + auto pBus = new EditBusItem(); + setupItem(pBus, blockData); + return pBus; +} + +QGraphicsLinearLayout* BusItemFactory::createLayerLayout() { + auto layout = new QGraphicsLinearLayout(Qt::Horizontal); + layout->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + layout->setPreferredHeight(10); + return layout; +} + +void BusItemFactory::setupItem(EditBaseItem* item, BlockDataPtr blockData) { + item->setType(EditorItemType::bus); + item->setBoundingRect(QRectF(0, 0, + Constants::EDITOR_ITEM_WIDTH, Constants::EDITOR_ITEM_HEIGHT)); +} diff --git a/diagramCavas/source/diagramEditor/editItemFactory.cpp b/diagramCavas/source/diagramEditor/editItemFactory.cpp new file mode 100644 index 0000000..a414ed1 --- /dev/null +++ b/diagramCavas/source/diagramEditor/editItemFactory.cpp @@ -0,0 +1,24 @@ +// EditItemFactory.cpp - 工厂管理器 +#include "diagramEditor/editItemFactory.h" +#include "diagramEditor/busItemFactory.h" +#include "diagramEditor/bayItemFactory.h" +#include "diagramEditor/transItemFactory.h" +#include +#include + +EditItemFactory* EditItemFactory::getFactory(int itemType) { + static std::map> factories; + + // 延迟初始化 + if (factories.empty()) { + factories[1] = std::make_unique(); + factories[2] = std::make_unique(); + factories[3] = std::make_unique(); + } + + auto it = factories.find(itemType); + if (it != factories.end()) { + return it->second.get(); + } + return nullptr; +} diff --git a/diagramCavas/source/diagramEditor/editPanel.cpp b/diagramCavas/source/diagramEditor/editPanel.cpp index d8073e2..48964ea 100644 --- a/diagramCavas/source/diagramEditor/editPanel.cpp +++ b/diagramCavas/source/diagramEditor/editPanel.cpp @@ -21,9 +21,10 @@ #include "diagramEditor/confirmEditorDlg.h" #include "projectManager.h" #include "diagramCavas.h" -//#include "global.h" #include "common/core_model/constants.h" #include "basePropertyManager.h" +#include "diagramEditor/transformerBuilder.h" +#include "diagramEditor/layoutBuilder.h" #include EditPanel::EditPanel(QWidget *parent) @@ -60,20 +61,18 @@ EditPanel::~EditPanel() void EditPanel::initByWizardInfo() { - QList lstBay; + /*QList lstBay; QList lstItem; - //if(!_lstData.empty() || !_pModel->getPreviewItem().empty()){ - _pModel->clearItems(); - m_pEditScene->clear(); - _lstData.clear(); - _mainWidget = new EditMainRect; - _widgetLayout = new QGraphicsLinearLayout(Qt::Vertical); - _widgetLayout->setSpacing(40); - _mainWidget->setLayout(_widgetLayout); - m_pEditScene->addItem(_mainWidget); - _mainWidget->setGeometry(m_pEditScene->sceneRect()); - BasePropertyManager::instance().clearEditorData(); - //} + _pModel->clearItems(); + m_pEditScene->clear(); + _lstData.clear(); + _mainWidget = new EditMainRect; + _widgetLayout = new QGraphicsLinearLayout(Qt::Vertical); + _widgetLayout->setSpacing(40); + _mainWidget->setLayout(_widgetLayout); + m_pEditScene->addItem(_mainWidget); + _mainWidget->setGeometry(m_pEditScene->sceneRect()); + BasePropertyManager::instance().clearEditorData(); auto& mapTotal = _pEditorWizard->getContainerStruct(); for(auto iter = mapTotal.begin();iter != mapTotal.end();++iter){ if(iter.key() == Constants::TRANSFORMER_LEVEL) @@ -145,11 +144,6 @@ void EditPanel::initByWizardInfo() pBay->setBoundingRect(QRectF(0,0,Constants::EDITOR_ITEM_WIDTH,Constants::EDITOR_ITEM_HEIGHT)); pItem = pBay; } - /*else if(nType == 3){ //变压器 - auto pTrans = new EditTransItem(); - pTrans->setType(EditorItemType::Trans); - pItem = pTrans; - }*/ if(pItem){ HierarchyItem bayInfo; //间隔层级 @@ -169,7 +163,6 @@ void EditPanel::initByWizardInfo() } } if(mapBlock.value(0).isEmpty()){ //为空则添加间距 - //layV->insertStretch(0); QGraphicsLinearLayout* layH = new QGraphicsLinearLayout(Qt::Horizontal); //container中每一层的布局 layV->insertItem(0,layH); auto pSpace = new EditBaseItem(); @@ -179,7 +172,6 @@ void EditPanel::initByWizardInfo() } if(mapBlock.value(3).isEmpty()){ //为空则添加间距 - //layV->addStretch(); QGraphicsLinearLayout* layH = new QGraphicsLinearLayout(Qt::Horizontal); //container中每一层的布局 layV->insertItem(3,layH); auto pSpace = new EditBaseItem(); @@ -198,13 +190,8 @@ void EditPanel::initByWizardInfo() calculateContainerWidth(pContain); - /*int n = getContainerBusType(mapBlock); - if(n == 1){ - layoutRowData->setMaximumHeight(210); - }*/ } _lstData.append(pRow); - //layoutRowData->addStretch(); _widgetLayout->addItem(layoutRowData); if(iter.key() == 0){ //若设置了变压器,直接插入到第一行下方 @@ -303,7 +290,19 @@ void EditPanel::initByWizardInfo() QTimer::singleShot(300, [&]() { // 1000 毫秒 = 1 秒 qDebug() << "一次性定时器触发!"; initBlockConnection(); - }); + });*/ + // 阶段1: 清理和初始化 + performCleanup(); + initializeSceneLayout(); + + // 阶段2: 获取数据 + const auto& containerStruct = _pEditorWizard->getContainerStruct(); + + // 阶段3: 处理所有层级 + processAllContainerLevels(containerStruct); + + // 阶段4: 完成构建 + finalizeConstruction(); } void EditPanel::initBlockConnection() @@ -324,13 +323,6 @@ void EditPanel::initBlockConnection() auto pItem1 = getItemByName(item1->getName()); auto pItem2 = getItemByName(item2->getName()); - /*QRectF rect1 = pItem1->geometry(); - QRectF rect2 = pItem2->geometry(); - - QPointF center1 = pItem1->mapToScene(rect1.center()); - QPointF center2 = pItem2->mapToScene(rect2.center());*/ - - EditLineItem* pLine = new EditLineItem(); pLine->setName(con.uid.toString()); @@ -436,7 +428,6 @@ void EditPanel::initBlockConnection() } } } - } } } @@ -673,3 +664,161 @@ void EditPanel::loadBaseSetting(QUuid uid) _pModel->setWizardInfo(info.context); } } + +void EditPanel::performCleanup() { + // 清理模型 + if (_pModel) { + _pModel->clearItems(); + } + + // 清理场景 + if (m_pEditScene) { + m_pEditScene->clear(); + } + + // 清理数据 + qDeleteAll(_lstData); + _lstData.clear(); + _accumulatedBayItems.clear(); + _accumulatedDeviceItems.clear(); + + // 清理主部件 + _mainWidget = nullptr; + _widgetLayout = nullptr; + + // 清理属性管理器 + BasePropertyManager::instance().clearEditorData(); +} + +void EditPanel::initializeSceneLayout() { + _mainWidget = new EditMainRect; + _widgetLayout = new QGraphicsLinearLayout(Qt::Vertical); + _widgetLayout->setSpacing(40); + _mainWidget->setLayout(_widgetLayout); + m_pEditScene->addItem(_mainWidget); + _mainWidget->setGeometry(m_pEditScene->sceneRect()); +} + +void EditPanel::processAllContainerLevels(const ContainerStructMap& containerStruct) { + // 普通层级构建器 + LayoutBuilder normalBuilder(this); + + // 按顺序处理所有层级 + auto keys = containerStruct.keys(); + std::sort(keys.begin(), keys.end()); + + for (int level : keys) { + if (level == Constants::TRANSFORMER_LEVEL) { + // 特殊处理变压器层级 + processTransformerLevel(containerStruct.value(level)); + } else { + // 处理普通层级 + processNormalContainerLevel(level, containerStruct.value(level), normalBuilder); + + // 如果当前是层级0,且存在变压器层级,在之后插入变压器 + if (level == 0 && containerStruct.contains(Constants::TRANSFORMER_LEVEL)) { + int transformerIndex = keys.indexOf(Constants::TRANSFORMER_LEVEL); + if (transformerIndex > 0) { // 变压器在后面 + continue; // 会在遍历到时处理 + } else if (transformerIndex < 0) { // 变压器不存在于keys中 + processTransformerLevel(containerStruct.value(Constants::TRANSFORMER_LEVEL)); + } + } + } + } +} + +void EditPanel::processNormalContainerLevel(int level, + const QList& containers, + LayoutBuilder& builder) { + if (containers.isEmpty()) return; + + // 创建行 + auto rowLayout = builder.createRowLayout(); + auto rowData = new EditRowData(); + rowData->setId(QString::number(level)); + + // 处理该层级的所有容器 + for (auto container : containers) { + if (!container) continue; + + const auto& blockMap = container->getBlockMap(); + auto result = builder.buildContainer(blockMap); + + if (result.container) { + rowLayout->addItem(result.container); + } + + // 累积层级项 + _accumulatedBayItems.append(result.bayItems); + _accumulatedDeviceItems.append(result.deviceItems); + } + + // 保存行数据 + _lstData.append(rowData); + _widgetLayout->addItem(rowLayout); +} + +void EditPanel::processTransformerLevel(const QList& containers) { + if (containers.isEmpty()) return; + + // 使用变压器专用构建器 + TransformerBuilder transformerBuilder(this); + + // 创建变压器行 + auto rowLayout = transformerBuilder.createTransformerRowLayout(); + auto rowData = new EditRowData(); + rowData->setId(QString::number(Constants::TRANSFORMER_LEVEL)); + + // 处理所有变压器容器 + for (auto container : containers) { + if (!container) continue; + + const auto& blockMap = container->getBlockMap(); + auto result = transformerBuilder.buildContainer(blockMap); + + if (result.container) { + rowLayout->addItem(result.container); + } + + // 累积变压器层级项 + _accumulatedBayItems.append(result.bayItems); + _accumulatedDeviceItems.append(result.deviceItems); + } + + // 插入变压器行(在层级0之后) + _lstData.append(rowData); + + // 找到层级0的位置,在它之后插入变压器 + int insertPosition = 1; // 默认在第一个之后 + for (int i = 0; i < _widgetLayout->count(); ++i) { + if (i < _lstData.size() && _lstData[i]->getId() == "0") { + insertPosition = i + 1; + break; + } + } + + _widgetLayout->insertItem(insertPosition, rowLayout); +} + +void EditPanel::finalizeConstruction() { + // 添加最后的拉伸 + _widgetLayout->addStretch(); + + // 发射拓扑更新信号 + emitTopologySignals(); + + // 延迟初始化连接 + QTimer::singleShot(300, this, &EditPanel::initBlockConnection); +} + +void EditPanel::emitTopologySignals() { + if (_pModel) { + emit _pModel->updateTopologyItems(_accumulatedBayItems, true, false); + emit _pModel->updateTopologyItems(_accumulatedDeviceItems, false, false); + } + + // 清空累积的数据 + _accumulatedBayItems.clear(); + _accumulatedDeviceItems.clear(); +} diff --git a/diagramCavas/source/diagramEditor/hierarchyItemBuilder.cpp b/diagramCavas/source/diagramEditor/hierarchyItemBuilder.cpp new file mode 100644 index 0000000..a760bfe --- /dev/null +++ b/diagramCavas/source/diagramEditor/hierarchyItemBuilder.cpp @@ -0,0 +1,64 @@ +// HierarchyItemBuilder.cpp +#include "diagramEditor/hierarchyItemBuilder.h" + +HierarchyItemBuilder& HierarchyItemBuilder::instance() { + static HierarchyItemBuilder instance; + return instance; +} + +HierarchyItem HierarchyItemBuilder::buildBayItem(BlockDataPtr blockData) { + if (!blockData) return {}; + + HierarchyItem item; + item.item.nEquipType = 0; // 间隔的设备类型为0 + item.item.nCategory = 1; // 类别为1表示间隔 + item.item.sName = blockData->getName(); + item.item.uid = blockData->getId(); + item.item.sVoltageLevel = QString::number(blockData->getVoltage()); + return item; +} + +HierarchyItem HierarchyItemBuilder::buildDeviceItem(BlockDataPtr blockData, int deviceType) { + if (!blockData) return {}; + + HierarchyItem item; + item.item.nEquipType = deviceType; + item.item.nCategory = 0; // 类别为0表示设备 + item.item.sName = blockData->getName(); + item.item.uid = blockData->getId(); + item.item.sVoltageLevel = QString::number(blockData->getVoltage()); + return item; +} + +HierarchyItem HierarchyItemBuilder::buildDeviceWithParent(BlockDataPtr deviceBlock, + BlockDataPtr parentBlock, + int deviceType) { + if (!deviceBlock) return {}; + + HierarchyItem item = buildDeviceItem(deviceBlock, deviceType); + + if (parentBlock) { + item.parent.nEquipType = 0; + item.parent.nCategory = 1; + item.parent.sName = parentBlock->getName(); + item.parent.uid = parentBlock->getId(); + item.parent.sVoltageLevel = QString::number(parentBlock->getVoltage()); + } + return item; +} + +HierarchyItem HierarchyItemBuilder::buildAutoFromBlock(BlockDataPtr blockData) { + if (!blockData) return {}; + + int blockType = blockData->getType(); + switch (blockType) { + case 1: // 母线 + return buildDeviceWithParent(blockData, blockData, 1); + case 2: // 间隔 + return buildBayItem(blockData); + case 3: // 变压器 + return buildDeviceWithParent(blockData, blockData, 16); + default: + return {}; + } +} diff --git a/diagramCavas/source/diagramEditor/layoutBuilder.cpp b/diagramCavas/source/diagramEditor/layoutBuilder.cpp new file mode 100644 index 0000000..d299ad0 --- /dev/null +++ b/diagramCavas/source/diagramEditor/layoutBuilder.cpp @@ -0,0 +1,158 @@ +// LayoutBuilder.cpp +#include "diagramEditor/layoutBuilder.h" +#include "diagramEditor/editItemFactory.h" +#include "diagramEditor/hierarchyItemBuilder.h" +#include "common/core_model/constants.h" +#include "diagramEditor/editPanel.h" + +#include + +LayoutBuilder::LayoutBuilder(EditPanel* panel) + : m_panel(panel) {} + +LayoutBuilder::BuildResult LayoutBuilder::buildContainer(const BlockMap& blockMap) { + BuildResult result; + + // 1. 创建容器 + result.container = new EditContainerItem(); + result.container->setMinimumWidth(Constants::EDITOR_ITEM_WIDTH + 40); + result.container->setId(QUuid::createUuid().toString()); + + // 2. 连接容器信号 + connectContainerSignals(result.container); + + // 3. 创建垂直布局 + auto verticalLayout = createVerticalLayout(); + result.container->setLayout(verticalLayout); + + // 4. 处理每一层 + for (int layerIndex = 0; layerIndex < TOTAL_LAYERS; ++layerIndex) { + auto blocks = blockMap.value(layerIndex); + auto layerLayout = createHorizontalLayout(); + verticalLayout->addItem(layerLayout); + + if (blocks.isEmpty()) { + // 空层添加占位符 + layerLayout->addItem(createSpacerItem()); + } else { + // 处理有Blocks的层 + processLayer(blocks, layerLayout, result.bayItems, result.deviceItems); + } + } + + // 5. 添加拉伸 + addStretchToVerticalLayout(verticalLayout); + + return result; +} + +EditBaseItem* LayoutBuilder::processBlock(BlockDataPtr block, + QList& bayItems, + QList& deviceItems) { + if (!block) return nullptr; + + // 1. 通过工厂创建Item + auto factory = EditItemFactory::getFactory(block->getType()); + if (!factory) { + qWarning() << "No factory found for block type:" << block->getType(); + return nullptr; + } + + auto editItem = factory->createItem(block); + if (!editItem) { + qWarning() << "Failed to create item for block type:" << block->getType(); + return nullptr; + } + + // 2. 设置Item属性 + editItem->setName(block->getName()); + // 注意:这里使用原始指针,不涉及所有权转移 + editItem->setBlockData(block); + + // 3. 连接信号 + connectSignals(editItem); + + // 4. 构建层级项 + int blockType = block->getType(); + switch (blockType) { + case 1: // 母线 + bayItems.append(HierarchyItemBuilder::instance().buildBayItem(block)); + deviceItems.append(HierarchyItemBuilder::instance().buildDeviceWithParent(block, block, 1)); + break; + case 2: // 间隔 + bayItems.append(HierarchyItemBuilder::instance().buildBayItem(block)); + break; + case 3: // 变压器 + // 变压器不创建bayItem,但会创建deviceItem + deviceItems.append(HierarchyItemBuilder::instance().buildDeviceWithParent(block, block, 16)); + break; + } + + return editItem; +} + +void LayoutBuilder::processLayer(const QList& blocks, + QGraphicsLinearLayout* layerLayout, + QList& bayItems, + QList& deviceItems) { + if (!layerLayout) return; + + for (auto block : blocks) { + auto editItem = processBlock(block, bayItems, deviceItems); + if (editItem) { + layerLayout->addItem(editItem); + } + } +} + +void LayoutBuilder::connectSignals(EditBaseItem* item) { + if (!m_panel || !item) return; + + QObject::connect(item, &EditBaseItem::itemDbClicked, + m_panel, &EditPanel::onItemDbClicked); +} + +void LayoutBuilder::connectContainerSignals(EditContainerItem* container) { + if (!m_panel || !container) return; + + QObject::connect(container, &EditContainerItem::containerSizeChange, + m_panel, &EditPanel::onContainerSizeChanged); +} + +QGraphicsLinearLayout* LayoutBuilder::createRowLayout() { + auto layout = new QGraphicsLinearLayout(Qt::Horizontal); + layout->setSpacing(20); + layout->setMaximumHeight(300); + return layout; +} + +QGraphicsLinearLayout* LayoutBuilder::createVerticalLayout() { + auto layout = new QGraphicsLinearLayout(Qt::Vertical); + layout->setSpacing(10); + layout->setMinimumHeight(260); + return layout; +} + +QGraphicsLinearLayout* LayoutBuilder::createHorizontalLayout() { + return new QGraphicsLinearLayout(Qt::Horizontal); +} + +EditBaseItem* LayoutBuilder::createSpacerItem() { + auto spacer = new EditBaseItem(); + spacer->setType(EditorItemType::None); + spacer->setBoundingRect(QRectF(0, 0, + Constants::EDITOR_ITEM_WIDTH, Constants::EDITOR_ITEM_HEIGHT)); + return spacer; +} + +void LayoutBuilder::addStretchToVerticalLayout(QGraphicsLinearLayout* layout) { + if (!layout) return; + + int count = layout->count(); + if (count == 4) { + layout->insertStretch(3); + layout->insertStretch(1); + } else if (count == 2) { + layout->insertStretch(1); + } +} diff --git a/diagramCavas/source/diagramEditor/layoutCalculator.cpp b/diagramCavas/source/diagramEditor/layoutCalculator.cpp new file mode 100644 index 0000000..6549bf2 --- /dev/null +++ b/diagramCavas/source/diagramEditor/layoutCalculator.cpp @@ -0,0 +1,265 @@ +// LayoutCalculator.cpp +#include "diagramEditor/layoutCalculator.h" +#include "diagramEditor/diagramEditorWizard.h" +#include "diagramEditor/diagramEditorStructContainer.h" +#include "diagramEditor/diagramEditorBaseBlock.h" +#include + +FixedLayoutCalculator::FixedLayoutCalculator(DiagramEditorWizard* wizard) + : m_wizard(wizard) {} + +QMap FixedLayoutCalculator::calculateLayout() { + m_blockPositions.clear(); + + if (!m_wizard) { + qWarning() << "FixedLayoutCalculator: Wizard为空"; + return m_blockPositions; + } + + auto mapTotal = m_wizard->getContainerStruct(); + double deltaY = 0; + double lastMaxDownH = 0; + + // 按层级顺序处理 + for (auto iter = mapTotal.begin(); iter != mapTotal.end(); ++iter) { + int level = iter.key(); + + if (level == Constants::TRANSFORMER_LEVEL) { + continue; // 变压器特殊处理 + } + + // 创建层级布局 + LevelLayout levelLayout; + levelLayout.level = level; + levelLayout.containers = iter.value(); + + if (levelLayout.containers.isEmpty()) { + continue; + } + + // 第一阶段:计算尺寸 + calculateContainerSizes(levelLayout); + + // 第二阶段:计算位置 + calculatePositions(levelLayout, deltaY, lastMaxDownH); + + // 处理变压器(在层级0之后) + if (level == 0 && mapTotal.contains(Constants::TRANSFORMER_LEVEL)) { + auto transformers = mapTotal.value(Constants::TRANSFORMER_LEVEL); + if (!transformers.isEmpty()) { + calculateTransformerPositions(transformers, deltaY, lastMaxDownH); + } + } + } + + return m_blockPositions; +} + +void FixedLayoutCalculator::calculateContainerSizes(LevelLayout& levelLayout) { + levelLayout.maxUpHeight = 0; + levelLayout.maxDownHeight = 0; + + for (auto container : levelLayout.containers) { + if (!container) continue; + + auto mapBlocks = container->getBlockMap(); + + // 计算上间隔尺寸 + auto topBays = mapBlocks.value(0); + double maxUp = 0; + double widthUp = 0; + + for (auto block : topBays) { + if (!block) continue; + QRectF rec = block->getRecSize(); + maxUp = qMax(maxUp, rec.height()); + widthUp += 100 + rec.width(); + } + maxUp += Constants::EDITOR_ITEM_HEIGHT; + levelLayout.maxUpHeight = qMax(levelLayout.maxUpHeight, maxUp); + + // 计算下间隔尺寸 + auto bottomBays = mapBlocks.value(3); + double maxDown = 0; + double widthDown = 0; + + for (auto block : bottomBays) { + if (!block) continue; + QRectF rec = block->getRecSize(); + maxDown = qMax(maxDown, rec.height()); + widthDown += 100 + rec.width(); + } + maxDown += Constants::EDITOR_ITEM_HEIGHT; + levelLayout.maxDownHeight = qMax(levelLayout.maxDownHeight, maxDown); + + // 计算母线宽度 + double busWidth = 0; + auto bus1 = mapBlocks.value(1); + auto bus2 = mapBlocks.value(2); + + if (!bus1.isEmpty()) { + busWidth = qMax(busWidth, bus1.first()->getRecSize().width()); + } + if (!bus2.isEmpty()) { + busWidth = qMax(busWidth, bus2.first()->getRecSize().width()); + } + + // 计算容器宽度 + double containerWidth = qMax(widthUp, widthDown); + if (containerWidth < busWidth) { + containerWidth = busWidth; + } + + // 设置容器尺寸 + container->setWidth(containerWidth); + } + + // 处理空的情况 + if (levelLayout.maxUpHeight == 0) { + levelLayout.maxUpHeight = Constants::EDITOR_ITEM_HEIGHT; + } + if (levelLayout.maxDownHeight == 0) { + levelLayout.maxDownHeight = Constants::EDITOR_ITEM_HEIGHT; + } +} + +void FixedLayoutCalculator::calculatePositions(LevelLayout& levelLayout, + double& deltaY, double& lastMaxDownH) { + double startX = CONTAINER_START_X; + bool isFirstContainer = true; + + for (auto container : levelLayout.containers) { + if (!container) continue; + + // 设置容器高度 + container->setMaxUpH(levelLayout.maxUpHeight); + container->setMaxDownH(levelLayout.maxDownHeight); + + // 计算垂直位置(每行第一个容器计算一次) + if (isFirstContainer) { + if (levelLayout.level == 0) { // 首行 + deltaY = container->getMaxUpH(); + } else { // 其他行 + deltaY = deltaY + BUS_V_SPACING + lastMaxDownH + container->getMaxUpH(); + } + lastMaxDownH = container->getMaxDownH(); + isFirstContainer = false; + } + + // 设置容器的关键Y坐标 + container->setMidUpY(deltaY); + container->setMidDownY(deltaY + BUS_V_SPACING); + container->setStartX(startX); + + // 计算容器内设备位置 + calculateBlockPositionsInContainer(container, startX, deltaY, deltaY + BUS_V_SPACING); + + // 更新水平位置 + startX += container->getWidth() + CONTAINER_H_SPACING; + } +} + +void FixedLayoutCalculator::calculateBlockPositionsInContainer(DiagramEditorStructContainer* container, + double startX, + double midUpY, + double midDownY) { + if (!container) return; + + auto mapBlocks = container->getBlockMap(); + double currentX = startX; + + for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) { + int layer = it.key(); + auto blocks = it.value(); + + for (auto block : blocks) { + if (!block) continue; + + QRectF rec = block->getRecSize(); + QPointF center; + + int blockType = block->getType(); + + if (blockType == 1) { // 母线 + if (layer == 1) { // 母线1 + center = QPointF(startX, midUpY + rec.height() * 0.5); + } else if (layer == 2) { // 母线2 + center = QPointF(startX, midDownY - rec.height() * 0.5); + } + } else if (blockType == 2) { // 间隔 + if (layer == 0) { // 上间隔 + center = QPointF(currentX + rec.width() * 0.5, + midUpY - rec.height() * 0.5 - Constants::EDITOR_ITEM_HEIGHT * 0.5); + } else if (layer == 3) { // 下间隔 + center = QPointF(currentX + rec.width() * 0.5, + midDownY + rec.height() * 0.5 + Constants::EDITOR_ITEM_HEIGHT * 0.5); + } + currentX += rec.width(); + } + // 变压器不在这里处理 + + if (!center.isNull()) { + m_blockPositions[block] = center; + block->setSeceneDelta(center); + } + } + } +} + +void FixedLayoutCalculator::calculateTransformerPositions(const QList& transformers, + double& deltaY, double& lastMaxDownH) { + if (transformers.isEmpty()) return; + + // 计算变压器尺寸 + for (auto container : transformers) { + if (!container) continue; + + auto mapBlocks = container->getBlockMap(); + auto transBlocks = mapBlocks.value(1); // 变压器在layer 1 + + for (auto block : transBlocks) { + if (!block) continue; + QRectF rec = block->getRecSize(); + container->setWidth(rec.width()); + container->setHeight(rec.height()); + break; // 只取第一个变压器 + } + } + + // 计算变压器位置 + double startX = TRANSFORMER_START_X; + bool isFirstTransformer = true; + + for (auto container : transformers) { + if (!container) continue; + + // 计算垂直位置 + if (isFirstTransformer) { + deltaY = deltaY + BUS_V_SPACING + lastMaxDownH + container->getHeight(); + isFirstTransformer = false; + } + + double centerY = deltaY - container->getHeight() * 0.5; + container->setStartY(centerY); + container->setStartX(startX); + + // 计算变压器内部设备位置 + auto mapBlocks = container->getBlockMap(); + for (auto it = mapBlocks.begin(); it != mapBlocks.end(); ++it) { + for (auto block : it.value()) { + if (!block) continue; + + QRectF rec = block->getRecSize(); + QPointF center(startX + rec.width() * 0.5, + centerY + rec.height() * 0.5); + + m_blockPositions[block] = center; + block->setSeceneDelta(center); + } + } + + // 更新水平位置 + startX += container->getWidth() + TRANSFORMER_SPACING; + } +} + diff --git a/diagramCavas/source/diagramEditor/transItemFactory.cpp b/diagramCavas/source/diagramEditor/transItemFactory.cpp new file mode 100644 index 0000000..f6b1517 --- /dev/null +++ b/diagramCavas/source/diagramEditor/transItemFactory.cpp @@ -0,0 +1,19 @@ +// BusItemFactory.cpp +#include "diagramEditor/transItemFactory.h" +#include "common/core_model/constants.h" + +EditBaseItem* TransItemFactory::createItem(BlockDataPtr blockData) { + auto pTrans = new EditTransItem(); + setupItem(pTrans, blockData); + return pTrans; +} + +QGraphicsLinearLayout* TransItemFactory::createLayerLayout() { + return new QGraphicsLinearLayout(Qt::Horizontal); +} + +void TransItemFactory::setupItem(EditBaseItem* item, BlockDataPtr blockData) { + item->setType(EditorItemType::trans); + item->setBoundingRect(QRectF(0, 0, + Constants::EDITOR_ITEM_WIDTH, Constants::EDITOR_ITEM_WIDTH)); +} diff --git a/diagramCavas/source/diagramEditor/transformerBuilder.cpp b/diagramCavas/source/diagramEditor/transformerBuilder.cpp new file mode 100644 index 0000000..f90e991 --- /dev/null +++ b/diagramCavas/source/diagramEditor/transformerBuilder.cpp @@ -0,0 +1,50 @@ +// TransformerBuilder.cpp +#include "diagramEditor/transformerBuilder.h" +#include "diagramEditor/hierarchyItemBuilder.h" + +TransformerBuilder::TransformerBuilder(EditPanel* panel) + : LayoutBuilder(panel) {} + +LayoutBuilder::BuildResult TransformerBuilder::buildContainer(const BlockMap& blockMap) { + BuildResult result = LayoutBuilder::buildContainer(blockMap); + + // 为变压器创建额外的层级项 + for (int layerIndex = 0; layerIndex < TOTAL_LAYERS; ++layerIndex) { + auto blocks = blockMap.value(layerIndex); + for (auto &block : blocks) { + if (block && block->getType() == TRANSFORMER_TYPE) { + processTransformerBlock(block, result.bayItems, result.deviceItems); + } + } + } + + return result; +} + +QGraphicsLinearLayout* TransformerBuilder::createTransformerRowLayout() { + auto layout = createRowLayout(); + layout->insertStretch(0); + layout->addStretch(); + return layout; +} + +HierarchyItem TransformerBuilder::buildTransformerHierarchyItem(BlockDataPtr blockData) { + if (!blockData) return {}; + + return HierarchyItemBuilder::instance() + .buildDeviceWithParent(blockData, blockData, TRANSFORMER_DEVICE_TYPE); +} + +void TransformerBuilder::processTransformerBlock(BlockDataPtr block, + QList& bayItems, + QList& deviceItems) { + if (!block) return; + + // 变压器需要bayItem吗?根据原始代码,变压器会创建bayItem + auto bayItem = HierarchyItemBuilder::instance().buildBayItem(block); + bayItems.append(bayItem); + + // 创建变压器的deviceItem + auto deviceItem = buildTransformerHierarchyItem(block); + deviceItems.append(deviceItem); +} diff --git a/diagramCavas/source/graphicsDataModel/baseModel.cpp b/diagramCavas/source/graphicsDataModel/baseModel.cpp index 40cdce1..74935bd 100644 --- a/diagramCavas/source/graphicsDataModel/baseModel.cpp +++ b/diagramCavas/source/graphicsDataModel/baseModel.cpp @@ -42,34 +42,8 @@ void BaseModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem,ModelFunctionT } } -QPointF BaseModel::calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item) +QPointF BaseModel::calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* item,QPointF para) { - //return QPointF(item->pos().x(),pBus->pos().y()); - /*QRectF recBus = pBus->sceneBoundingRect(); - QLineF busLine = QLineF(recBus.left(),recBus.y(),recBus.right(),recBus.y()); - - QPointF p1 = busLine.p1(); - QPointF p2 = busLine.p2(); - - // 计算item的中心点在垂直于线段方向上的投影 - QPointF itemCenter = item->pos();// + QPointF(item->boundingRect().width()/2, item->boundingRect().height()/2); - - // 计算投影点在线段上的位置 - QPointF projection; - if (busLine.length() == 0) { // 如果线段长度为0,直接返回端点 - projection = p1; - } else { - // 计算投影点 - QPointF vec = p2 - p1; - QPointF relPos = itemCenter - p1; - qreal dot = QPointF::dotProduct(relPos, vec) / (busLine.length() * busLine.length()); - - // 限制投影点在线段范围内 - dot = qBound(0.0, dot, 1.0); - projection = p1 + dot * vec; - } - - return projection;*/ QRectF recBus = pBus->sceneBoundingRect(); QRectF recItem = item->sceneBoundingRect(); @@ -81,16 +55,23 @@ QPointF BaseModel::calculateBusPortPos(GraphicsBaseItem* pBus,GraphicsBaseItem* QPointF p1 = busLine.p1(); QPointF p2 = busLine.p2(); - // 计算item的中心点 - QPointF itemCenter = recItem.center(); - // 计算投影点在线段上的位置 QPointF projection; if (busLine.length() == 0) { projection = p1; } else { QPointF vec = p2 - p1; - QPointF relPos = itemCenter - p1; + + // 如果para不是(0,0),则使用para点计算投影 + // 否则使用item的中心点计算投影 + QPointF pointToProject; + if (para != QPointF(0, 0)) { + pointToProject = para; + } else { + pointToProject = recItem.center(); + } + + QPointF relPos = pointToProject - p1; qreal dot = QPointF::dotProduct(relPos, vec) / (busLine.length() * busLine.length()); dot = qBound(0.0, dot, 1.0); projection = p1 + dot * vec; diff --git a/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp b/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp index 768545f..fb097ce 100644 --- a/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp +++ b/diagramCavas/source/graphicsDataModel/diagramEditorModel.cpp @@ -21,6 +21,7 @@ #include #include "common/core_model/constants.h" #include "include/instance/baseTypeManager.h" +#include "diagramEditor/layoutCalculator.h" int g_nCompoWidth = 50; //元件默认宽度(计算布局使用) int g_nCompoHeight = 50; @@ -796,7 +797,7 @@ void DiagramEditorModel::generatePreview(bool bVisible) void DiagramEditorModel::calculateBlockPos() { - if(_pWizard){ + /*if(_pWizard){ double deltaY = 0; //竖直方向每行增量 double lastMaxDownH = 0; //上一行的下部最大高度 auto mapTotal = _pWizard->getContainerStruct(); @@ -899,10 +900,10 @@ void DiagramEditorModel::calculateBlockPos() QPointF center; if(pBlock->getType() == 1){ //母线 if(it.key() == 1){ //1母 - center = QPointF(pStartX/*+recBlock.width()*0.5*/,dMiddleUpY+recBlock.height()*0.5); + center = QPointF(pStartX,dMiddleUpY+recBlock.height()*0.5); } else if(it.key() == 2){ //2母 - center = QPointF(pStartX/*+recBlock.width()*0.5*/,dMiddleDownY-recBlock.height()*0.5); + center = QPointF(pStartX,dMiddleDownY-recBlock.height()*0.5); } } else if(pBlock->getType() == 2){ //间隔 @@ -963,7 +964,22 @@ void DiagramEditorModel::calculateBlockPos() } } } + }*/ + if (!_pWizard) { + qWarning() << "calculateBlockPos: Wizard为空"; + return; } + + // 使用修正后的布局计算器 + FixedLayoutCalculator calculator(_pWizard); + + // 计算布局 + auto blockPositions = calculator.calculateLayout(); + + // 可以记录布局结果 + //m_blockPositions = blockPositions; + + qDebug() << "布局计算完成,处理了" << blockPositions.size() << "个设备"; } void DiagramEditorModel::setItemInBlockPos() @@ -1058,11 +1074,13 @@ void DiagramEditorModel::refreshConnection() auto pFromData = pFromItem->getProperty(); auto pToData = pToItem->getProperty(); if(pFromData->type() == 1){ //from是母线 - QPointF p = calculateBusPortPos(pFromItem,pToItem); + auto pToPort = pToItem->getPortById(toTerId); + QPointF p = calculateBusPortPos(pFromItem,pToItem,pToPort->scenePos()); pFromItem->movePort(fromTerId,pFromItem->mapFromScene(p)); } else if(pToData->type() == 1){ //to是母线 - QPointF p = calculateBusPortPos(pToItem,pFromItem); + auto pFromPort = pFromItem->getPortById(fromTerId); + QPointF p = calculateBusPortPos(pToItem,pFromItem,pFromPort->scenePos()); pToItem->movePort(toTerId,pToItem->mapFromScene(p)); } @@ -1092,6 +1110,20 @@ void DiagramEditorModel::refreshConnection() } } +void DiagramEditorModel::applyLayoutResult(const LayoutResult& result) { + // 应用所有设备位置 + for (auto it = result.allBlockPositions.begin(); it != result.allBlockPositions.end(); ++it) { + DiagramEditorBaseBlock* block = it.key(); + QPointF position = it.value(); + + if (block) { + block->setSeceneDelta(position); + } + } + + qDebug() << "布局计算完成,共处理" << result.allBlockPositions.size() << "个设备"; +} + QStandardItem* DiagramEditorModel::getNameItem(const QString& sName,int nFrom) { QStandardItemModel* pModel = nullptr; diff --git a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp index c03eefd..e2feadb 100644 --- a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp +++ b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp @@ -647,6 +647,34 @@ QString FixedPortsModel::addNodeItem(QUuid id,QPointF pos,double width,double he addPortsToItem_json(P_const,portArr,item); } + else if(type == GIT_CustomType) + { + PropertyModel model = ProjectModelManager::instance().getData()[sMeta][sProModel]; + QByteArray svg; + if(model.modelSetting.mapSvg.isEmpty()){ + svg = DataBase::GetInstance()->ModelType()[18].icon; + } + else{ + svg = ProjectModelManager::instance().getData()[sMeta][sProModel].modelSetting.mapUsedSvg["customType"]; + } + + if(width == 0 && height == 0){ + dX = 40; + dY = 40; + } + else{ + dX = width; + dY = height; + } + + auto pCustom = new ElectricSvgItem(QRect(-dX*0.5, -dY*0.5, dX, dY)); + pCustom->setItemType(GIT_CustomType); + pCustom->loadSvg(svg); + item = pCustom; + QJsonArray portArr = pro->context()["port"].toArray(); + + addPortsToItem_json(P_const,portArr,item); + } if(item) { item->setItemId(id); diff --git a/include/mainwindow.h b/include/mainwindow.h index 74cd90c..e9c1c44 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -25,6 +25,7 @@ class CreateEditor; class MonitorItemsDlg; class MonitorPagesDlg; class QDetailsView; +class BaseDockWidget; class CMainWindow : public QMainWindow { @@ -87,6 +88,7 @@ private: MonitorPagesDlg* m_pMonitorPagesDlg; QDockWidget* m_pMonitorItemsDock; QDockWidget* m_pMonitorPagesDock; + BaseDockWidget* m_pPropertyEditorDock; QDetailsView* m_pPropertiesEditorView; QAction* _pActMonitor; }; diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 0b7d0ca..9a64ec8 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -47,6 +47,7 @@ CMainWindow::CMainWindow(QWidget *parent) m_pMonitorItemsDock = nullptr; m_pMonitorPagesDock = nullptr; m_pPropertiesEditorView = nullptr; + m_pPropertyEditorDock = nullptr; _pActMonitor = nullptr; qRegisterMetaType("PropertyStateInfo"); @@ -137,12 +138,13 @@ void CMainWindow::initializeDockUi() connect(&ProjectModelManager::instance(),&ProjectModelManager::modelChange,m_pElectricElementsBox,&ElectricElementsBox::onSignal_modelChanged); m_pPropertiesEditorView = new QDetailsView(); - BaseDockWidget* PropertyEditorDock = new BaseDockWidget(QString::fromWCharArray(L"属性面板"),this); - PropertyEditorDock->setWidget(m_pPropertiesEditorView); - PropertyEditorDock->setMinimumSize(350,150); - m_pPropertiesEditorView->setObject(m_pDiagramCavas); - PropertyEditorDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); - this->addDockWidget(Qt::RightDockWidgetArea,PropertyEditorDock); + m_pPropertyEditorDock = new BaseDockWidget(QString::fromWCharArray(L"属性面板"),this); + m_pPropertyEditorDock->setWidget(m_pPropertiesEditorView); + m_pPropertyEditorDock->setMinimumSize(350,150); + m_pPropertiesEditorView->setObject(new QObject(this)); + m_pPropertyEditorDock->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); + this->addDockWidget(Qt::RightDockWidgetArea,m_pPropertyEditorDock); + m_pPropertyEditorDock->hide(); connect(m_pDiagramCavas,&DiagramCavas::selectTarget,this,&CMainWindow::onCavasItemSelected); } @@ -359,6 +361,7 @@ void CMainWindow::onAction_unloadEditor(const QString& str) void CMainWindow::onCavasItemSelected(QObject* obj) { + m_pPropertyEditorDock->show(); if(m_pPropertiesEditorView) m_pPropertiesEditorView->setObject(obj); }