530 lines
19 KiB
C++
530 lines
19 KiB
C++
#include <QMessageBox>
|
|
#include <QMenu>
|
|
#include "diagramEditor/diagramEditorBayDetailSettingDlg.h"
|
|
#include "diagramEditor/diagramEditorBayDetailAddDlg.h"
|
|
#include "diagramEditor/diagramEditorBayPreviewDlg.h"
|
|
#include "ui_diagramEditorBayDetailSettingDlg.h"
|
|
#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>
|
|
#include "titleBar.h"
|
|
#include <QSizeGrip>
|
|
|
|
DiagramEditorBayDetailSettingDlg::DiagramEditorBayDetailSettingDlg(QWidget *parent,DiagramEditorModel* pModel)
|
|
: QDialog(parent)
|
|
, ui(new Ui::diagramEditorBayDetailSettingDlg)
|
|
,_pAddDlg(nullptr)
|
|
,_curOperateObj(nullptr)
|
|
,_compoModel(nullptr)
|
|
,_routeModel(nullptr)
|
|
,_pPreviewDlg(nullptr)
|
|
,_pModel(pModel)
|
|
,_pWizard(nullptr)
|
|
,_pSizeGrip(nullptr)
|
|
{
|
|
ui->setupUi(this);
|
|
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
|
|
this->setWindowModality(Qt::WindowModal);
|
|
setStyleSheet("background-color: white;");
|
|
initial();
|
|
}
|
|
|
|
DiagramEditorBayDetailSettingDlg::~DiagramEditorBayDetailSettingDlg()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::initial()
|
|
{
|
|
m_titleBar = new TitleBar(this);
|
|
m_titleBar->setTitle("间隔详细设置");
|
|
ui->verticalLayout_2->insertWidget(0,m_titleBar);
|
|
_pSizeGrip = new QSizeGrip(this);
|
|
_pSizeGrip->setFixedSize(12, 12);
|
|
|
|
_compoModel = new QStandardItemModel(this);
|
|
_routeModel = new QStandardItemModel(this);
|
|
_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);
|
|
connect(ui->tableView, &QTableView::customContextMenuRequested, this, &DiagramEditorBayDetailSettingDlg::onRouteRbtnClicked);
|
|
|
|
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
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);
|
|
if(_pModel){
|
|
_pModel->setCurBayComponentModel(_compoModel);
|
|
_pModel->setCurBayRouteModel(_routeModel);
|
|
}
|
|
_pPreviewDlg->setSceneRect(ui->tableView->rect());
|
|
QVBoxLayout *layout = new QVBoxLayout;
|
|
layout->addWidget(_pPreviewDlg);
|
|
ui->groupBox_preview->setLayout(layout);
|
|
}
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::refreshModel()
|
|
{
|
|
if(_curOperateObj){
|
|
_compoModel->clear();
|
|
_compoModel->setColumnCount(5);
|
|
_compoModel->setHorizontalHeaderLabels({"分类", "名称", "类型", "关联对象", "引用线路"});
|
|
auto mapComponent = _curOperateObj->getBayInfo().mapComponent;
|
|
for(auto& comp:mapComponent){
|
|
DiagramEditorComponentInfo info = comp;
|
|
QStandardItem *itemCate = new QStandardItem();
|
|
QStandardItem *itemName = new QStandardItem();
|
|
QStandardItem *itemType = new QStandardItem();
|
|
QStandardItem *itemObj = new QStandardItem();
|
|
QStandardItem *itemRoute = new QStandardItem();
|
|
QString sCategory;
|
|
QString sType;
|
|
if(info.nCategory == 0){
|
|
sCategory = "电气设备";
|
|
sType = BaseTypeManager::getInstance()->getNameById(info.nType);
|
|
}
|
|
else if(info.nCategory == 1){
|
|
sCategory = "连接关系";
|
|
if(info.nType == 0){ //连接点暂时写死
|
|
sType = "连接点";
|
|
}
|
|
}
|
|
int nBaseType = BaseTypeManager::getInstance()->getBaseTypeById(info.nType);
|
|
itemCate->setText(sCategory);
|
|
itemCate->setData(info.nCategory);
|
|
itemName->setText(info.sName);
|
|
itemName->setData(info.nUsedDirection);
|
|
itemName->setData(info.deltaPos,Qt::UserRole+2);
|
|
itemName->setData(info.uid,Qt::UserRole+3);
|
|
itemName->setData(info.nFlag,Qt::UserRole+4);
|
|
itemName->setData(info.nRotate,Qt::UserRole+5);
|
|
itemType->setText(sType);
|
|
itemType->setData(info.nType);
|
|
itemType->setData(nBaseType,Qt::UserRole+2);
|
|
itemObj->setText(info.sBindObj);
|
|
itemObj->setData(info.nBindType);
|
|
itemObj->setData(info.nBindPara,Qt::UserRole+2);
|
|
itemObj->setData(info.sBindParent,Qt::UserRole+3);
|
|
itemRoute->setText(info.sUsedRoute.join("、"));
|
|
|
|
QList<QStandardItem*> lstItems;
|
|
lstItems<<itemCate<<itemName<<itemType<<itemObj<<itemRoute;
|
|
_compoModel->appendRow(lstItems);
|
|
}
|
|
|
|
_routeModel->clear();
|
|
_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; //更新路径数据到本界面
|
|
|
|
for(auto& route:mapRoute){
|
|
QString sRoute = route.sRouteName;
|
|
if(sRoute.isEmpty())
|
|
continue;
|
|
QStringList lstComp;
|
|
for(auto& comp:route.lstCompo){
|
|
lstComp.append(comp.sName);
|
|
}
|
|
|
|
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<<itemParent<<itemComponents;
|
|
|
|
_routeModel->appendRow(lstItems);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::showDlg(DiagramEditorBayBlock* p)
|
|
{
|
|
show();
|
|
_curOperateObj = p;
|
|
if(p->getBayType() == BayType::busSectionBay) //分段间隔默认水平
|
|
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);
|
|
m_titleBar->setCenterText(p->getName());
|
|
refreshModel();
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::onAddClicked()
|
|
{
|
|
if(_pAddDlg == nullptr){
|
|
_pAddDlg = new DiagramEditorBayDetailAddDlg(this);
|
|
_pAddDlg->setParent(this);
|
|
}
|
|
_pAddDlg->showDlg();
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::onOkClicked()
|
|
{
|
|
//将ui设置的参数更新到对应block
|
|
bool changePos = false;
|
|
if(_curOperateObj){
|
|
|
|
QMap<QString, DiagramEditorComponentInfo> tempComponents;
|
|
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);
|
|
|
|
DiagramEditorComponentInfo info;
|
|
// ✅ 必须恢复的字段(原代码中有)
|
|
int nDir = itemName->data(Qt::UserRole+1).toInt();
|
|
QPoint deltaPos = itemName->data(Qt::UserRole+2).toPoint();
|
|
int nVal = itemName->data(Qt::UserRole+4).toInt();
|
|
int nRotate = itemName->data(Qt::UserRole+5).toInt();
|
|
|
|
info.sName = itemName->text();
|
|
info.uid = itemName->data(Qt::UserRole+3).toUuid();
|
|
|
|
if(itemCate->text() == "电气设备"){
|
|
info.nCategory = 0;
|
|
}
|
|
else if(itemCate->text() == "连接关系"){
|
|
info.nCategory = 1;
|
|
}
|
|
|
|
info.nType = itemType->data().toInt();
|
|
info.sBindObj = itemBind->text();
|
|
info.nBindType = itemBind->data().toInt();
|
|
info.nBindPara = itemBind->data(Qt::UserRole+2).toInt();
|
|
info.sBindParent = itemBind->data(Qt::UserRole+3).toString();
|
|
info.sUsedRoute = itemRoute->text().split(",");
|
|
|
|
// ✅ 关键修复:恢复被丢弃的状态
|
|
info.nUsedDirection = nDir;
|
|
info.deltaPos = deltaPos;
|
|
info.nFlag = nVal;
|
|
info.nRotate = nRotate;
|
|
tempComponents.insert(info.sName, info);
|
|
}
|
|
|
|
// ✅ 2. 设置布局参数
|
|
int nLayout = ui->cb_layout->currentData().toInt();
|
|
_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(
|
|
_curBayInfo.mapRoute,
|
|
_curBayInfo.mapComponent,
|
|
_curBayInfo.directionOccupancyMap,
|
|
_curBayInfo.routeDirectionMap,
|
|
0);
|
|
|
|
QRectF recBounding =
|
|
getModel()->updateTarget(
|
|
_curBayInfo.mapRoute,
|
|
_curBayInfo.mapComponent,
|
|
_curBayInfo.directionOccupancyMap,
|
|
_curBayInfo.routeDirectionMap,
|
|
nDir,
|
|
0,
|
|
false); // ✅ 结果写回 mapComponent
|
|
|
|
// ✅ 4. 保存“已经算好的正确数据”
|
|
if (_curOperateObj->getRecSize().isEmpty())
|
|
_curOperateObj->setRecSize(recBounding);
|
|
|
|
_curOperateObj->setBayInfo(_curBayInfo); // ✅ 此时 mapComponent 是正确的
|
|
|
|
TopologyManager::instance().clearGlobalBlockData(_curOperateObj->getName());
|
|
TopologyManager::instance().moveTempBlockData();
|
|
_curOperateObj->setEditState(true);
|
|
_curOperateObj = nullptr;
|
|
}
|
|
hide();
|
|
if(changePos){
|
|
_pModel->getPanel()->initByWizardInfo();
|
|
}
|
|
|
|
QTimer::singleShot(300, this, [this]() {
|
|
_pModel->clearCurPreview(); //关闭时清除预览Item
|
|
_pModel->generatePreview();
|
|
_pModel->calculateBlockPos();
|
|
_pModel->setItemInBlockPos();
|
|
_pModel->refreshConnection();
|
|
});
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::onCancelClicked()
|
|
{
|
|
hide();
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::onRouteDeleteClicked()
|
|
{
|
|
// 获取当前选中的索引
|
|
QModelIndexList selectedIndexes = ui->tableView->selectionModel()->selectedRows();
|
|
if (selectedIndexes.isEmpty()) {
|
|
return; // 没有选中任何行
|
|
}
|
|
|
|
// 获取行号并排序(从大到小删除避免索引变化)
|
|
QList<int> rowsToRemove;
|
|
foreach (const QModelIndex &index, selectedIndexes) {
|
|
rowsToRemove.append(index.row());
|
|
}
|
|
|
|
// 获取当前选中的第一项索引
|
|
QModelIndex index = selectedIndexes.first();
|
|
if (!index.isValid()) {
|
|
return;
|
|
}
|
|
|
|
QModelIndex indexName = index.sibling(index.row(),0);
|
|
QString sName = indexName.data().toString();
|
|
|
|
// 移除行
|
|
foreach (int row, rowsToRemove) {
|
|
QList<QStandardItem*> rowItems;
|
|
for (int col = 0; col < _routeModel->columnCount(); ++col) {
|
|
QStandardItem *item = _routeModel->takeItem(row, col);
|
|
rowItems.append(item);
|
|
}
|
|
qDeleteAll(rowItems); //take的item不释放
|
|
_routeModel->removeRow(row);
|
|
}
|
|
|
|
onRouteModified(_curBayInfo.mapRoute,_curBayInfo.routeOrder,sName,true);
|
|
auto info = _curBayInfo.mapRoute.value(sName);
|
|
QStringList lst;
|
|
for(auto &compo:info.lstCompo){
|
|
lst.append(compo.sName);
|
|
}
|
|
removeRouteUsageFromDevices(lst,sName);
|
|
_curBayInfo.mapRoute.remove(sName); //同步移除数据
|
|
_curBayInfo.routeOrder.removeAll(sName); //移除排序
|
|
|
|
_pModel->removeRouteDir(sName,_curBayInfo.mapComponent,_curBayInfo.directionOccupancyMap,_curBayInfo.routeDirectionMap,0);
|
|
|
|
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)
|
|
{
|
|
QModelIndex index = ui->tableView->indexAt(pos);
|
|
if (!index.isValid()) {
|
|
return; // 如果点击的是空白区域,直接返回
|
|
}
|
|
|
|
QMenu menu;
|
|
QAction *deleteAction = new QAction("删除", this);
|
|
QAction *modifyAction = new QAction("修改", this);
|
|
menu.addAction(deleteAction);
|
|
menu.addAction(modifyAction);
|
|
|
|
// 连接删除菜单项的触发信号与槽函数
|
|
connect(deleteAction, &QAction::triggered, this, &DiagramEditorBayDetailSettingDlg::onRouteDeleteClicked);
|
|
//连接修改
|
|
connect(modifyAction, &QAction::triggered, this, &DiagramEditorBayDetailSettingDlg::onRouteEditClicked);
|
|
|
|
// 在点击位置显示菜单
|
|
menu.exec(ui->tableView->mapToGlobal(pos));
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::onRouteEditClicked()
|
|
{
|
|
if(_pAddDlg == nullptr){
|
|
_pAddDlg = new DiagramEditorBayDetailAddDlg(this);
|
|
_pAddDlg->setParent(this);
|
|
}
|
|
|
|
// 获取当前选中的索引
|
|
QModelIndexList selectedIndexes = ui->tableView->selectionModel()->selectedRows();
|
|
if (selectedIndexes.isEmpty()) {
|
|
return; // 没有选中任何行
|
|
}
|
|
// 获取当前选中的第一项索引
|
|
QModelIndex index = selectedIndexes.first();
|
|
if (!index.isValid()) {
|
|
return;
|
|
}
|
|
QModelIndex indexName = index.sibling(index.row(),0);
|
|
QString sName = indexName.data().toString();
|
|
|
|
auto routeInfo = _curBayInfo.mapRoute.value(sName);
|
|
_pAddDlg->showDlg(routeInfo);
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::showPreview()
|
|
{
|
|
int nLayout = ui->cb_layout->currentData().toInt();
|
|
_pPreviewDlg->showDlg(nLayout);
|
|
QRectF recContainAll = _pModel->generateTempBay(_curOperateObj);
|
|
if(_curOperateObj){
|
|
_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);
|
|
}
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::resizeEvent(QResizeEvent *) {
|
|
_pSizeGrip->move(width() - _pSizeGrip->width(),
|
|
height() - _pSizeGrip->height());
|
|
}
|
|
|
|
void DiagramEditorBayDetailSettingDlg::removeRouteUsageFromDevices(const QStringList &deviceNames, const QString &routeName)
|
|
{
|
|
if (deviceNames.isEmpty() || routeName.isEmpty()) {
|
|
qWarning() << "设备名列表或路线名为空";
|
|
return;
|
|
}
|
|
|
|
auto pCompoModel = _compoModel;
|
|
if (!pCompoModel) {
|
|
qWarning() << "组件模型为空";
|
|
return;
|
|
}
|
|
|
|
// 1. 设备名去重
|
|
QSet<QString> uniqueDeviceNames(deviceNames.begin(),deviceNames.end());
|
|
|
|
// 2. 遍历组件模型
|
|
for (int row = 0; row < pCompoModel->rowCount(); ++row) {
|
|
QStandardItem *itemName = pCompoModel->item(row, 1);
|
|
if (!itemName) continue;
|
|
|
|
QString currentDevice = itemName->text();
|
|
if (uniqueDeviceNames.contains(currentDevice)) {
|
|
// 3. 移除路线占用
|
|
QStandardItem *itemUsed = pCompoModel->item(row, 4);
|
|
if (!itemUsed) continue;
|
|
|
|
QString usageText = itemUsed->text();
|
|
QStringList routes = usageText.split(",", Qt::SkipEmptyParts);
|
|
|
|
int beforeCount = routes.count();
|
|
routes.removeAll(routeName);
|
|
|
|
// 4. 只有当有实际变化时才更新
|
|
if (routes.count() != beforeCount) {
|
|
itemUsed->setText(routes.isEmpty() ? "" : routes.join(","));
|
|
}
|
|
|
|
// 5. 从待处理集合中移除
|
|
uniqueDeviceNames.remove(currentDevice);
|
|
|
|
// 6. 如果所有设备都已处理,提前结束
|
|
if (uniqueDeviceNames.isEmpty()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|