optimize editor route build

This commit is contained in:
baiYue 2026-05-14 20:11:48 +08:00
parent 9ef08a005e
commit 803a4bde6c
30 changed files with 724 additions and 480 deletions

View File

@ -0,0 +1,15 @@
#include "diagram.h"
bool shareComponent(const DiagramEditorRouteInfo& a,const DiagramEditorRouteInfo& b) //计算两个线路是否相交
{
if (a.lstCompo.isEmpty() || b.lstCompo.isEmpty())
return false;
for (const auto& ca : a.lstCompo) {
for (const auto& cb : b.lstCompo) {
if (ca.sName == cb.sName)
return true;
}
}
return false;
}

View File

@ -122,6 +122,7 @@ struct DiagramEditorComponentInfo //组态设备信息
};
enum class Direction : int {
Invalid = 0,
Right = 1,
Left = 2,
Down = 4,
@ -140,12 +141,14 @@ struct DiagramEditorRouteInfo //间隔中单条线路信息
QList<DiagramEditorComponentInfo> lstOrder; //线路顺序容器(计算用)
QList<DiagramEditorComponentInfo> lstReverse; //逆序容器(计算用)
QString sParentRoute; //父线路名
Direction preferDirection = Direction::Invalid;
friend QDataStream &operator<<(QDataStream &out, const DiagramEditorRouteInfo &data) {
out << data.sRouteName << data.bMainRoute << data.lstCompo << data.lstOrder << data.lstReverse;
out << data.sRouteName << data.bMainRoute << data.lstCompo << data.lstOrder << data.lstReverse << data.sParentRoute << data.preferDirection;
return out;
}
friend QDataStream &operator>>(QDataStream &in, DiagramEditorRouteInfo &data) {
in >> data.sRouteName >> data.bMainRoute >> data.lstCompo >> data.lstOrder >> data.lstReverse;
in >> data.sRouteName >> data.bMainRoute >> data.lstCompo >> data.lstOrder >> data.lstReverse >> data.sParentRoute >> data.preferDirection;
return in;
}
};
@ -154,21 +157,25 @@ struct DiagramEditorBayInfo //组态编辑间隔信息
{
QString name; //间隔名
int nLayout = 0; //布局 0纵向1横向
int nLocate = 0; //间隔位置
QList<QUuid> lstFrom; //起始
QList<QUuid> lstTo; //结束
QMap<QString,DiagramEditorRouteInfo> mapRoute; //线路信息
QMap<QString,DiagramEditorComponentInfo> mapComponent; //设备信息
QList<QString> routeOrder; //线路顺序
friend QDataStream &operator<<(QDataStream &out, const DiagramEditorBayInfo &data) {
out << data.name << data.nLayout << data.lstFrom << data.lstTo << data.mapRoute << data.mapComponent;
out << data.name << data.nLayout << data.lstFrom << data.lstTo << data.mapRoute << data.mapComponent << data.routeOrder;
return out;
}
friend QDataStream &operator>>(QDataStream &in, DiagramEditorBayInfo &data) {
in >> data.name >> data.nLayout >> data.lstFrom >> data.lstTo >> data.mapRoute >> data.mapComponent;
in >> data.name >> data.nLayout >> data.lstFrom >> data.lstTo >> data.mapRoute >> data.mapComponent >> data.routeOrder;
return in;
}
};
extern bool shareComponent(const DiagramEditorRouteInfo& a,const DiagramEditorRouteInfo& b);
struct DiagramEditorTransNeutralInfo //组态编辑变压器中性点信息
{
QString name; //中性点名
@ -270,6 +277,7 @@ struct DiagramEditorBlockInfo //组态编辑block信息
QList<QPair<int,QUuid>> _lstSub; //子对象列表(非拓扑计算使用) 如母线子对象为间隔间隔子对象为item电动机子对象为item <类型uid> 类型0设备1间隔
QRectF recSize; //当前大小(根据内容确定)
QPointF sceneDelta; //block中心相对位移(计算布局位置
QPointF centerOffset; //逻辑中心与实际中心偏移量
bool bEditState; //详细编辑状态
//bus
@ -285,12 +293,12 @@ struct DiagramEditorBlockInfo //组态编辑block信息
friend QDataStream &operator<<(QDataStream &out, const DiagramEditorBlockInfo &data) {
out << data.sName << data.sContainerId << data.nType << data.nContainerLevel << data.uid << data._lstCon << data.recSize << data.sceneDelta
<< data.bEditState << data.fVoltage << data.nBusType << data.nIndex << data.nBayType << data.bayInfo << data.nTransType << data.transInfo;
<< data.centerOffset << data.bEditState << data.fVoltage << data.nBusType << data.nIndex << data.nBayType << data.bayInfo << data.nTransType << data.transInfo;
return out;
}
friend QDataStream &operator>>(QDataStream &in, DiagramEditorBlockInfo &data) {
in >> data.sName >> data.sContainerId >> data.nType >> data.nContainerLevel >> data.uid >> data._lstCon >> data.recSize >> data.sceneDelta
>> data.bEditState >> data.fVoltage >> data.nBusType >> data.nIndex >> data.nBayType >> data.bayInfo >> data.nTransType >> data.transInfo;
>> data.centerOffset >> data.bEditState >> data.fVoltage >> data.nBusType >> data.nIndex >> data.nBayType >> data.bayInfo >> data.nTransType >> data.transInfo;
return in;
}
};

View File

@ -314,6 +314,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
../common/source/extraPropertyManager.cpp
../common/core_model/types.cpp
../common/core_model/diagram.cpp
)
set(UI_FILES

View File

@ -44,6 +44,8 @@ public:
virtual QRectF getRecSize() {return recSize;}
virtual void setSeceneDelta(QPointF p){sceneDelta = p;}
virtual QPointF getSceneDelta() {return sceneDelta;}
virtual void setCenterOffset(QPointF p) {centerOffset = p;}
virtual QPointF getCenterOffset() {return centerOffset;}
virtual void setEditState(bool b){bEditState = b;}
virtual bool getEditState(){return bEditState;}
virtual void setVoltage(float f) { fVoltage = f;}
@ -60,6 +62,7 @@ protected:
QRectF recSize; //当前大小(根据内容确定)
QPointF sceneDelta; //block中心相对位移(计算布局位置
bool bEditState; //详细编辑状态
QPointF centerOffset; //逻辑中心与实际中心的偏移量
//bus
float fVoltage; //母线电压
@ -68,6 +71,7 @@ protected:
//bay
BayType nBayType;
DiagramEditorBayInfo bayInfo; //间隔信息
int nBayLocate = -1; //间隔所在位置 0母线上 3母线下
//transformer
TransformerType nTransType;
DiagramEditorTransInfo transInfo;
@ -97,6 +101,8 @@ public:
virtual void setBayType(BayType typ) {nBayType = typ;}
virtual BayType getBayType() {return nBayType;}
virtual void setBayInfo(DiagramEditorBayInfo info) {bayInfo = info;}
virtual int getBayLocate() {return nBayLocate;}
virtual void setBayLocate(int n) {nBayLocate = n;}
virtual DiagramEditorBayInfo& getBayInfo(){return bayInfo;}
};

View File

@ -36,6 +36,11 @@ public:
DiagramEditorBayBlock* getCurBlock(){return _curOperateObj;}
DiagramEditorWizard* getWizard() {return _pWizard;}
void showPreview(); //预览间隔
QString calculateParent(const QMap<QString,DiagramEditorRouteInfo>& mapRoute,const QList<QString>& routeOrder,DiagramEditorRouteInfo& cur); //获取当前线路的父
void markAffectedRoutes(const QMap<QString, DiagramEditorRouteInfo>& mapRoute,const QList<QString>& routeOrder,
const QString& routeName,QSet<QString>& affected); //标记线路的子线路
void onRouteModified(QMap<QString, DiagramEditorRouteInfo>& mapRoute,QList<QString>& routeOrder,const QString& modifiedRoute,bool onlyClear = false); //重新计算本路线及子路线的父
public slots:
void onAddClicked();
void onOkClicked();

View File

@ -17,6 +17,7 @@ public:
virtual ~DiagramEditorStructContainer();
public:
bool insertBlock(int,DiagramEditorBaseBlock*);
bool changeBlockLocate(DiagramEditorBaseBlock*,int src,int dest); //改变block所处层级
auto& getBlockMap() {return _mapBlocks;}
void setId(const QString& s) {sId = s;}
QString getId() {return sId;}

View File

@ -36,6 +36,10 @@ protected:
EditorItemType nType;
QRectF m_boundingRect;
QPointer<DiagramEditorBaseBlock> _pBlock;
QColor m_normalColor = QColor(180, 180, 180); // 浅灰,未编辑
QColor m_editedColor = QColor(80, 200, 210); // 蓝色,已编辑
QColor m_hoverColor = QColor(255, 120, 0); // 橙色,高亮
};
/********************bus*********************/
@ -60,6 +64,10 @@ public:
virtual QString getShowType() override;
protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private:
bool m_hovered = false;
};
/********************trans*********************/
@ -72,6 +80,10 @@ public:
virtual QString getShowType() override;
protected:
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
private:
bool m_hovered = false;
};
/********************连线*********************/

View File

@ -13,6 +13,7 @@ public:
bool saveToModel = false;
QMap<QString, QStandardItem*> itemCache;
QMap<QString, DiagramEditorComponentInfo> componentsCache;
QMap<QString, QSet<Direction>> branchUsedDirections; //key: 组件名 value: 已被支线占用的方向集合
void initComponentsCache(const QMap<QString, DiagramEditorComponentInfo>& compos) {
componentsCache = compos;
@ -48,7 +49,7 @@ private:
Context& context,
bool isOrder,
int polarity);
void markDirectionUsed(const QString& compoName,Direction dir,Context& context);
// 组件相关
Direction determineBranchDirection(const DiagramEditorComponentInfo& currentNode,
Direction preferredDir,
@ -65,6 +66,7 @@ private:
QStandardItem* getNameItem(const QString& name, Context& context);
int getComponentDirection(const QString& compoName, Context& context);
QRectF calculateBoundingRect(const QMap<QString, DiagramEditorComponentInfo>& components);
Direction getRouteDirection(const QString& routeName,const QMap<QString, DiagramEditorRouteInfo>& routes);
private:
int m_compoWidth = 50;

View File

@ -45,8 +45,9 @@ private:
// 全局常量
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 CONTAINER_H_SPACING = 120.0; // 容器水平间距
const double CONTAINER_START_X = 60.0; // 容器起始X
const double TRANSFORMER_START_X = 150.0; // 变压器起始X
const double TRANSFORMER_SPACING = 200.0; // 变压器间距
const double TRANSFORMER_MA = 200.0; // 变压器间距
};

View File

@ -40,6 +40,7 @@ DiagramEditorBlockInfo DiagramEditorBaseBlock::getBlockInfo()
info._lstSub = _lstSub;
info.recSize = recSize;
info.sceneDelta = sceneDelta;
info.centerOffset = centerOffset;
info.bEditState = bEditState;
info.fVoltage = fVoltage;

View File

@ -63,7 +63,7 @@ void DiagramEditorBayDetailAddDlg::initial()
ui->tableView_selected->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView_selected->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView_selected->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView_selected->verticalHeader()->setVisible(false);
//ui->tableView_selected->verticalHeader()->setVisible(false);
ui->cb_lineType->setItemData(0,1); //设置主线支线
ui->cb_lineType->setItemData(1,0);
@ -258,7 +258,7 @@ void DiagramEditorBayDetailAddDlg::showDlg()
ui->le_routeName->setText("线路"+QString::number(n+1));
ui->tableView_items->setModel(pCompo);
ui->label->setText("新建线路");
ui->le_routeName->setReadOnly(true);
//ui->le_routeName->setReadOnly(true);
_curMode = 0;
updateBindLst();
@ -479,12 +479,22 @@ void DiagramEditorBayDetailAddDlg::onSaveClicked()
rowItems[Col_Route] = new QStandardItem();
pModel->appendRow(rowItems);
const int newRow = pModel->rowCount() - 1;
QModelIndex index = pModel->index(newRow, 0);
// 设置当前选中项(焦点)
ui->tableView_items->setCurrentIndex(index);
// 滚动到该行
ui->tableView_items->scrollTo(index, QAbstractItemView::PositionAtCenter);
}
void DiagramEditorBayDetailAddDlg::onOkClicked()
{
QString sRoute = ui->le_routeName->text();
auto& mapRoute = _pParent->getBayInfo().mapRoute;
auto& lstRouteOrder = _pParent->getBayInfo().routeOrder;
QStringList lstName; //线路的设备列表
DiagramEditorRouteInfo routeInfo;
routeInfo.sRouteName = sRoute;
@ -550,21 +560,31 @@ void DiagramEditorBayDetailAddDlg::onOkClicked()
return;
}
lstRouteOrder.append(sRoute);
if(!routeInfo.bMainRoute){ //非主线才设置父
QString sParent = _pParent->calculateParent(mapRoute,lstRouteOrder,routeInfo);
if(!sParent.isEmpty())
routeInfo.sParentRoute = sParent;
}
mapRoute.insert(sRoute,routeInfo); //插入线路到parent存储中
QStandardItem *itemRoute = new QStandardItem();
QStandardItem *itemParent = new QStandardItem();
QStandardItem *itemNames = new QStandardItem();
itemRoute->setText(sRoute);
itemRoute->setData(nMain);
itemParent->setText(routeInfo.sParentRoute);
itemNames->setText(strCompoNames);
QList<QStandardItem*> lstItems;
lstItems<<itemRoute<<itemNames;
lstItems<<itemRoute<<itemParent<<itemNames;
auto pRoute = _pParent->getRouteModel();
pRoute->appendRow(lstItems);
}
else if(_curMode == 1){
_pParent->onRouteModified(mapRoute,lstRouteOrder,routeInfo.sRouteName);
mapRoute[sRoute] = routeInfo;
auto pRoute = _pParent->getRouteModel();
int nCount = pRoute->rowCount();
@ -572,11 +592,22 @@ void DiagramEditorBayDetailAddDlg::onOkClicked()
QStandardItem *itemName = pRoute->item(i, 0);
if(itemName->text() == sRoute){
itemName->setData(nMain);
QStandardItem *itemRoutes = pRoute->item(i, 1);
QStandardItem *itemRoutes = pRoute->item(i, 2);
itemRoutes->setText(strCompoNames);
break;
}
}
for(int i = 0;i < rowCount;++i){ //重新加载所有父路线
QStandardItem *itemName = pRoute->item(i, 0);
for(auto& route:mapRoute){
if(itemName->text() == route.sRouteName){
QStandardItem *itemParnet = pRoute->item(i, 1);
itemParnet->setText(route.sParentRoute);
continue;
}
}
}
}
if(_pParent){
_pParent->showPreview();

View File

@ -7,7 +7,10 @@
#include "diagramEditor/diagramEditorBaseBlock.h"
#include "graphicsDataModel/diagramEditorModel.h"
#include "include/instance/baseTypeManager.h"
#include "diagramEditor/diagramEditorStructContainer.h"
#include "diagramEditor/editPanel.h"
#include "topologyManager.h"
#include <QTimer>
DiagramEditorBayDetailSettingDlg::DiagramEditorBayDetailSettingDlg(QWidget *parent,DiagramEditorModel* pModel)
: QDialog(parent)
@ -36,8 +39,12 @@ void DiagramEditorBayDetailSettingDlg::initial()
{
_compoModel = new QStandardItemModel(this);
_routeModel = new QStandardItemModel(this);
_routeModel->setHorizontalHeaderLabels({"线路名", "包含设备"});
_routeModel->setHorizontalHeaderLabels({"线路名", "父线路","包含设备"});
ui->tableView->setModel(_routeModel);
QHeaderView *header = ui->tableView->horizontalHeader();
ui->tableView->setColumnWidth(0, 40);
ui->tableView->setColumnWidth(1, 40);
header->setStretchLastSection(true);
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);
@ -46,12 +53,14 @@ void DiagramEditorBayDetailSettingDlg::initial()
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView->verticalHeader()->setVisible(false);
ui->cb_layout->addItem("纵向",0);
ui->cb_layout->addItem("横向",1);
ui->cb_locate->addItem("",0);
ui->cb_locate->addItem("",3);
if(_pPreviewDlg == nullptr){
_pPreviewDlg = new DiagramEditorBayPreviewDlg(this);
_pPreviewDlg->setParent(this);
@ -116,13 +125,14 @@ void DiagramEditorBayDetailSettingDlg::refreshModel()
}
_routeModel->clear();
_routeModel->setColumnCount(2);
_routeModel->setHorizontalHeaderLabels({"线路名", "包含设备"});
_routeModel->setColumnCount(3);
_routeModel->setHorizontalHeaderLabels({"线路名","父线路","包含设备"});
auto info = _curOperateObj->getBayInfo();
if(info.nLayout == 0) //纵向
ui->cb_layout->setCurrentIndex(0);
else
ui->cb_layout->setCurrentIndex(1);
setBayInfo(info);
auto mapRoute = info.mapRoute; //更新路径数据到本界面
@ -136,13 +146,15 @@ void DiagramEditorBayDetailSettingDlg::refreshModel()
}
QStandardItem *itemRoute = new QStandardItem();
QStandardItem *itemParent = new QStandardItem();
QStandardItem *itemComponents = new QStandardItem();
itemRoute->setText(sRoute);
itemRoute->setData(route.bMainRoute);
itemParent->setText(route.sParentRoute);
itemComponents->setText(lstComp.join(","));
QList<QStandardItem*> lstItems;
lstItems<<itemRoute<<itemComponents;
lstItems<<itemRoute<<itemParent<<itemComponents;
_routeModel->appendRow(lstItems);
}
@ -157,6 +169,12 @@ void DiagramEditorBayDetailSettingDlg::showDlg(DiagramEditorBayBlock* p)
ui->cb_layout->setCurrentIndex(1);
else
ui->cb_layout->setCurrentIndex(0);
if(p->getBayLocate() == 0)
ui->cb_locate->setCurrentIndex(0);
else
ui->cb_locate->setCurrentIndex(1);
ui->label_bay->setText(p->getName());
refreshModel();
}
@ -172,61 +190,9 @@ void DiagramEditorBayDetailSettingDlg::onAddClicked()
void DiagramEditorBayDetailSettingDlg::onOkClicked()
{
//将ui设置的参数更新到对应block
bool changePos = false;
if(_curOperateObj){
/*QMap<QString,DiagramEditorComponentInfo> mapComponents;
int nRowCount = _compoModel->rowCount();
for(int i = 0;i < nRowCount;++i){
QStandardItem *itemCate = _compoModel->item(i, 0);
QStandardItem *itemName = _compoModel->item(i, 1);
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(); //相对位置
QUuid uid = itemName->data(Qt::UserRole+3).toUuid(); //uid
int nVal = itemName->data(Qt::UserRole+4).toInt(); //标志
int nRotate = itemName->data(Qt::UserRole+5).toInt(); //旋转角度
DiagramEditorComponentInfo compoInfo;
if(itemCate->text() == "电气设备"){
compoInfo.nCategory = 0;
}
else if(itemCate->text() == "连接关系"){
compoInfo.nCategory = 1;
}
compoInfo.sName = itemName->text();
compoInfo.nType = itemType->data().toInt();
compoInfo.sBindObj = itemBind->text();
compoInfo.nBindType = itemBind->data().toInt();
compoInfo.nBindPara = itemBind->data(Qt::UserRole+2).toInt();
compoInfo.sBindParent = itemBind->data(Qt::UserRole+3).toString();
compoInfo.sUsedRoute = itemRoute->text().split(",");
compoInfo.nUsedDirection = nDir;
compoInfo.deltaPos = deltaPos;
compoInfo.uid = uid;
compoInfo.nFlag = nVal;
compoInfo.nRotate = nRotate;
mapComponents.insert(compoInfo.sName,compoInfo);
}
int nLayout = ui->cb_layout->currentData().toInt();
_curBayInfo.nLayout = nLayout;
_curBayInfo.mapComponent = mapComponents;
int nDir = 0;
if(nLayout == 0){ //纵,下右
nDir = 41;
}
else if(nLayout == 1){ //横,右下
nDir = 14;
}
getModel()->clearCompoDir(_curBayInfo.mapRoute,_curBayInfo.mapComponent,0);
QRectF recBounding = getModel()->updateTarget(_curBayInfo.mapRoute,_curBayInfo.mapComponent,nDir,0,false);
if(_curOperateObj->getRecSize().isEmpty())
_curOperateObj->setRecSize(recBounding);
_curOperateObj->setBayInfo(_curBayInfo);*/
QMap<QString, DiagramEditorComponentInfo> tempComponents;
int nRowCount = _compoModel->rowCount();
for (int i = 0; i < nRowCount; ++i) {
@ -273,6 +239,16 @@ void DiagramEditorBayDetailSettingDlg::onOkClicked()
_curBayInfo.nLayout = nLayout;
_curBayInfo.mapComponent = tempComponents; // ✅ 仅存非布局数据
int nLocate = ui->cb_locate->currentData().toInt();
if(_curBayInfo.nLocate != nLocate){
//位置发生变动
_curOperateObj->getCurContainer()->changeBlockLocate(_curOperateObj,_curBayInfo.nLocate,nLocate);
_curBayInfo.nLocate = nLocate;
_curOperateObj->setBayLocate(nLocate);
//emit _pWizard->wizardFinish();
changePos = true;
}
// ✅ 3. 执行布局(唯一正确时机)
int nDir = (nLayout == 0) ? 41 : 14;
getModel()->clearCompoDir(
@ -300,12 +276,17 @@ void DiagramEditorBayDetailSettingDlg::onOkClicked()
_curOperateObj = nullptr;
}
hide();
_pModel->clearCurPreview(); //关闭时清除预览Item
_pModel->generatePreview();
_pModel->calculateBlockPos();
_pModel->setItemInBlockPos();
_pModel->refreshConnection();
//todo:清除mainPanel中的对应item(如果存在)
if(changePos){
_pModel->getPanel()->initByWizardInfo();
}
QTimer::singleShot(300, this, [this]() {
_pModel->clearCurPreview(); //关闭时清除预览Item
_pModel->generatePreview();
_pModel->calculateBlockPos();
_pModel->setItemInBlockPos();
_pModel->refreshConnection();
});
}
void DiagramEditorBayDetailSettingDlg::onCancelClicked()
@ -347,7 +328,21 @@ void DiagramEditorBayDetailSettingDlg::onRouteDeleteClicked()
_routeModel->removeRow(row);
}
onRouteModified(_curBayInfo.mapRoute,_curBayInfo.routeOrder,sName,true);
_curBayInfo.mapRoute.remove(sName); //同步移除数据
_curBayInfo.routeOrder.removeAll(sName); //移除排序
for(int i = 0;i < _routeModel->rowCount();++i){ //重新加载所有父路线
QStandardItem *itemName = _routeModel->item(i, 0);
for(auto& route:_curBayInfo.mapRoute){
if(itemName->text() == route.sRouteName){
QStandardItem *itemParnet = _routeModel->item(i, 1);
itemParnet->setText(route.sParentRoute);
continue;
}
}
}
}
void DiagramEditorBayDetailSettingDlg::onRouteRbtnClicked(const QPoint &pos)
@ -405,3 +400,56 @@ void DiagramEditorBayDetailSettingDlg::showPreview()
_curOperateObj->setRecSize(recContainAll);
}
}
QString DiagramEditorBayDetailSettingDlg::calculateParent(const QMap<QString, DiagramEditorRouteInfo>& mapRoute,const QList<QString>& routeOrder,DiagramEditorRouteInfo& cur)
{
int curIndex = routeOrder.indexOf(cur.sRouteName);
for (int i = 0; i < curIndex; ++i) {
const QString& otherName = routeOrder.at(i);
const DiagramEditorRouteInfo& other =
mapRoute.value(otherName);
if (shareComponent(other, cur)) {
return otherName;
}
}
return QString();
}
void DiagramEditorBayDetailSettingDlg::markAffectedRoutes(const QMap<QString, DiagramEditorRouteInfo>& mapRoute,const QList<QString>& routeOrder,
const QString& routeName,QSet<QString>& affected)
{
if (affected.contains(routeName))
return;
affected.insert(routeName);
int idx = routeOrder.indexOf(routeName);
for (int i = idx + 1; i < routeOrder.size(); ++i) {
const QString& otherName = routeOrder.at(i);
const auto& other = mapRoute.value(otherName);
if (shareComponent(other, mapRoute.value(routeName))) {
markAffectedRoutes(mapRoute, routeOrder,
otherName, affected);
}
}
}
void DiagramEditorBayDetailSettingDlg::onRouteModified(QMap<QString, DiagramEditorRouteInfo>& mapRoute,QList<QString>& routeOrder,const QString& modifiedRoute,bool onlyClear)
{
QSet<QString> affected;
markAffectedRoutes(mapRoute, routeOrder,
modifiedRoute, affected);
for (const auto& name : affected) {
auto& route = mapRoute[name];
route.sParentRoute.clear();
if(onlyClear)
continue;
route.sParentRoute =
calculateParent(mapRoute, routeOrder, route);
}
}

View File

@ -23,6 +23,24 @@ bool DiagramEditorStructContainer::insertBlock(int nPos,DiagramEditorBaseBlock*
return true;
}
bool DiagramEditorStructContainer::changeBlockLocate(DiagramEditorBaseBlock* p,int src,int dest)
{
bool bFind = false;
for(int i = 0; i < _mapBlocks[src].size();++i){
if(_mapBlocks[src].value(i) == p)
{
_mapBlocks[src].removeAt(i);
bFind = true;
break;
}
}
if(bFind){
_mapBlocks[dest].append(p);
return true;
}
return false;
}
QMap<int,QList<DiagramEditorBlockInfo>> DiagramEditorStructContainer::getMapBlocksData()
{
QMap<int,QList<DiagramEditorBlockInfo>> map;

View File

@ -65,7 +65,7 @@ void DiagramEditorTransDetailAddDlg::initial()
ui->tableView_selected->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView_selected->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView_selected->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView_selected->verticalHeader()->setVisible(false);
//ui->tableView_selected->verticalHeader()->setVisible(false);
_bindItemModel = new QStandardItemModel(this);
ui->cb_bindObj->setModel(_bindItemModel);
@ -471,6 +471,15 @@ void DiagramEditorTransDetailAddDlg::onSaveClicked()
rowItems[Col_Route] = new QStandardItem();
pModel->appendRow(rowItems);
const int newRow = pModel->rowCount() - 1;
QModelIndex index = pModel->index(newRow, 0);
// 设置当前选中项(焦点)
ui->tableView_items->setCurrentIndex(index);
// 滚动到该行
ui->tableView_items->scrollTo(index, QAbstractItemView::PositionAtCenter);
}
void DiagramEditorTransDetailAddDlg::onOkClicked()

View File

@ -60,18 +60,24 @@ void DiagramEditorTransDetailSettingDlg::initial()
showPreview();
});
ui->tableView_hv->setColumnWidth(0, 40);
ui->tableView_hv->horizontalHeader()->setStretchLastSection(true);
ui->tableView_hv->setContextMenuPolicy(Qt::CustomContextMenu);
ui->tableView_hv->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView_hv->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView_hv->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView_hv->verticalHeader()->setVisible(false);
ui->tableView_mv->setColumnWidth(0, 40);
ui->tableView_mv->horizontalHeader()->setStretchLastSection(true);
ui->tableView_mv->setContextMenuPolicy(Qt::CustomContextMenu);
ui->tableView_mv->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView_mv->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableView_mv->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView_mv->verticalHeader()->setVisible(false);
ui->tableView_lv->setColumnWidth(0, 40);
ui->tableView_lv->horizontalHeader()->setStretchLastSection(true);
ui->tableView_lv->setContextMenuPolicy(Qt::CustomContextMenu);
ui->tableView_lv->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView_lv->setSelectionBehavior(QAbstractItemView::SelectRows);
@ -177,6 +183,7 @@ void DiagramEditorTransDetailSettingDlg::showDlg(DiagramEditorTransformerBlock*
{
show();
_curOperateObj = p;
ui->label_name->setText(p->getName());
refreshModel();
}

View File

@ -21,6 +21,7 @@ DiagramEditorWizard::DiagramEditorWizard(QWidget *parent)
{
ui->setupUi(this);
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
setWindowModality(Qt::WindowModal);
setStyleSheet("background-color: white;");
initial();
}
@ -406,6 +407,7 @@ void DiagramEditorWizard::setPara(DiagramEditorProjectInfo info)
pBay->addConnect(uid);
}
pBay->setBayInfo(blockInfo.bayInfo);
pBay->setBayLocate(ite.key()); //间隔的相对位置
pBlock = pBay;
}
else if(blockInfo.nType == 3){
@ -424,6 +426,7 @@ void DiagramEditorWizard::setPara(DiagramEditorProjectInfo info)
pBlock->setContainerLevel(blockInfo.nContainerLevel);
pBlock->setRecSize(blockInfo.recSize);
pBlock->setSeceneDelta(blockInfo.sceneDelta);
pBlock->setCenterOffset(blockInfo.centerOffset);
pBlock->setEditState(blockInfo.bEditState);
pBlock->setVoltage(blockInfo.fVoltage);
pContainer->insertBlock(ite.key(),pBlock);
@ -781,9 +784,11 @@ void DiagramEditorWizard::onAddBayFinished(DiagramEditorWizardBayInfo info)
if((lstlevel.value(0) == lstlevel.value(1))){ //加入container最上层
if((lstlevel.value(0) == 1)){
pContainer->insertBlock(0,pBlock);
pBlock->setBayLocate(0);
}
else if((lstlevel.value(0) == 2)){ //加入container最下层
pContainer->insertBlock(3,pBlock);
pBlock->setBayLocate(3);
}
}
}
@ -796,9 +801,11 @@ void DiagramEditorWizard::onAddBayFinished(DiagramEditorWizardBayInfo info)
if((lstlevel.value(0) == lstlevel.value(1))){ //加入container最上层
if((lstlevel.value(0) == 1)){
pContainer->insertBlock(0,pBlock);
pBlock->setBayLocate(0);
}
else if((lstlevel.value(0) == 2)){ //加入container最下层
pContainer->insertBlock(3,pBlock);
pBlock->setBayLocate(3);
}
}
}
@ -808,10 +815,12 @@ void DiagramEditorWizard::onAddBayFinished(DiagramEditorWizardBayInfo info)
else if(info.nType == BayType::incomingBay || info.nType == BayType::busCouplerBay){ //进线间隔、母联间隔在上边
auto pContainer = getContainerByBlock(curIndex,1,info.lstBindObj.first());
pContainer->insertBlock(0,pBlock);
pBlock->setBayLocate(0);
}
else{ //其他间隔
auto pContainer = getContainerByBlock(curIndex,1,info.lstBindObj.first());
pContainer->insertBlock(3,pBlock);
pBlock->setBayLocate(3);
}
_bayContentDlg->flushData(curIndex);
}

View File

@ -31,6 +31,6 @@ void EditContainerItem::resizeEvent(QGraphicsSceneResizeEvent *event)
void EditContainerItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setPen(QColor(255,0,0));
painter->drawRect(boundingRect());
//painter->setPen(QColor(255,0,0));
//painter->drawRect(boundingRect());
}

View File

@ -69,7 +69,7 @@ void EditBusItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* optio
EditBayItem::EditBayItem(QGraphicsItem *parent)
: EditBaseItem(parent)
{
setAcceptHoverEvents(true);
}
EditBayItem::~EditBayItem()
{
@ -118,28 +118,46 @@ void EditBayItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* optio
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setPen(QColor(220,220,230));
QString sState = getEditState();
QString str1 = "类型:"+getShowType();
QString str2 = "状态:"+sState;
QString text = str1+"\n"+str2;
if(m_hovered)
painter->setPen(QPen(m_hoverColor, 2));
else{
if(sState == "已编辑")
painter->setPen(QPen(m_editedColor, 2));
else
painter->setPen(QPen(m_normalColor, 2));
}
painter->drawRect(m_boundingRect);
painter->drawText(QPointF(-10,0),sName);
painter->setFont(QFont("Arial", 12));
painter->setPen(Qt::cyan);
QString str1 = "类型:"+getShowType();
QString str2 = "状态:"+getEditState();
QString text = str1+"\n"+str2;
QTextOption op;
op.setAlignment(Qt::AlignCenter);
painter->drawText(boundingRect(), text, op);
}
void EditBayItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
m_hovered = true;
update();
}
void EditBayItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
{
m_hovered = false;
update();
}
/********************trans*********************/
EditTransItem::EditTransItem(QGraphicsItem *parent)
: EditBaseItem(parent)
{
setAcceptHoverEvents(true);
}
EditTransItem::~EditTransItem()
{
@ -173,22 +191,40 @@ void EditTransItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setPen(QColor(180,235,155));
QString sState = getEditState();
QString str1 = "类型:"+getShowType();
QString str2 = "状态:"+sState;
QString text = str1+"\n"+str2;
if(m_hovered)
painter->setPen(QPen(m_hoverColor, 2));
else{
if(sState == "已编辑")
painter->setPen(QPen(m_editedColor, 2));
else
painter->setPen(QPen(m_normalColor, 2));
}
painter->drawRect(m_boundingRect);
painter->drawText(QPointF(-10,0),sName);
painter->setFont(QFont("Arial", 12));
painter->setPen(Qt::cyan);
QString str1 = "类型:"+getShowType();
QString str2 = "状态:"+getEditState();
QString text = str1+"\n"+str2;
QTextOption op;
op.setAlignment(Qt::AlignCenter);
painter->drawText(boundingRect(), text, op);
}
void EditTransItem::hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
m_hovered = true;
update();
}
void EditTransItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
{
m_hovered = false;
update();
}
/********************连线*********************/
EditLineItem::EditLineItem(QGraphicsItem *parent)

View File

@ -3,6 +3,7 @@
#include <QGraphicsGridLayout>
#include <QPushButton>
#include <QTimer>
#include <QMessageBox>
#include <QGraphicsProxyWidget>
#include "diagramEditor/editPanel.h"
#include "diagramEditor/editScene.h"
@ -61,236 +62,6 @@ EditPanel::~EditPanel()
void EditPanel::initByWizardInfo()
{
/*QList<HierarchyItem> lstBay;
QList<HierarchyItem> lstItem;
_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)
continue;
QGraphicsLinearLayout* layoutRowData = new QGraphicsLinearLayout(Qt::Horizontal);
layoutRowData->setSpacing(20);
layoutRowData->setMaximumHeight(300);
EditRowData* pRow = new EditRowData();
pRow->setId(QString::number(iter.key()));
auto& mapCon = iter.value();
for(int i = 0;i < mapCon.size();++i){
EditContainerItem* pContain = new EditContainerItem();
connect(pContain,&EditContainerItem::containerSizeChange,this,&EditPanel::onContainerSizeChanged);
pContain->setMinimumWidth(Constants::EDITOR_ITEM_WIDTH+40);
layoutRowData->addItem(pContain);
pContain->setId(QUuid::createUuid().toString());
QGraphicsLinearLayout* layV = new QGraphicsLinearLayout(Qt::Vertical); //container中分层布局
layV->setSpacing(10);
layV->setMinimumHeight(260);
pContain->setLayout(layV);
auto pConData = mapCon[i];
auto mapBlock = pConData->getBlockMap();
for(auto ite = mapBlock.begin();ite != mapBlock.end();++ite){
QGraphicsLinearLayout* layH = new QGraphicsLinearLayout(Qt::Horizontal); //container中每一层的布局
layV->addItem(layH);
if(ite.value().size() > 0){
for(auto pBlock:ite.value()){
int nType = pBlock->getType();
EditBaseItem* pItem = nullptr;
if(nType == 1){ //母线
auto pBus = new EditBusItem();
pBus->setType(EditorItemType::bus);
pItem = pBus;
layH->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
layH->setPreferredHeight(10); // 固定高度
HierarchyItem info;
info.item.nEquipType = 1;
info.item.nCategory = 0; // 类别为0表示设备
info.item.sName = pBlock->getName();
info.item.uid = pBlock->getId(); //间隔id与对象id此处相同(表示此间隔对应一个设备)
// 查找设备所属的间隔
QString bayTag;
QString bayUuid;
QString sVoltageLevel;
bayTag = pBlock->getName();
bayUuid = pBlock->getId().toString();
sVoltageLevel = QString::number(pBlock->getVoltage());
if(!bayTag.isEmpty()){
// 设置父间隔信息
info.parent.nEquipType = 0;
info.parent.nCategory = 1;
info.parent.sName = bayTag;
info.parent.uid = QUuid(bayUuid);
info.parent.sVoltageLevel = sVoltageLevel;
}
lstItem.append(info);
}
else if(nType == 2){ //间隔
auto pBay = new EditBayItem();
pBay->setType(EditorItemType::bay);
pBay->setBoundingRect(QRectF(0,0,Constants::EDITOR_ITEM_WIDTH,Constants::EDITOR_ITEM_HEIGHT));
pItem = pBay;
}
if(pItem){
HierarchyItem bayInfo; //间隔层级
bayInfo.item.nEquipType = 0; // 间隔的设备类型为0
bayInfo.item.nCategory = 1; // 类别为1表示间隔
bayInfo.item.sName = pBlock->getName();
bayInfo.item.uid = pBlock->getId();
bayInfo.item.sVoltageLevel = QString::number(pBlock->getVoltage());
lstBay.append(bayInfo);
connect(pItem,&EditBaseItem::itemDbClicked,this,&EditPanel::onItemDbClicked);
pItem->setName(pBlock->getName());
pItem->setBlockData(pBlock);
layH->addItem(pItem);
}
}
}
}
if(mapBlock.value(0).isEmpty()){ //为空则添加间距
QGraphicsLinearLayout* layH = new QGraphicsLinearLayout(Qt::Horizontal); //container中每一层的布局
layV->insertItem(0,layH);
auto pSpace = new EditBaseItem();
pSpace->setType(EditorItemType::None);
pSpace->setBoundingRect(QRectF(0,0,Constants::EDITOR_ITEM_WIDTH,Constants::EDITOR_ITEM_HEIGHT));
layH->addItem(pSpace);
}
if(mapBlock.value(3).isEmpty()){ //为空则添加间距
QGraphicsLinearLayout* layH = new QGraphicsLinearLayout(Qt::Horizontal); //container中每一层的布局
layV->insertItem(3,layH);
auto pSpace = new EditBaseItem();
pSpace->setType(EditorItemType::None);
pSpace->setBoundingRect(QRectF(0,0,Constants::EDITOR_ITEM_WIDTH,Constants::EDITOR_ITEM_HEIGHT));
layH->addItem(pSpace);
}
if(layV->count() == 4){
layV->insertStretch(3);
layV->insertStretch(1);
}
else if(layV->count() == 2)
{
layV->insertStretch(1);
}
calculateContainerWidth(pContain);
}
_lstData.append(pRow);
_widgetLayout->addItem(layoutRowData);
if(iter.key() == 0){ //若设置了变压器,直接插入到第一行下方
if(!mapTotal.value(Constants::TRANSFORMER_LEVEL).empty()){
QGraphicsLinearLayout* layoutRowData = new QGraphicsLinearLayout(Qt::Horizontal);
layoutRowData->setSpacing(20);
EditRowData* pRow = new EditRowData();
pRow->setId(QString::number(Constants::TRANSFORMER_LEVEL));
auto& mapCon = mapTotal[Constants::TRANSFORMER_LEVEL];
for(int i = 0;i < mapCon.size();++i){
EditContainerItem* pContain = new EditContainerItem();
connect(pContain,&EditContainerItem::containerSizeChange,this,&EditPanel::onContainerSizeChanged);
pContain->setMinimumWidth(Constants::EDITOR_ITEM_WIDTH+40);
layoutRowData->addItem(pContain);
pContain->setId(QUuid::createUuid().toString());
QGraphicsLinearLayout* layV = new QGraphicsLinearLayout(Qt::Vertical); //container中分层布局
layV->setSpacing(10);
layV->setMinimumHeight(260);
pContain->setLayout(layV);
auto pConData = mapCon[i];
auto mapBlock = pConData->getBlockMap();
for(auto ite = mapBlock.begin();ite != mapBlock.end();++ite){
QGraphicsLinearLayout* layH = new QGraphicsLinearLayout(Qt::Horizontal); //container中每一层的布局
layV->addItem(layH);
if(ite.value().size() > 0){
for(auto pBlock:ite.value()){
int nType = pBlock->getType();
EditBaseItem* pItem = nullptr;
if(nType == 3){ //变压器
auto pTrans = new EditTransItem();
pTrans->setType(EditorItemType::trans);
pTrans->setBoundingRect(QRectF(0,0,Constants::EDITOR_ITEM_WIDTH,Constants::EDITOR_ITEM_WIDTH));
pItem = pTrans;
HierarchyItem info;
info.item.nEquipType = 16;
info.item.nCategory = 0; // 类别为0表示设备
info.item.sName = pBlock->getName();
info.item.uid = pBlock->getId(); //间隔id与对象id此处相同(表示此间隔对应一个设备)
// 查找设备所属的间隔
QString bayTag;
QString bayUuid;
QString sVoltageLevel;
bayTag = pBlock->getName();
bayUuid = pBlock->getId().toString();
sVoltageLevel = QString::number(pBlock->getVoltage());
if(!bayTag.isEmpty()){
// 设置父间隔信息
info.parent.nEquipType = 0;
info.parent.nCategory = 1;
info.parent.sName = bayTag;
info.parent.uid = QUuid(bayUuid);
info.parent.sVoltageLevel = sVoltageLevel;
}
lstItem.append(info);
}
if(pItem){
HierarchyItem bayInfo; //间隔层级
bayInfo.item.nEquipType = 0; // 间隔的设备类型为0
bayInfo.item.nCategory = 1; // 类别为1表示间隔
bayInfo.item.sName = pBlock->getName();
bayInfo.item.uid = pBlock->getId();
bayInfo.item.sVoltageLevel = QString::number(pBlock->getVoltage());
lstBay.append(bayInfo);
connect(pItem,&EditBaseItem::itemDbClicked,this,&EditPanel::onItemDbClicked);
pItem->setName(pBlock->getName());
pItem->setBlockData(pBlock);
layH->addItem(pItem);
}
}
}
}
layV->insertStretch(3);
layV->insertStretch(0);
layoutRowData->addStretch();
}
layoutRowData->insertStretch(0);
_lstData.append(pRow);
_widgetLayout->addItem(layoutRowData);
}
}
}
_widgetLayout->addStretch();
emit _pModel->updateTopologyItems(lstBay,true,false);
emit _pModel->updateTopologyItems(lstItem,false,false);
QTimer::singleShot(300, [&]() { // 1000 毫秒 = 1 秒
qDebug() << "一次性定时器触发!";
initBlockConnection();
});*/
// 阶段1: 清理和初始化
performCleanup();
initializeSceneLayout();
@ -643,7 +414,26 @@ EditBaseItem* EditPanel::getItemByName(const QString& sName)
void EditPanel::closeEvent(QCloseEvent *closeEvent)
{
emit panelDelete(_tagName,0);
QMessageBox msgBox;
msgBox.setText(QString::fromWCharArray(L"提示"));
msgBox.setInformativeText(QString::fromWCharArray(L"确认关闭?"));
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Ok);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Ok:
{
emit panelDelete(_tagName,0);
}
break;
case QMessageBox::Cancel:
// Cancel was clicked
break;
default:
// should never be reached
break;
}
}
void EditPanel::prepareSaveEditor()

View File

@ -21,6 +21,20 @@ QRectF DiagramLayoutEngine::executeLayout(
// 1. 布局主线
layoutMainRoute(routes[mainRouteName], config, context);
// 设置一级支线父方向
for (auto it = routes.begin(); it != routes.end(); ++it) {
if (it->bMainRoute) continue;
if(it->sParentRoute == mainRouteName) //一级支线方向
it->preferDirection = config.subDirection();
}
for (auto it = routes.begin(); it != routes.end(); ++it) {
if (it->bMainRoute) continue;
if(it->sParentRoute == mainRouteName)
continue;
it->preferDirection = config.mainDirection(); //二级支线方向(与主线同向)
}
// 2. 布局所有支线(✅ 此时方向数据必须是最新的)
for (auto it = routes.begin(); it != routes.end(); ++it) {
if (it->sRouteName == mainRouteName) continue;
@ -91,61 +105,38 @@ void DiagramLayoutEngine::layoutMainRoute(
if (components.isEmpty()) return;
// 计算分段
int nSeg = components.size() / 2;
int nSegIndex = 0;
int nSegIndex =
(mainDir == Direction::Down || mainDir == Direction::Right)
? -nSeg
: nSeg;
// 确定起始索引方向
if (mainDir == Direction::Down || mainDir == Direction::Right) {
nSegIndex = -nSeg; // 正向从负半开始
} else {
nSegIndex = nSeg; // 反向从正半开始
}
// 遍历所有组件
for (int i = 0; i < components.size(); ++i) {
DiagramEditorComponentInfo& compo = components[i];
// 确定方向占用
Direction dir = mainDir;
if (i == 0) {
// 队首保持主线方向
} else if (i == components.size() - 1) {
// 队尾取反方向
if (i == components.size() - 1) {
dir = DirectionManager::getOpposite(mainDir);
} else {
// 中间元件双向占用
compo.nUsedDirection = static_cast<int>(mainDir) |
static_cast<int>(DirectionManager::getOpposite(mainDir));
}
// 计算位置增量
QPoint delta = QPoint(0, 0);
QPoint delta(0, 0);
int spacing = DirectionManager::isHorizontal(mainDir)
? config.horizontalSpacing()
: config.verticalSpacing();
if (DirectionManager::isHorizontal(mainDir)) {
if (DirectionManager::isHorizontal(mainDir))
delta.setX(nSegIndex * spacing);
} else {
else
delta.setY(nSegIndex * spacing);
}
// 计算旋转角度
int rotate = DirectionManager::getRotationAngle(mainDir);
if (!context.saveToModel) {
context.componentsCache[compo.sName] = compo;
}
// 更新组件
// ✅ 主线方向 → 统一交给 updateComponent
updateComponent(compo, dir, delta, rotate, context);
// 更新索引
if (mainDir == Direction::Up || mainDir == Direction::Left) {
nSegIndex -= 1;
} else {
nSegIndex += 1;
}
nSegIndex += (mainDir == Direction::Up || mainDir == Direction::Left)
? -1
: 1;
}
}
@ -214,7 +205,7 @@ void DiagramLayoutEngine::layoutBranchRoute(
// ✅ 第一个元件的真实方向,由 determineBranchDirection 决定
Direction startDir =
determineBranchDirection(route.lstOrder[0],
config.subDirection(),
route.preferDirection,
context);
int polarity = 1;
@ -229,7 +220,7 @@ void DiagramLayoutEngine::layoutBranchRoute(
if (route.lstReverse.size() > 1) {
Direction startDir =
determineBranchDirection(route.lstReverse[0],
config.subDirection(),
route.preferDirection,
context);
int polarity = -1;
layoutBranchSequence(route.lstReverse,
@ -252,14 +243,13 @@ void DiagramLayoutEngine::layoutBranchSequence(
if (sequence.size() < 2) return;
// ✅ 1. 根据主线方向决定展开轴
bool mainIsVertical =
DirectionManager::isVertical(config.mainDirection());
bool isVertical =
DirectionManager::isVertical(branchDir);
// ✅ 2. 间距由主线方向决定
int spacing = mainIsVertical
? config.horizontalSpacing()
: config.verticalSpacing();
int spacing = isVertical
? config.verticalSpacing()
: config.horizontalSpacing();
for (int i = 0; i < sequence.size(); ++i) {
@ -276,14 +266,10 @@ void DiagramLayoutEngine::layoutBranchSequence(
int offset = (i + 1) * polarity * spacing;
QPoint nextPos = basePos;
if (mainIsVertical) {
// ✅ 只在 X 轴应用偏移Y 轴纹丝不动
nextPos.setX(basePos.x() + offset);
// nextPos.setY(basePos.y()); // ✅ 隐式成立,无需再写
} else {
// ✅ 只在 Y 轴应用偏移X 轴纹丝不动
if (isVertical) {
nextPos.setY(basePos.y() + offset);
// nextPos.setX(basePos.x()); // ✅ 隐式成立,无需再写
} else {
nextPos.setX(basePos.x() + offset);
}
QPoint deltaPos = nextPos - basePos;
@ -297,6 +283,25 @@ void DiagramLayoutEngine::layoutBranchSequence(
}
}
}
void DiagramLayoutEngine::markDirectionUsed(
const QString& compoName,
Direction dir,
Context& context)
{
if (context.saveToModel) {
QStandardItem* item = getNameItem(compoName, context);
if (!item) return;
int old = item->data().toInt();
int updated = old | static_cast<int>(dir);
item->setData(updated);
} else {
context.componentsCache[compoName].nUsedDirection |=
static_cast<int>(dir);
}
}
// 确定支线方向
Direction DiagramLayoutEngine::determineBranchDirection(
const DiagramEditorComponentInfo& currentNode,
@ -304,41 +309,23 @@ Direction DiagramLayoutEngine::determineBranchDirection(
Context& context) {
int usedDirections = getComponentDirection(currentNode.sName, context);
bool isHorizontalLayout = DirectionManager::isHorizontal(preferredDir);
bool horizontal = DirectionManager::isHorizontal(preferredDir);
if (isHorizontalLayout) {
// 水平布局,检查左右
bool leftOccupied = DirectionManager::isDirectionOccupied(usedDirections, Direction::Left);
bool rightOccupied = DirectionManager::isDirectionOccupied(usedDirections, Direction::Right);
if (horizontal) {
bool left = DirectionManager::isDirectionOccupied(usedDirections, Direction::Left);
bool right = DirectionManager::isDirectionOccupied(usedDirections, Direction::Right);
if (leftOccupied && rightOccupied) {
qWarning() << "Component" << currentNode.sName
<< "has both left and right directions occupied";
return preferredDir;
} else if (leftOccupied && !rightOccupied) {
return Direction::Right;
} else if (rightOccupied && !leftOccupied) {
return Direction::Left;
} else {
return preferredDir;
}
if (!left && right) return Direction::Left;
if (left && !right) return Direction::Right;
} else {
// 垂直布局,检查上下
bool upOccupied = DirectionManager::isDirectionOccupied(usedDirections, Direction::Up);
bool downOccupied = DirectionManager::isDirectionOccupied(usedDirections, Direction::Down);
bool up = DirectionManager::isDirectionOccupied(usedDirections, Direction::Up);
bool down = DirectionManager::isDirectionOccupied(usedDirections, Direction::Down);
if (upOccupied && downOccupied) {
qWarning() << "Component" << currentNode.sName
<< "has both up and down directions occupied";
return preferredDir;
} else if (upOccupied && !downOccupied) {
return Direction::Down;
} else if (downOccupied && !upOccupied) {
return Direction::Up;
} else {
return preferredDir;
}
if (!up && down) return Direction::Up;
if (up && !down) return Direction::Down;
}
return preferredDir;
}
// 获取组件位置
@ -417,13 +404,6 @@ void DiagramLayoutEngine::updateComponent(
item->setData(QString::number(newDir));
item->setData(position, Qt::UserRole + 2);
item->setData(rotate, Qt::UserRole + 5);
//compo.nUsedDirection = DirectionManager::markDirectionOccupied(compo.nUsedDirection, dir);
//compo.deltaPos = position;
//compo.nRotate = rotate;
// 更新缓存
//context.componentsCache[compo.sName] = compo;
}
} else {
compo.nUsedDirection = DirectionManager::markDirectionOccupied(compo.nUsedDirection, dir);
@ -473,3 +453,22 @@ QRectF DiagramLayoutEngine::calculateBoundingRect(
return QRectF(minX, minY, maxX - minX, maxY - minY);
}
Direction DiagramLayoutEngine::getRouteDirection(
const QString& routeName,
const QMap<QString, DiagramEditorRouteInfo>& routes)
{
if (!routes.contains(routeName))
return Direction::Invalid;
const auto& route = routes[routeName];
if (route.bMainRoute)
return Direction::Invalid; // 主线没有父方向
// ✅ 主线 → 支线
if (route.preferDirection == Direction::Invalid)
return Direction::Invalid; // 等待填充
return route.preferDirection;
}

View File

@ -151,7 +151,7 @@ void FixedLayoutCalculator::calculatePositions(LevelLayout& levelLayout,
container->setMidDownY(deltaY + BUS_V_SPACING);
container->setStartX(startX);
// 计算容器内设备位置
// 计算容器内间隔位置
calculateBlockPositionsInContainer(container, startX, deltaY, deltaY + BUS_V_SPACING);
// 更新水平位置
@ -176,23 +176,30 @@ void FixedLayoutCalculator::calculateBlockPositionsInContainer(DiagramEditorStru
if (!block) continue;
QRectF rec = block->getRecSize();
QPointF centerOffset = block->getCenterOffset(); //参考中心与boundingrect中心的偏移量
QPointF center;
int blockType = block->getType();
if (blockType == 1) { // 母线
if (layer == 1) { // 母线1
center = QPointF(startX, midUpY + rec.height() * 0.5);
center = QPointF(startX-20, midUpY + rec.height() * 0.5);
} else if (layer == 2) { // 母线2
center = QPointF(startX, midDownY - rec.height() * 0.5);
center = QPointF(startX-20, midDownY - rec.height() * 0.5);
}
} else if (blockType == 2) { // 间隔
/*int nLayout = 0; //默认垂直
auto pBay = dynamic_cast<DiagramEditorBayBlock*>(block);
if(pBay){
nLayout = pBay->getBayInfo().nLayout;
}*/
if (layer == 0) { // 上间隔
center = QPointF(currentX + rec.width() * 0.5,
midUpY - rec.height() * 0.5 - Constants::EDITOR_ITEM_HEIGHT * 0.5);
midUpY - rec.height() * 0.5 + centerOffset.y() - 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);
midDownY + rec.height() * 0.5 + centerOffset.y() + Constants::EDITOR_ITEM_HEIGHT * 0.5);
}
currentX += rec.width();
}

View File

@ -224,71 +224,185 @@ void BaseModel::selectTransformerPort(
QMap<QString, ItemPort*> mapSrc = pSrc->getPorts();
QMap<QString, ItemPort*> mapDest = pDest->getPorts();
// src 是变压器
if (nTypeSrc == 15 || nTypeSrc == 16)
// ===== nMode == 1连接中性点 =====
if (nMode == 1)
{
for (auto& port : mapSrc)
// src 是变压器
if (nTypeSrc == 15 || nTypeSrc == 16)
{
int tpe = port->getType();
int pos = port->portPos();
if (tpe != T_newTral)
for (auto& port : mapSrc)
{
if ((nParam == 0 && pos == P_top) ||
(nParam == 1 && (pos == P_left || pos == P_right)) ||
(nParam == 2 && pos == P_down))
int nTpe = port->getType();
int nPos = port->portPos();
if (nTpe == T_newTral)
{
pSrcPort = port;
break;
if (nParam == 0 && nPos == P_top)
{
pSrcPort = port;
break;
}
else if (nParam == 1 &&
(nPos == P_left || nPos == P_right))
{
pSrcPort = port;
break;
}
else if (nParam == 2 && nPos == P_down)
{
pSrcPort = port;
break;
}
}
}
}
int transType = pSrcPort ? pSrcPort->getType() : 0;
for (auto& port : mapDest)
{
if (transType == T_lineOut && port->getType() == T_lineIn)
for (auto& port : mapDest)
{
pDestPort = port;
break;
}
else if (transType == T_lineIn && port->getType() == T_lineOut)
{
pDestPort = port;
break;
}
}
}
// dest 是变压器
else if (nTypeDest == 15 || nTypeDest == 16)
{
for (auto& port : mapDest)
{
int tpe = port->getType();
int pos = port->portPos();
if (tpe != T_newTral)
{
if ((nParam == 0 && pos == P_top) ||
(nParam == 1 && (pos == P_left || pos == P_right)) ||
(nParam == 2 && pos == P_down))
if (port->getType() == T_lineIn)
{
pDestPort = port;
break;
}
}
}
int transType = pDestPort ? pDestPort->getType() : 0;
for (auto& port : mapSrc)
// dest 是变压器
else if (nTypeDest == 15 || nTypeDest == 16)
{
if (transType == T_lineOut && port->getType() == T_lineIn)
for (auto& port : mapSrc)
{
pSrcPort = port;
break;
if (port->getType() == T_lineIn)
{
pSrcPort = port;
break;
}
}
else if (transType == T_lineIn && port->getType() == T_lineOut)
for (auto& port : mapDest)
{
pSrcPort = port;
break;
int nTpe = port->getType();
int nPos = port->portPos();
if (nTpe == T_newTral)
{
if (nParam == 0 && nPos == P_top)
{
pDestPort = port;
break;
}
else if (nParam == 1 &&
(nPos == P_left || nPos == P_right))
{
pDestPort = port;
break;
}
else if (nParam == 2 && nPos == P_down)
{
pDestPort = port;
break;
}
}
}
}
}
// ===== nMode == 2连接非中性点 =====
else if (nMode == 2)
{
// src 是变压器
if (nTypeSrc == 15 || nTypeSrc == 16)
{
for (auto& port : mapSrc)
{
int nTpe = port->getType();
int nPos = port->portPos();
if (nTpe != T_newTral)
{
if (nParam == 0 && nPos == P_top)
{
pSrcPort = port;
break;
}
else if (nParam == 1 &&
(nPos == P_left || nPos == P_right))
{
pSrcPort = port;
break;
}
else if (nParam == 2 && nPos == P_down)
{
pSrcPort = port;
break;
}
}
}
int transType = 0;
if (pSrcPort)
transType = pSrcPort->getType();
for (auto& port : mapDest)
{
if (transType == T_lineOut &&
port->getType() == T_lineIn)
{
pDestPort = port;
break;
}
else if (transType == T_lineIn &&
port->getType() == T_lineOut)
{
pDestPort = port;
break;
}
}
}
// dest 是变压器
else if (nTypeDest == 15 || nTypeDest == 16)
{
for (auto& port : mapDest)
{
int nTpe = port->getType();
int nPos = port->portPos();
if (nTpe != T_newTral)
{
if (nParam == 0 && nPos == P_top)
{
pDestPort = port;
break;
}
else if (nParam == 1 &&
(nPos == P_left || nPos == P_right))
{
pDestPort = port;
break;
}
else if (nParam == 2 && nPos == P_down)
{
pDestPort = port;
break;
}
}
}
int transType = 0;
if (pDestPort)
transType = pDestPort->getType();
for (auto& port : mapSrc)
{
if (transType == T_lineOut &&
port->getType() == T_lineIn)
{
pSrcPort = port;
break;
}
else if (transType == T_lineIn &&
port->getType() == T_lineOut)
{
pSrcPort = port;
break;
}
}
}
}

View File

@ -981,9 +981,16 @@ QStandardItem* DiagramEditorModel::getNameItem(const QString& sName,int nFrom)
void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,DiagramEditorBaseBlock* pBlock,int nFrom,QPoint delta)
{
QPointF originPos = QPointF(0,0);
int rowCount = pModel->rowCount();
for(int i = 0;i < rowCount;++i){
QStandardItem *itemComps = pModel->item(i, 1);
QStandardItem *itemComps = nullptr;
if(pBlock->getType() == 3)
itemComps = pModel->item(i, 1); //变压器暂时没变
else
itemComps = pModel->item(i, 2);
if(!itemComps)
continue;
QString sComps = itemComps->text();
QStringList lst = sComps.split(",");
for(auto& name:lst){ //第一次循环生成item
@ -1002,11 +1009,17 @@ void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,DiagramE
if(pItem->data(Qt::UserRole+5).isValid())
nRotate = pItem->data(Qt::UserRole+5).toInt();
QPoint pos = pItem->data(Qt::UserRole+2).toPoint();
bool isOrigin = false;
if(pos.isNull()){ //是相对中心点
isOrigin = true;
}
pos += delta;
QUuid uid = pItem->data(Qt::UserRole+3).toUuid();
if(!_tempItem.contains(uid)){
int nBaseType = BaseTypeManager::getInstance()->getBaseTypeById(nType);
generateComponent(uid,name,nCate,nType,nBaseType,pos,nRotate,0,pBlock);
auto pItem = generateComponent(uid,name,nCate,nType,nBaseType,pos,nRotate,0,pBlock);
if(isOrigin)
originPos = pItem->scenePos();
}
}
}
@ -1044,6 +1057,9 @@ void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,DiagramE
}
}
}
QPointF offset = originPos-_pCurPreviewScene->itemsBoundingRect().center();
pBlock->setCenterOffset(offset);
}
QList<DiagramEditorComponentInfo> DiagramEditorModel::generateItemByInfo(QMap<QString,DiagramEditorRouteInfo>& mapRoute,QMap<QString,DiagramEditorComponentInfo>& mapCompo,QPointF delta,DiagramEditorBaseBlock* pParent)

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>580</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>580</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
@ -80,6 +86,34 @@ QWidget QLabel {
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_bay">
<property name="font">
<font>
<pointsize>-1</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
@ -87,7 +121,7 @@ QWidget QLabel {
</property>
<property name="sizeHint" stdset="0">
<size>
<width>530</width>
<width>40</width>
<height>20</height>
</size>
</property>
@ -121,6 +155,16 @@ QWidget QLabel {
<item>
<widget class="QComboBox" name="cb_layout"/>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>间隔位置</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cb_locate"/>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>580</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
@ -182,7 +188,7 @@ QWidget QLabel {
<number>20</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout" columnstretch="1,2">
<layout class="QGridLayout" name="gridLayout" columnstretch="1,3">
<property name="leftMargin">
<number>0</number>
</property>

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>580</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>580</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
@ -80,6 +86,34 @@ QWidget QLabel {
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>530</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_name">
<property name="font">
<font>
<pointsize>-1</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

View File

@ -6,9 +6,15 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>605</width>
<height>580</height>
</rect>
</size>
</property>
<property name="font">
<font>
@ -152,7 +158,7 @@ QWidget QLabel {
<number>20</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0" columnstretch="1,2">
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0" columnstretch="1,3">
<property name="verticalSpacing">
<number>10</number>
</property>

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>726</width>
<height>532</height>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>