add data previewer structure

This commit is contained in:
baiYue 2025-12-31 17:15:55 +08:00
parent 90e5cf755a
commit 05b6f448e9
26 changed files with 1527 additions and 60 deletions

View File

@ -22,6 +22,8 @@ public:
virtual QJsonObject context() const {return jContext;}
virtual void setSubList(QList<QPair<int,QUuid>> lst) {subList = lst;}
virtual QList<QPair<int,QUuid>>& getSubList() {return subList;}
virtual void setVoltageLevel(double d){dVoltageLevel = d;}
virtual double getVoltageLevel() const {return dVoltageLevel;}
virtual QJsonArray saveSubToJsonArr();
protected:
@ -30,6 +32,7 @@ protected:
QString sName;
QJsonObject jContext; //存放port信息
QList<QPair<int,QUuid>> subList; //可能存在的子对象(不用来拓朴计算) <类型uid> //类型0:设备 1:间隔
double dVoltageLevel; //所属电压等级
};
class BayProperty:public AbstractProperty //间隔属性(待扩展)

View File

@ -478,6 +478,7 @@ struct DiagramEditorWizardTransformerInfo //组态变压器信息
{
QString sName;
TransformerType nType;
double dVoltageLevel;
QList<EditorTransConnection> lstBindObj; //连接的对象
};
@ -485,6 +486,7 @@ struct DiagramEditorWizardBayInfo //组态间隔信息
{
QString sName;
BayType nType;
double dVoltageLevel;
QList<QString> lstBindObj; //连接的对象
};
@ -922,6 +924,97 @@ struct MeasurementInfo //量测
QStringList lstParameter; //"action:parameters" 字符串数组
};
//属性其他参数与层级关系
struct ExtraProperty
{
int id = 0;
QString code; // 唯一编码(拼接字符串)
QString tag; // 属性tag
QString name; // 显示名称
QString connect_para; // 连接参数
// 层级名称
QString grid_name;
QString zone_name;
QString station_name;
QString currentLevel;
QString bay_name;
QString component_name;
QString group_name;
//层级索引
QString grid_tag;
QString zone_tag;
QString station_tag;
QString page_tag;
QString bay_tag;
QUuid component_uuid;
QString group_tag;
// 数据源配置
QString sourceType; // "property", "measurement"
QVariantMap sourceConfig;
// 获取完整路径
QString getFullName() const {
QStringList parts = {grid_name, zone_name, station_name, currentLevel, bay_name, component_name, group_name, name};
parts.removeAll("");
return parts.join(".");
}
//获取完整索引
QString getFullTag() const {
QStringList parts = {grid_tag, zone_tag, station_tag, page_tag, currentLevel, bay_tag, component_uuid.toString(), group_tag, tag};
parts.removeAll("");
return parts.join(".");
}
// 检查是否匹配过滤条件
bool matches(const QVariantMap& filter,const QString& type) const {
for (auto it = filter.begin(); it != filter.end(); ++it) {
QString field = it.key();
QString filterValue = it.value().toString();
QString fieldValue;
if(type == "name"){
fieldValue = getFieldName(field);
}
else if(type == "tag"){
fieldValue = getFieldTag(field);
}
if (!filterValue.isEmpty() && fieldValue != filterValue) {
return false;
}
}
return true;
}
QString getFieldName(const QString& field) const {
if (field == "grid") return grid_name;
if (field == "zone") return zone_name;
if (field == "station") return station_name;
if (field == "currentLevel") return currentLevel;
if (field == "bay") return bay_name;
if (field == "component") return component_name;
if (field == "group") return group_name;
if (field == "property") return name;
return "";
}
QString getFieldTag(const QString& field) const {
if (field == "grid") return grid_tag;
if (field == "zone") return zone_tag;
if (field == "station") return station_tag;
if (field == "page") return page_tag;
if (field == "currentLevel") return currentLevel;
if (field == "bay") return bay_tag;
if (field == "component") return component_name;
if (field == "group") return component_uuid.toString();
if (field == "tag") return name;
return "";
}
};
//==================================================
struct baseComponentInfo //基模图元数据
{

View File

@ -41,6 +41,8 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/projectIconSelectionDlg.h
include/projectDiagramNameInput.h
include/diagramConnectSetting.h
include/structDataPreviewDlg.h
include/titleBar.h
include/diagramEditor/editPanel.h
include/diagramEditor/editView.h
include/diagramEditor/editScene.h
@ -114,6 +116,7 @@ set(DIAGRAMCAVAS_HEADER_FILES
include/util/selectorManager.h
include/util/subMovingSelector.h
include/instance/dataAccessor.h
include/instance/extraPropertyManager.h
../common/include/httpInterface.h
../common/include/tools.h
../common/include/global.h
@ -163,6 +166,8 @@ set(DIAGRAMCAVAS_SOURCE_FILES
source/projectIconSelectionDlg.cpp
source/projectDiagramNameInput.cpp
source/diagramConnectSetting.cpp
source/structDataPreviewDlg.cpp
source/titleBar.cpp
source/diagramEditor/editPanel.cpp
source/diagramEditor/editView.cpp
source/diagramEditor/editScene.cpp
@ -236,6 +241,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES
source/util/selectorManager.cpp
source/util/subMovingSelector.cpp
source/instance/dataAccessor.cpp
source/instance/extraPropertyManager.cpp
../common/source/httpInterface.cpp
../common/source/baseProperty.cpp
../common/source/tools.cpp
@ -268,6 +274,7 @@ set(UI_FILES
ui/monitorDisplaySettingDlg.ui
ui/loadMonitorPageDlg.ui
ui/diagramConnectSetting.ui
ui/structDataPreviewDlg.ui
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)

View File

@ -21,6 +21,8 @@ class LoadMonitorPageDlg;
class DiagramConnectSetting;
class DataAccessor;
struct HttpRecommandInfo;
class StructDataPreviewDlg;
class ExtraPropertyManager;
class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea
{
@ -38,6 +40,7 @@ public:
void updateSubPos();
void passRecommmandHttpData(HttpRecommandInfo); //传递推荐列表数据
DiagramConnectSetting* getConnectSettingDlg() {return _connectSetting;}
ExtraPropertyManager* getExtraPropertyManager() {return _extraPropertyManager;}
public:
void initial();
signals:
@ -71,6 +74,7 @@ public slots:
void onSignal_selectDiagram(DiagramInfo);
void onSignal_openNetSetting(); //打开网络设置
void onSignal_openStructDataPreview(); //打开结构数据界面
void onCreateTestBaseModelDiagram(); //生成测试基模图
/******************************生成组态***********************************/
@ -114,6 +118,8 @@ private:
LoadMonitorPageDlg* _loadMonitorPageDlg;
DiagramConnectSetting* _connectSetting;
DataAccessor* _dataAccessor;
StructDataPreviewDlg* _structDataPreviewDlg;
ExtraPropertyManager* _extraPropertyManager;
};
#endif

View File

@ -45,6 +45,8 @@ public:
virtual QPointF getSceneDelta() {return sceneDelta;}
virtual void setEditState(bool b){bEditState = b;}
virtual bool getEditState(){return bEditState;}
virtual void setVoltage(float f) { fVoltage = f;}
virtual float getVoltage() {return fVoltage;}
virtual DiagramEditorBlockInfo getBlockInfo(); //返回block中存储的信息
protected:
DiagramEditorStructContainer* _curContainer; //当前所处的容器
@ -77,14 +79,11 @@ class DiagramEditorBusBlock:public DiagramEditorBaseBlock
public:
DiagramEditorBusBlock(QObject *parent = 0);
virtual ~DiagramEditorBusBlock();
virtual void setVoltage(float f) { fVoltage = f;}
virtual float getVoltage() {return fVoltage;}
virtual void setBusType(int n) {nBusType = n;}
virtual int getBusType() {return nBusType;}
virtual void setIndex(int n) {nIndex = n;}
virtual int getIndex() {return nIndex;}
virtual void setBusPro(QString sNa,int nTp,float fVol,int nBT,int nIdx) {sName = sNa;nType = nTp;fVoltage = fVol;nBusType = nBT;nIndex = nIdx;}
};
/***************************bay单元****************************/

View File

@ -14,6 +14,7 @@ class DiagramEditorWizard;
class DiagramCavas;
class EditBaseItem;
class DiagramEditorBaseBlock;
class DiagramEditorBayBlock;
int const g_nHorizontalBlockSpacing = 100; //间隔横向间距
@ -27,12 +28,12 @@ public:
bool addPreviewItem(QUuid uuid,GraphicsBaseModelItem*,int mode); //mode 0局部1整体
DiagramEditorItemProperty* addPreviewData(QUuid id,int type,QString name,QString metaName,QString sBlock,int mode = 0); //添加图元基模数据 mode:0局部1整体
void createTopoTerminalsByItem(GraphicsBaseItem*,ModelFunctionType funType = ModelFunctionType::ProjectModel); //通过图形对象创建port接线点(新建)
QRectF generateTempBay(); //通过设置生成间隔预览对象
QRectF generateTempBay(DiagramEditorBayBlock*); //通过设置生成间隔预览对象
void generateTempTrans(int nType,DiagramEditorTransformerBlock* block = nullptr); //0高压侧1中压侧2低压侧3整个变压器
void connectTransToNeutral(DiagramEditorTransformerBlock* block); //连接变压器与中性点设备
void linkTransItem(GraphicsBaseModelItem*,QStandardItemModel*); //连接中性点与设备点
GraphicsBaseModelItem* generateComponent(QUuid uid,QString sName,int nCategory,int nType,QPointF pos,int nRotate,int mode,QString sBay = QString()); //生成设备 uid,分类(设备、逻辑点),类型,旋转,模式(0局部1整体)
ElectricBaseModelLineItem* generateLine(QUuid uid,QString sName,int mode,QString sBay = QString()); //生成连线 mode 0局部1整体
void linkTransItem(GraphicsBaseModelItem*,QStandardItemModel*,DiagramEditorTransformerBlock* pBlock); //连接中性点与设备点
GraphicsBaseModelItem* generateComponent(QUuid uid,QString sName,int nCategory,int nType,QPointF pos,int nRotate,int mode,DiagramEditorBaseBlock* pBlock = nullptr); //生成设备 uid,分类(设备、逻辑点),类型,旋转,模式(0局部1整体)
ElectricBaseModelLineItem* generateLine(QUuid uid,QString sName,int mode,DiagramEditorBaseBlock* pBlock = nullptr); //生成连线 mode 0局部1整体
void clearCurPreview();
void setPanel(EditPanel* p) {_pPanel = p;}
EditPanel* getPanel(){return _pPanel;}
@ -57,7 +58,7 @@ public:
void setCurPreviewScene(EditBaseScene* p) {_pCurPreviewScene = p;}
QStandardItem* getNameItem(const QString&,int nFrom = 0); //获取返回当前设备模型中的name项 nFrom,0间隔1变压器
void generateItemByModel(QStandardItemModel* pModel,int nFrom = 0,QPoint delta = QPoint(0,0)); //0间隔1变压器
void generateItemByModel(QStandardItemModel* pModel,DiagramEditorBaseBlock* pBlock,int nFrom = 0,QPoint delta = QPoint(0,0)); //0间隔1变压器
QList<DiagramEditorComponentInfo> generateItemByInfo(QMap<QString,DiagramEditorRouteInfo> mapRoute,QMap<QString,DiagramEditorComponentInfo> mapCompo,QPointF delta = QPointF(0,0),DiagramEditorBaseBlock* pParent = nullptr); //根据data生成item parent:生成的对象添加到parent下(非拓扑计算)
QMultiMap<int,QUuid> generateOutConnection(QList<DiagramEditorComponentInfo>,int nTypeTransCon,int nPos = 0,DiagramEditorBaseBlock* pParent = nullptr); //生成外部连接手动bind的连接 nTypeTransCon变压器连线类型,1中性点连接2外部连接,nPos中性点连接时的位置
QRectF updateTarget(QMap<QString,DiagramEditorRouteInfo>&,QMap<QString,DiagramEditorComponentInfo>&,int nLayout,int nSource,bool saveToModel = true); //更新位置 nLayout主次朝向:8421,8421 上下左右,上下左右 nSource:0间隔1变压器 regenerate重新生成标志 saveToModel:生成到模型或map

View File

@ -0,0 +1,38 @@
// extraPropertyManager.h
#pragma once
#include <QObject>
#include <QVector>
#include <QMap>
#include "global.h"
/**
*
* */
class ExtraPropertyManager : public QObject {
Q_OBJECT
public:
explicit ExtraPropertyManager(QObject* parent = nullptr);
// 加载所有属性
bool loadAll();
void initial();
// 查询方法
QVector<ExtraProperty> getByFilter(const QVariantMap& filter,const QString& filterType) const; //filterType:name,tag
ExtraProperty getByCode(const QString& code) const;
QMap<QString, ExtraProperty> geAlltProperty() {return m_props;}
// CRUD操作
int add(const ExtraProperty& prop);
bool update(const ExtraProperty& prop);
bool remove(int id);
// 层级选项
QStringList getGrids() const;
QStringList getZones(const QString& grid = "") const;
QStringList getStations(const QString& grid = "", const QString& zone = "") const;
private:
QMap<QString, ExtraProperty> m_props; // 内存缓存
};

View File

@ -0,0 +1,54 @@
#ifndef STRUCTDATAPREVIEWDLG_H
#define STRUCTDATAPREVIEWDLG_H
/**
* **************
**/
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui { class structDataPreviewDlg; }
QT_END_NAMESPACE
class QStandardItemModel;
class TitleBar;
class ExtraPropertyManager;
class StructDataPreviewDlg : public QDialog
{
Q_OBJECT
public:
StructDataPreviewDlg(QWidget *parent = nullptr);
~StructDataPreviewDlg();
void initial();
void showMaximized();
void showNormal();
void setExtraPropertyManager(ExtraPropertyManager* p) {_pExtraProManager = p;}
void showDlg();
public slots:
void onExitClicked();
void onSaveClicked();
void onGridClicked(); //网
void onZoneClicked(); //区
void onStationClicked(); //站
void onBayClicked(); //间隔
void onDeviceClicked(); //设备
void onPropertyClicked(); //属性
protected:
void showEvent(QShowEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private slots:
void toggleMaximize();
private:
void clearItems();
private:
Ui::structDataPreviewDlg *ui;
QStandardItemModel* _treeModel;
TitleBar* m_titleBar;
QRect m_normalGeometry; // 记录正常状态的位置和大小
ExtraPropertyManager* _pExtraProManager; //使用外部的manager
};
#endif

View File

@ -0,0 +1,47 @@
#ifndef TITLEBAR_H
#define TITLEBAR_H
/**
*
* */
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QWidget>
#include <QMouseEvent>
#include <QApplication>
class TitleBar : public QWidget
{
Q_OBJECT
public:
explicit TitleBar(QWidget *parent = nullptr);
void setTitle(const QString &title);
void updateMaximizeButton(); // 根据窗口状态更新按钮文本
signals:
void maximizeClicked();
void closeClicked();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
private:
void setupUI();
private:
QPoint m_dragStartPosition;
QWidget *m_parentWindow;
QLabel *m_titleLabel;
QPushButton *m_maximizeButton;
QPushButton *m_closeButton;
bool m_isMaximized = false;
};
#endif

View File

@ -25,6 +25,8 @@
#include "uiCommunicationBus.h"
#include "itemPropertyDlg.h"
#include "monitorConfigDlg.h"
#include "structDataPreviewDlg.h"
#include "instance/extraPropertyManager.h"
DiagramCavas::DiagramCavas(QWidget *parent)
: QMdiArea(parent)
@ -32,6 +34,8 @@ DiagramCavas::DiagramCavas(QWidget *parent)
,_loadMonitorPageDlg(nullptr)
,_connectSetting(nullptr)
,_dataAccessor(nullptr)
,_structDataPreviewDlg(nullptr)
,_extraPropertyManager(nullptr)
{
_pageIndex = 0;
}
@ -137,6 +141,9 @@ void DiagramCavas::initial()
ConfigManager* config = ConfigManager::instance();
config->loadConfig("config.json");
_extraPropertyManager = new ExtraPropertyManager(this);
_extraPropertyManager->initial();
// 应用配置
comm->updateHttpConfig(config->getHttpConfig());
comm->updateWebSocketConfig(config->getWebSocketConfig());
@ -153,6 +160,8 @@ void DiagramCavas::initial()
_dataAccessor,
SLOT(onReceiveWebsocketData(QVariant)),
Qt::AutoConnection);
_structDataPreviewDlg = new StructDataPreviewDlg(this);
_structDataPreviewDlg->setExtraPropertyManager(_extraPropertyManager);
}
void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent)
@ -517,6 +526,12 @@ void DiagramCavas::onSignal_openNetSetting()
}
}
void DiagramCavas::onSignal_openStructDataPreview()
{
if(_structDataPreviewDlg)
_structDataPreviewDlg->show();
}
void DiagramCavas::removePanel(PowerEntity* pEntity)
{
QMap<QString,QPair<DrawingPanel*,QMdiSubWindow*>>::Iterator iter;

View File

@ -372,7 +372,7 @@ void DiagramEditorBayDetailSettingDlg::onPreviewClicked()
}
if(!_pPreviewDlg->isVisible()){
_pPreviewDlg->showDlg(nLayout);
QRectF recContainAll = _pModel->generateTempBay();
QRectF recContainAll = _pModel->generateTempBay(_curOperateObj);
if(_curOperateObj){
_curOperateObj->setRecSize(recContainAll);
}

View File

@ -134,10 +134,13 @@ void DiagramEditorBaySettingDlg::onOkClicked()
lst.append(ui->listWidget->item(i)->text());
}
double d = map.value(_curLevel).dVoltage;
DiagramEditorWizardBayInfo info;
info.sName = sName;
info.nType = nType;
info.lstBindObj = lst;
info.dVoltageLevel = d;
_pWizard->onAddBayFinished(info);
}

View File

@ -437,7 +437,7 @@ void DiagramEditorTransDetailSettingDlg::onPreviewNeutralClicked()
int n = ui->tabWidget->currentIndex();
_pPreviewDlg->showDlg(n);
_pModel->clearCurPreview();
_pModel->generateTempTrans(n);
_pModel->generateTempTrans(n,_curOperateObj);
}
else
_pPreviewDlg->hide();

View File

@ -128,6 +128,7 @@ void DiagramEditorWizard::generateBayStruct()
auto pBus = new DiagramEditorBusBlock(this);
pBus->setId(QUuid::createUuid());
pBus->setBusPro(sVoltage+"母线"+sDivPre,1,iter->dVoltage,0,i+1);
pBus->setVoltage(iter->dVoltage);
pContainer->insertBlock(1,pBus);
_mapSturctContainer[iter.key()].insert(i,pContainer);
@ -152,11 +153,13 @@ void DiagramEditorWizard::generateBayStruct()
auto pBus1 = new DiagramEditorBusBlock(this);
pBus1->setId(QUuid::createUuid());
pBus1->setBusPro(sVoltage+"Ⅰ母"+sDivPre,1,iter->dVoltage,1,i+1);
pBus1->setVoltage(iter->dVoltage);
pContainer->insertBlock(1,pBus1);
auto pBus2 = new DiagramEditorBusBlock(this);
pBus2->setId(QUuid::createUuid());
pBus2->setBusPro(sVoltage+"Ⅱ母"+sDivPre,1,iter->dVoltage,2,i+1);
pBus2->setVoltage(iter->dVoltage);
pContainer->insertBlock(2,pBus2);
_mapSturctContainer[iter.key()].insert(i,pContainer);
@ -172,6 +175,7 @@ void DiagramEditorWizard::generateBayStruct()
auto pBus1 = new DiagramEditorBusBlock(this);
pBus1->setId(QUuid::createUuid());
pBus1->setBusPro(sVoltage+"Ⅰ母"+sDivPre1,1,iter->dVoltage,1,i+1);
pBus1->setVoltage(iter->dVoltage);
pContainer->insertBlock(1,pBus1);
if(i < nDivide2){
@ -185,6 +189,7 @@ void DiagramEditorWizard::generateBayStruct()
auto pBus2 = new DiagramEditorBusBlock(this);
pBus2->setId(QUuid::createUuid());
pBus2->setBusPro(sVoltage+"Ⅱ母"+sDivPre2,1,iter->dVoltage,2,i+1);
pBus2->setVoltage(iter->dVoltage);
pContainer->insertBlock(2,pBus2);
}
@ -199,6 +204,7 @@ void DiagramEditorWizard::generateBayStruct()
auto pBus2 = new DiagramEditorBusBlock(this);
pBus2->setId(QUuid::createUuid());
pBus2->setBusPro(sVoltage+"Ⅱ母"+sDivPre2,1,iter->dVoltage,2,i+1);
pBus2->setVoltage(iter->dVoltage);
pContainer->insertBlock(2,pBus2);
if(i < nDivide1){
@ -212,6 +218,7 @@ void DiagramEditorWizard::generateBayStruct()
auto pBus1 = new DiagramEditorBusBlock(this);
pBus1->setId(QUuid::createUuid());
pBus1->setBusPro(sVoltage+"Ⅰ母"+sDivPre1,1,iter->dVoltage,1,i+1);
pBus1->setVoltage(iter->dVoltage);
pContainer->insertBlock(1,pBus1);
}
@ -242,8 +249,13 @@ void DiagramEditorWizard::flushTransPage()
QString sOpposite = con.getOpposite(pItem->getName()).sName;
QString sPos;
if(con.nPara == 0){
if(con.nPara == 0){ //变压器电压等级决定于所连的高压侧
sPos = "高压侧";
auto pBlock = getBlockByName_all(sOpposite);
if(pBlock){
double dVol = pBlock->getVoltage();
pItem->setVoltage(dVol);
}
}
else if(con.nPara == 1){
sPos = "中压侧";
@ -404,6 +416,7 @@ void DiagramEditorWizard::setPara(DiagramEditorProjectInfo info)
pBlock->setRecSize(blockInfo.recSize);
pBlock->setSeceneDelta(blockInfo.sceneDelta);
pBlock->setEditState(blockInfo.bEditState);
pBlock->setVoltage(blockInfo.fVoltage);
pContainer->insertBlock(ite.key(),pBlock);
}
}
@ -713,6 +726,7 @@ void DiagramEditorWizard::onAddBayFinished(DiagramEditorWizardBayInfo info)
pBlock->setName(info.sName);
pBlock->setType(2);
pBlock->setBayType(info.nType);
pBlock->setVoltage(info.dVoltageLevel);
for(auto& sName:info.lstBindObj){
QUuid uid = addConnection(pBlock->getName(),sName,2,1);
pBlock->addConnect(uid);

View File

@ -135,17 +135,17 @@ void DiagramEditorModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem,Model
}
}
QRectF DiagramEditorModel::generateTempBay()
QRectF DiagramEditorModel::generateTempBay(DiagramEditorBayBlock* p)
{
QRectF itemsRect;
generateItemByModel(_pCurBayRoute);
generateItemByModel(_pCurBayRoute,p);
if(_pCurPreviewScene)
itemsRect = _pCurPreviewScene->itemsBoundingRect();
return itemsRect;
}
GraphicsBaseModelItem* DiagramEditorModel::generateComponent(QUuid uid,QString sName,int nCategory,int nType,QPointF pos,int nRotate,int mode,QString sBay)
GraphicsBaseModelItem* DiagramEditorModel::generateComponent(QUuid uid,QString sName,int nCategory,int nType,QPointF pos,int nRotate,int mode,DiagramEditorBaseBlock* pBlock)
{
GraphicsBaseModelItem* pItem = nullptr;
int componentType = -1; //对应的componentType
@ -299,6 +299,14 @@ GraphicsBaseModelItem* DiagramEditorModel::generateComponent(QUuid uid,QString s
if(pEntityData)
pItem->setEntity(pEntityData);
DiagramEditorItemProperty* pData = nullptr;
QString sBay;
double dVoltage = 0.0;
if(pBlock){
sBay = pBlock->getName();
dVoltage = pBlock->getVoltage();
}
if(nCategory == 1){
pData = addPreviewData(uid,0,sName,"node",sBay,mode);
pData->setGraphicsType(pItem->getItemType());
@ -309,6 +317,7 @@ GraphicsBaseModelItem* DiagramEditorModel::generateComponent(QUuid uid,QString s
}
if(pData)
{
pData->setVoltageLevel(dVoltage);
pItem->setProperty(pData);
createTopoTerminalsByItem(pItem,typ);
pData->setDataChanged(true); //数据状态改变
@ -320,15 +329,22 @@ GraphicsBaseModelItem* DiagramEditorModel::generateComponent(QUuid uid,QString s
return pItem;
}
ElectricBaseModelLineItem* DiagramEditorModel::generateLine(QUuid uid,QString sName,int mode,QString sBay)
ElectricBaseModelLineItem* DiagramEditorModel::generateLine(QUuid uid,QString sName,int mode,DiagramEditorBaseBlock* pBlock)
{
ElectricBaseModelLineItem* pLine = new ElectricBaseModelLineItem();
pLine->setItemId(uid);
pLine->setItemType(GIT_baseLine);
QString sBay;
double d;
if(pBlock){
sBay = pBlock->getName();
d = pBlock->getVoltage();
}
DiagramEditorItemProperty* pData = addPreviewData(uid,8,sName,DataBase::GetInstance()->ModelType()[4].modelType,sBay,mode);
pData->setGraphicsType(GIT_baseLine);
if(pData)
{
pData->setGraphicsType(GIT_baseLine);
pData->setVoltageLevel(d);
pLine->setProperty(pData);
pData->setDataChanged(true); //数据状态改变
}
@ -349,24 +365,24 @@ void DiagramEditorModel::clearCurPreview()
void DiagramEditorModel::generateTempTrans(int nType,DiagramEditorTransformerBlock* block)
{
if(nType == 0 || nType == 1 || nType == 2){
generateItemByModel(_pCurTransLRoutes.value(nType),1);
generateItemByModel(_pCurTransLRoutes.value(nType),block,1);
}
else if(nType == 3){
TransformerType typ = block->getTransType();
auto pInfo = block->getTranInfo();
int nT = 0;
if(typ == TransformerType::twoWinding){
generateItemByModel(_pCurTransLRoutes.value(0),1,QPoint(100,-25));
generateItemByModel(_pCurTransLRoutes.value(2),1,QPoint(100,25));
generateItemByModel(_pCurTransLRoutes.value(0),block,1,QPoint(100,-25));
generateItemByModel(_pCurTransLRoutes.value(2),block,1,QPoint(100,25));
if(pInfo.mapNeutral.contains(0))
pInfo.mapNeutral[0].delPoint = QPoint(100,-25);
if(pInfo.mapNeutral.contains(2))
pInfo.mapNeutral[2].delPoint = QPoint(100,25);
}
else if(typ == TransformerType::threeWinding){
generateItemByModel(_pCurTransLRoutes.value(0),1,QPoint(100,-25));
generateItemByModel(_pCurTransLRoutes.value(1),1,QPoint(-150,0));
generateItemByModel(_pCurTransLRoutes.value(2),1,QPoint(100,25));
generateItemByModel(_pCurTransLRoutes.value(0),block,1,QPoint(100,-25));
generateItemByModel(_pCurTransLRoutes.value(1),block,1,QPoint(-150,0));
generateItemByModel(_pCurTransLRoutes.value(2),block,1,QPoint(100,25));
if(pInfo.mapNeutral.contains(0))
pInfo.mapNeutral[0].delPoint = QPoint(100,-25);
if(pInfo.mapNeutral.contains(1))
@ -398,24 +414,24 @@ void DiagramEditorModel::connectTransToNeutral(DiagramEditorTransformerBlock* bl
else if(typ == TransformerType::threeWinding){
nT = 16;
}
generateComponent(uid,sName,0,nT,QPoint(0,0),0,0);
generateComponent(uid,sName,0,nT,QPoint(0,0),0,0,block);
auto pTransItem = _tempItem.value(uid);
if(pTransItem){
if(typ == TransformerType::twoWinding){
linkTransItem(pTransItem,_pCurTransLRoutes.value(0));
linkTransItem(pTransItem,_pCurTransLRoutes.value(2));
linkTransItem(pTransItem,_pCurTransLRoutes.value(0),block);
linkTransItem(pTransItem,_pCurTransLRoutes.value(2),block);
}
else if(typ == TransformerType::threeWinding){
linkTransItem(pTransItem,_pCurTransLRoutes.value(0));
linkTransItem(pTransItem,_pCurTransLRoutes.value(1));
linkTransItem(pTransItem,_pCurTransLRoutes.value(2));
linkTransItem(pTransItem,_pCurTransLRoutes.value(0),block);
linkTransItem(pTransItem,_pCurTransLRoutes.value(1),block);
linkTransItem(pTransItem,_pCurTransLRoutes.value(2),block);
}
}
}
}
void DiagramEditorModel::linkTransItem(GraphicsBaseModelItem* pTrans,QStandardItemModel* pModel)
void DiagramEditorModel::linkTransItem(GraphicsBaseModelItem* pTrans,QStandardItemModel* pModel,DiagramEditorTransformerBlock* pBlock)
{
QUuid uid1 = pTrans->itemId();
int rowCount = pModel->rowCount();
@ -444,7 +460,7 @@ void DiagramEditorModel::linkTransItem(GraphicsBaseModelItem* pTrans,QStandardIt
auto pLineData = TopologyManager::instance().ifConnection(uid1.toString(),uid2.toString()); //判断两个item是否有连接
if(pLineData != nullptr){
if(!_tempItem.contains(QUuid(pLineData->id()))){ //connectdata已存在item未绘制
auto pLine = generateLine(QUuid(pLineData->id()),strCable,0); //重新绘制
auto pLine = generateLine(QUuid(pLineData->id()),strCable,0,pBlock); //重新绘制
if(pLine)
establishConnection(pItem,pTrans,pLine,ModelFunctionType::BlockEditorModel,1,nPos);
}
@ -452,7 +468,7 @@ void DiagramEditorModel::linkTransItem(GraphicsBaseModelItem* pTrans,QStandardIt
}
}
else{ //connectdata不存在新建
auto pLine = generateLine(QUuid::createUuid(),strCable,0);
auto pLine = generateLine(QUuid::createUuid(),strCable,0,pBlock);
if(pLine)
establishConnection(pItem,pTrans,pLine,ModelFunctionType::BlockEditorModel,1,nPos);
}
@ -474,7 +490,8 @@ void DiagramEditorModel::generatePreview()
for(auto item:lst){
if(item->getType() == EditorItemType::bus){ //首次循环生成母线
auto p = item->getBlockData(); //获取blockitem对应的data
if(p){
DiagramEditorBusBlock* pBus = dynamic_cast<DiagramEditorBusBlock*>(p.data());
if(pBus){
QUuid uid = p->getId();
QString name = p->getName();
auto pContainer = _pWizard->getContainerByBlock_all(name); //获取block所在的container
@ -497,11 +514,11 @@ void DiagramEditorModel::generatePreview()
QPointF pos = item->scenePos();
if(_previewItem.contains(uid))
continue;
auto pItem = generateComponent(uid,name,0,1,pos,0,1);
auto pItem = generateComponent(uid,name,0,1,pos,0,1,pBus);
if(nMaxLen > rec.width())
rec.setWidth(nMaxLen);
pItem->setBoundingRect(rec);
p->setRecSize(rec);
pBus->setRecSize(rec);
}
}
else if(item->getType() == EditorItemType::bay){ //第二次生成间隔、变压器
@ -538,7 +555,7 @@ void DiagramEditorModel::generatePreview()
nType = 15;
else
nType = 16;
auto pItem = generateComponent(uid,name,0,nType,pos,0,1);
auto pItem = generateComponent(uid,name,0,nType,pos,0,1,pTrans);
auto pro = pItem->getProperty();
QRectF rect = item->boundingRect();
@ -984,7 +1001,7 @@ QStandardItem* DiagramEditorModel::getNameItem(const QString& sName,int nFrom)
return nullptr;
}
void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,int nFrom,QPoint delta)
void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,DiagramEditorBaseBlock* pBlock,int nFrom,QPoint delta)
{
int rowCount = pModel->rowCount();
for(int i = 0;i < rowCount;++i){
@ -1010,7 +1027,7 @@ void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,int nFro
pos += delta;
QUuid uid = pItem->data(Qt::UserRole+3).toUuid();
if(!_tempItem.contains(uid))
generateComponent(uid,name,nCate,nType,pos,nRotate,0);
generateComponent(uid,name,nCate,nType,pos,nRotate,0,pBlock);
}
}
@ -1030,7 +1047,7 @@ void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,int nFro
auto pLineData = TopologyManager::instance().ifConnection(uid1.toString(),uid2.toString(),ModelFunctionType::BlockEditorModel); //判断两个item是否有连接
if(pLineData != nullptr){
if(!_tempItem.contains(QUuid(pLineData->id()))){ //connectdata已存在item未绘制
auto pLine = generateLine(QUuid(pLineData->id()),strCable,0); //重新绘制
auto pLine = generateLine(QUuid(pLineData->id()),strCable,0,pBlock); //重新绘制
if(pLine)
establishConnection(p1,p2,pLine,ModelFunctionType::BlockEditorModel);
}
@ -1038,7 +1055,7 @@ void DiagramEditorModel::generateItemByModel(QStandardItemModel* pModel,int nFro
}
}
else{ //connectdata不存在新建
auto pLine = generateLine(QUuid::createUuid(),strCable,0);
auto pLine = generateLine(QUuid::createUuid(),strCable,0,pBlock);
if(pLine)
establishConnection(p1,p2,pLine,ModelFunctionType::BlockEditorModel);
}
@ -1060,7 +1077,7 @@ QList<DiagramEditorComponentInfo> DiagramEditorModel::generateItemByInfo(QMap<QS
auto info = mapCompo.value(compo.sName);
if(_previewItem.contains(info.uid))
continue;
generateComponent(info.uid,info.sName,info.nCategory,info.nType,info.deltaPos+delta,info.nRotate,1,pParent->getName());
generateComponent(info.uid,info.sName,info.nCategory,info.nType,info.deltaPos+delta,info.nRotate,1,pParent);
if(!info.sBindObj.isEmpty() && info.sBindObj != QString::fromWCharArray(L"")){ //非空且不是无
if(!lstBind.contains(info))
lstBind.append(info);
@ -1085,7 +1102,7 @@ QList<DiagramEditorComponentInfo> DiagramEditorModel::generateItemByInfo(QMap<QS
auto info = mapCompo.value(compo.sName);
if(_previewItem.contains(info.uid))
continue;
generateComponent(info.uid,info.sName,info.nCategory,info.nType,info.deltaPos+delta,info.nRotate,1,pParent->getName());
generateComponent(info.uid,info.sName,info.nCategory,info.nType,info.deltaPos+delta,info.nRotate,1,pParent);
if(!info.sBindObj.isEmpty() && info.sBindObj != QString::fromWCharArray(L"")){ //非空且不是无
if(!lstBind.contains(info))
lstBind.append(info);
@ -1096,7 +1113,7 @@ QList<DiagramEditorComponentInfo> DiagramEditorModel::generateItemByInfo(QMap<QS
auto info = mapCompo.value(compo.sName);
if(_previewItem.contains(info.uid))
continue;
generateComponent(info.uid,info.sName,info.nCategory,info.nType,info.deltaPos+delta,info.nRotate,1,pParent->getName());
generateComponent(info.uid,info.sName,info.nCategory,info.nType,info.deltaPos+delta,info.nRotate,1,pParent);
if(!info.sBindObj.isEmpty() && info.sBindObj != QString::fromWCharArray(L"")){ //非空且不是无
if(!lstBind.contains(info))
lstBind.append(info);
@ -1140,7 +1157,7 @@ QMultiMap<int,QUuid> DiagramEditorModel::generateOutConnection(QList<DiagramEdit
if(pLineData != nullptr){
lineId = QUuid(pLineData->id());
if(!_previewItem.contains(lineId)){ //connectdata已存在item未绘制
auto pLine = generateLine(lineId,strCable,1,pParent->getName()); //重新绘制
auto pLine = generateLine(lineId,strCable,1,pParent); //重新绘制
if(pLine)
establishConnection(pSrc,pTarget,pLine,ModelFunctionType::EditorModel);
}
@ -1149,7 +1166,7 @@ QMultiMap<int,QUuid> DiagramEditorModel::generateOutConnection(QList<DiagramEdit
}
else{ //connectdata不存在新建
lineId = QUuid::createUuid();
auto pLine = generateLine(lineId,strCable,1,pParent->getName());
auto pLine = generateLine(lineId,strCable,1,pParent);
if(pLine)
establishConnection(pSrc,pTarget,pLine,ModelFunctionType::EditorModel);
}
@ -2310,7 +2327,7 @@ void DiagramEditorModel::bulidAndLinkComponent(QList<DiagramEditorComponentInfo>
if(_previewItem.contains(lineId)) //已绘制
continue;
if(!_previewItem.contains(lineId)){ //connectdata已存在item未绘制
auto pLine = generateLine(lineId,strCable,1,pParent->getName()); //重新绘制
auto pLine = generateLine(lineId,strCable,1,pParent); //重新绘制
if(pLine)
establishConnection(p1,p2,pLine,ModelFunctionType::EditorModel);
}
@ -2319,7 +2336,7 @@ void DiagramEditorModel::bulidAndLinkComponent(QList<DiagramEditorComponentInfo>
}
else{ //connectdata不存在新建
lineId = QUuid::createUuid();
auto pLine = generateLine(lineId,strCable,1,pParent->getName());
auto pLine = generateLine(lineId,strCable,1,pParent);
if(pLine)
establishConnection(p1,p2,pLine,ModelFunctionType::EditorModel);
}

View File

@ -886,6 +886,10 @@ void FixedPortsModel::deleteNodeItem(GraphicsProjectModelItem* pItem)
void FixedPortsModel::saveNode(int nPageId)
{
QList<gridInfo> lstGrid = DataBase::GetInstance()->getAllGrid();
QList<zoneInfo> lstZone = DataBase::GetInstance()->getAllZone();
QList<stationInfo> lstStation = DataBase::GetInstance()->getAllStation();
for(auto& bay:_bayItem)
{
AbstractProperty* pro = bay->getProperty(); //间隔
@ -951,9 +955,9 @@ void FixedPortsModel::saveNode(int nPageId)
if(pVariable)
{
modelDataInfo& dataInfo = pVariable->getPropertyValue();
QString tempTag = pData->tag()+"_"+_pageName; //tag后加工程名使得全局唯一
if(exist) //已存在更新
{
QString tempTag = pData->tag()+"_"+_pageName; //tag后加工程名使得全局唯一
DataBase::GetInstance()->updateComponent(pData->uuid(),tempTag,pData->name(),pData->context());
for(auto &val:dataInfo.groupInfo)
{
@ -971,7 +975,6 @@ void FixedPortsModel::saveNode(int nPageId)
}
else
{
QString tempTag = pData->tag()+"_"+_pageName; //tag后加工程名使得全局唯一
QString tempPath = pData->path()+"_"+_pageName;
DataBase::GetInstance()->insertComponent(pData->uuid(),pData->modelName(),tempPath,tempTag,pData->name(),pData->description(),pData->grid(),pData->zone(),pData->station(),pData->type(),true,pData->state(),pData->status(),pData->connectedBus(),pData->label(),pData->context(),1);
for(auto &val:dataInfo.groupInfo)
@ -989,6 +992,48 @@ void FixedPortsModel::saveNode(int nPageId)
}
}
//层级关系与连接参数
for(auto &val:dataInfo.groupInfo)
{
if(val.groupName == "component" || val.groupName == "bay")
continue;
if(val.mapInfo.contains(pData->uuid())){
auto mapPro = val.mapInfo[pData->uuid()];
for(auto& pro:mapPro)
{
QString sCode;
ExtraProperty extraPro;
extraPro.name = pro.name;
extraPro.tag = pro.tagName;
for(auto& gridInfo:lstGrid){
if(pData->grid() == gridInfo.tagname){
extraPro.grid_tag = gridInfo.tagname;
extraPro.grid_name = gridInfo.name;
break;
}
}
for(auto& zoneInfo:lstZone){
if(pData->zone() == zoneInfo.tagname){
extraPro.zone_tag = zoneInfo.tagname;
extraPro.zone_name = zoneInfo.name;
break;
}
}
for(auto& stationInfo:lstStation){
if(pData->station() == stationInfo.tagname){
extraPro.station_tag = stationInfo.tagname;
extraPro.station_name = stationInfo.name;
break;
}
}
}
}
}
QMap<QString,MeasurementInfo> mapMeasure = pData->getMeasurement(); //量测
QList<MeasurementInfo> lstDataBase = DataBase::GetInstance()->getMeasurement(pData->uuid()); //数据库中现有量测
@ -1751,8 +1796,10 @@ void FixedPortsModel::onWizardFinished(QMap<QUuid,GraphicsBaseModelItem*> mapIte
DiagramEditorBusBlock* pBus = dynamic_cast<DiagramEditorBusBlock*>(p.data());
if(pBus){
QString sBus = pBus->getName();
if(sBus == pPro->name())
if(sBus == pPro->name()){
pPro->setVoltageLevel(pBus->getVoltage()); //设置本体电压层级
pPro->setSubList(pBus->getSubList()); //将子列表转移到item
}
}
}
}
@ -1764,8 +1811,10 @@ void FixedPortsModel::onWizardFinished(QMap<QUuid,GraphicsBaseModelItem*> mapIte
DiagramEditorTransformerBlock* pTrans = dynamic_cast<DiagramEditorTransformerBlock*>(p.data());
if(pTrans){
QString sTrans = pTrans->getName();
if(sTrans == pPro->name())
if(sTrans == pPro->name()){
pPro->setVoltageLevel(pTrans->getVoltage()); //设置本体电压
pPro->setSubList(pTrans->getSubList()); //将子列表转移到item
}
}
}
}
@ -1807,7 +1856,39 @@ void FixedPortsModel::onWizardFinished(QMap<QUuid,GraphicsBaseModelItem*> mapIte
//**************间隔*************
for(auto item:mapBlock){
auto p = item->getBlockData(); //获取blockitem对应的data
if(p->getType() == 2){
if(p->getType() == 1){ //母线
DiagramEditorBusBlock* pBus = dynamic_cast<DiagramEditorBusBlock*>(p.data());
if(pBus){
QString sBus = pBus->getName();
QUuid busId;
for(auto pItem:_baseItem){
BaseModelProperty* pPro = BasePropertyManager::instance().findBaseEntityData(pItem->itemId());
if(pPro){
if(pPro->name() == sBus){
busId = pPro->uuid();
}
}
}
QRectF rec;
ElectricBayItem* pNew = new ElectricBayItem(rec);
pNew->setItemType(GIT_bay);
pNew->setText(sBus);
QUuid bayId = pBus->getId();
BayProperty* pBayData = addBayData(bayId,ModelFunctionType::BaseModel);
pNew->setProperty(pBayData);
pBayData->setName(sBus);
pBayData->setTag(sBus);
pBayData->setType("母线间隔");
//pBayData->setSubList(pBus->getSubList());
pBayData->getLstComponent().append(busId);
addBayItem(bayId,pNew,ModelFunctionType::BaseModel);
//_scene->addItem(pNew);
}
}
else if(p->getType() == 2){ //普通间隔
DiagramEditorBayBlock* pBay = dynamic_cast<DiagramEditorBayBlock*>(p.data());
if(pBay){
QString sBay = pBay->getName();
@ -1888,6 +1969,73 @@ void FixedPortsModel::onWizardFinished(QMap<QUuid,GraphicsBaseModelItem*> mapIte
_scene->addItem(pNew);
}
}
else if(p->getType() == 3){ //变压器本体&中心点间隔
DiagramEditorTransformerBlock* pTrans = dynamic_cast<DiagramEditorTransformerBlock*>(p.data());
if(pTrans){
QString sTrans = pTrans->getName();
auto transInfo = pTrans->getTranInfo();
auto mapNeutral = transInfo.mapNeutral;
auto mapCompo = transInfo.mapComponent;
QList<DiagramEditorComponentInfo> lstInfo;
for(auto& neutral:mapNeutral){
for(auto& route:neutral.mapRoute){ //获取路线中使用的设备
for(auto& compo:route.lstCompo){
auto info = mapCompo.value(compo.sName);
bool exist = false;
for(auto& inf:lstInfo){
if(inf == info){
exist = true;
break;
}
}
if(!exist){
lstInfo.append(info);
}
}
}
}
QList<GraphicsBaseItem*> lst;
for(auto &inf:lstInfo){ //添加附属设备
if(_baseItem.contains(inf.uid))
lst.append(_baseItem.value(inf.uid));
}
for(auto pItem:_baseItem){ //添加本体
BaseModelProperty* pPro = BasePropertyManager::instance().findBaseEntityData(pItem->itemId());
if(pPro){
if(pPro->name() == sTrans){
lst.append(pItem);
break;
}
}
}
QRectF rec = calculateItemsBoundingRect(lst);
ElectricBayItem* pNew = new ElectricBayItem(rec);
pNew->setItemType(GIT_bay);
pNew->setText(sTrans);
QString sType;
QUuid bayId = pTrans->getId();
BayProperty* pBayData = addBayData(bayId,ModelFunctionType::BaseModel);
pNew->setProperty(pBayData);
pBayData->setName(sTrans);
pBayData->setTag(sTrans);
pBayData->setType(sType);
pBayData->setSubList(pTrans->getSubList());
for(auto &info:lstInfo){
pBayData->getLstComponent().append(info.uid);
}
addBayItem(bayId,pNew,ModelFunctionType::BaseModel);
_scene->addItem(pNew);
}
}
}
}

View File

@ -0,0 +1,68 @@
// extraPropertyManager.cpp
#include "instance/extraPropertyManager.h"
#include "dataBase.h"
#include <QDebug>
ExtraPropertyManager::ExtraPropertyManager(QObject* parent) : QObject(parent) {
}
bool ExtraPropertyManager::loadAll() {
m_props.clear();
int count = 0;
QList<ExtraProperty> lstPro = DataBase::GetInstance()->getAllExtraProperty();
for(auto& pro:lstPro){
m_props[pro.code] = pro;
count++;
}
qInfo() << "加载了" << count << "个属性";
return true;
}
void ExtraPropertyManager::initial()
{
loadAll();
}
QVector<ExtraProperty> ExtraPropertyManager::getByFilter(const QVariantMap& filter,const QString& filterType) const {
QVector<ExtraProperty> result;
for (const ExtraProperty& prop : m_props) {
if (prop.matches(filter,filterType)) {
result.append(prop);
}
}
return result;
}
ExtraProperty ExtraPropertyManager::getByCode(const QString& code) const {
return m_props.value(code);
}
int ExtraPropertyManager::add(const ExtraProperty& prop) {
if (prop.code.isEmpty()) {
qWarning() << "属性编码不能为空";
return -1;
}
if (m_props.contains(prop.code)) {
qWarning() << "属性编码已存在:" << prop.code;
return -1;
}
bool res = DataBase::GetInstance()->insertExtraProperty(prop);
return res;
}
QStringList ExtraPropertyManager::getGrids() const {
QSet<QString> grids;
for (const ExtraProperty& prop : m_props) {
if (!prop.grid_tag.isEmpty()) {
grids.insert(prop.grid_tag);
}
}
return QStringList(grids.begin(), grids.end());
}

View File

@ -65,7 +65,7 @@ void MonitorPanel::createToolBar()
_toolBar = new QToolBar(this);
_toolBar->setStyleSheet("QToolBar { background-color: palette(window); border: none; }");
_menuFile = new QMenu("文件", this);
_menuFile = new QMenu("系统", this);
// 保存操作
QAction *saveAction = _menuFile->addAction("保存");

View File

@ -0,0 +1,205 @@
#include "structDataPreviewDlg.h"
#include "ui_structDataPreviewDlg.h"
#include <QStandardItemModel>
#include <QMenuBar>
#include "titleBar.h"
#include "instance/extraPropertyManager.h"
StructDataPreviewDlg::StructDataPreviewDlg(QWidget *parent)
: QDialog(parent)
, ui(new Ui::structDataPreviewDlg)
,_pExtraProManager(nullptr)
{
ui->setupUi(this);
this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());
initial();
}
StructDataPreviewDlg::~StructDataPreviewDlg()
{
delete ui;
}
void StructDataPreviewDlg::initial()
{
// 创建标题栏
m_titleBar = new TitleBar(this);
m_titleBar->setTitle("结构数据展示");
ui->mainLayout->insertWidget(0,m_titleBar);
QMenuBar *menuBar = new QMenuBar(this);
QMenu *fileMenu = menuBar->addMenu("文件");
QAction *saveAction = fileMenu->addAction("保存");
menuBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
menuBar->setFixedHeight(33);
QString style = R"(
QMenuBar {
background: #f1f5f9;
border-bottom: 1px solid #cbd5e1;
color: #334155;
font-weight: 500;
padding: 2px 0;
}
QMenuBar::item {
padding: 6px 12px;
border-radius: 3px;
margin: 0 1px;
}
QMenuBar::item:hover {
background: #e2e8f0;
border: 1px solid #cbd5e1;
}
QMenuBar::item:pressed {
background: #cbd5e0;
}
QMenu {
background: #ffffff;
border: 1px solid #cbd5e1;
border-radius: 4px;
color: #475569;
padding: 4px 0;
}
QMenu::item {
padding: 2px 20px 2px 6px;
margin: 1px 2px;
min-height: 20px;
}
QMenu::item:selected {
background: #3b82f6;
color: white;
border-radius: 2px;
}
QMenu::separator {
height: 1px;
background: #e2e8f0;
margin: 3px 8px;
}
)";
setStyleSheet(style);
ui->mainLayout->insertWidget(1,menuBar);
ui->mainLayout->setStretchFactor(menuBar, 0);
ui->splitter_2->setStretchFactor(0,1);
ui->splitter_2->setStretchFactor(1,4);
ui->splitter->setStretchFactor(0,5);
ui->splitter->setStretchFactor(1,1);
connect(saveAction,&QAction::triggered,this,&StructDataPreviewDlg::onSaveClicked);
connect(m_titleBar, &TitleBar::maximizeClicked, this, &StructDataPreviewDlg::toggleMaximize);
connect(m_titleBar, &TitleBar::closeClicked, this, &StructDataPreviewDlg::onExitClicked);
}
void StructDataPreviewDlg::clearItems()
{
if(_treeModel){
QStandardItem *root = _treeModel->invisibleRootItem(); //先清空model
int rowCount = root->rowCount();
if (rowCount > 0) {
_treeModel->removeRows(0, rowCount);
}
}
}
void StructDataPreviewDlg::onExitClicked()
{
hide();
}
void StructDataPreviewDlg::onSaveClicked()
{
}
void StructDataPreviewDlg::onGridClicked()
{
}
void StructDataPreviewDlg::onZoneClicked()
{
}
void StructDataPreviewDlg::onStationClicked()
{
}
void StructDataPreviewDlg::onBayClicked()
{
}
void StructDataPreviewDlg::onDeviceClicked()
{
}
void StructDataPreviewDlg::onPropertyClicked()
{
}
void StructDataPreviewDlg::showEvent(QShowEvent *event)
{
QDialog::showEvent(event);
if (m_titleBar) {
m_titleBar->updateMaximizeButton();
}
}
void StructDataPreviewDlg::showMaximized()
{
if (!isMaximized()) {
m_normalGeometry = geometry(); // 保存当前位置和大小
}
QDialog::showMaximized();
}
void StructDataPreviewDlg::showNormal()
{
QDialog::showNormal();
}
void StructDataPreviewDlg::showDlg()
{
if(_pExtraProManager)
{
QMap<QString, ExtraProperty> mapPro = _pExtraProManager->geAlltProperty();
}
}
void StructDataPreviewDlg::resizeEvent(QResizeEvent *event)
{
QDialog::resizeEvent(event);
if (m_titleBar) {
m_titleBar->updateMaximizeButton();
}
}
void StructDataPreviewDlg::toggleMaximize()
{
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
// 更新标题栏按钮
if (m_titleBar) {
m_titleBar->updateMaximizeButton();
}
}

View File

@ -0,0 +1,113 @@
#include "titleBar.h"
#include <QStyle>
#include <QScreen>
#include <QGuiApplication>
TitleBar::TitleBar(QWidget *parent)
: QWidget(parent)
, m_parentWindow(parent)
{
setupUI();
setFixedHeight(35); // 稍微矮一点
setAttribute(Qt::WA_StyledBackground, true); // 启用样式背景
setAttribute(Qt::WA_NoSystemBackground, false);
// 确保有自己的调色板
setAutoFillBackground(true);
// 使用更具体的样式表
QString style = R"(
QWidget {
background: #2c5282;
}
QLabel {
color: white;
font-size: 12px;
background: transparent;
}
QPushButton {
background: transparent;
border: none;
color: white;
min-width: 30px;
min-height: 30px;
}
)";
setStyleSheet(style);
}
void TitleBar::setupUI()
{
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setContentsMargins(4, 0, 0, 0);
layout->setSpacing(0);
// 标题
m_titleLabel = new QLabel("窗口标题");
m_titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
// 最大化/还原按钮
m_maximizeButton = new QPushButton(tr("🗖")); // 最大化图标
m_maximizeButton->setObjectName("maximizeButton");
m_maximizeButton->setToolTip("最大化");
// 关闭按钮
m_closeButton = new QPushButton("×");
m_closeButton->setObjectName("closeButton");
m_closeButton->setToolTip("关闭");
layout->addWidget(m_titleLabel);
layout->addWidget(m_maximizeButton);
layout->addWidget(m_closeButton);
// 连接信号
connect(m_maximizeButton, &QPushButton::clicked, this, &TitleBar::maximizeClicked);
connect(m_closeButton, &QPushButton::clicked, this, &TitleBar::closeClicked);
}
void TitleBar::setTitle(const QString &title)
{
m_titleLabel->setText(title);
}
void TitleBar::updateMaximizeButton()
{
if (m_parentWindow) {
m_isMaximized = m_parentWindow->isMaximized();
if (m_isMaximized) {
m_maximizeButton->setText(tr("🗗")); // 还原图标
m_maximizeButton->setToolTip("还原");
} else {
m_maximizeButton->setText(tr("🗖")); // 最大化图标
m_maximizeButton->setToolTip("最大化");
}
}
}
void TitleBar::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_dragStartPosition = event->globalPosition().toPoint() - m_parentWindow->frameGeometry().topLeft();
event->accept();
}
}
void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
m_parentWindow->move(event->globalPosition().toPoint() - m_dragStartPosition);
event->accept();
}
}
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
emit maximizeClicked();
}
}

View File

@ -0,0 +1,472 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>structDataPreviewDlg</class>
<widget class="QDialog" name="structDataPreviewDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1032</width>
<height>667</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="mainLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_2" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<widget class="QWidget" name="widget_6" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_7" native="true">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QWidget {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #f8fafc,
stop:1 #f1f5f9);
}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(6, 6, 6);</string>
</property>
<property name="text">
<string>层级结构</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>601</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_8" native="true">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
background-color: #6b8cb8; /* 稍亮的灰蓝 */
color: rgb(255, 255, 255);
}
QPushButton:hover {
background-color: #5a79a1; /* 悬停到主色 */
}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btn_gird">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>网</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_zone">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>区</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_station">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>站</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_bay">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>间</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_device">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>设</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>组</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_property">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>属</string>
</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>
</layout>
</widget>
</item>
<item>
<widget class="QTreeView" name="tree_level"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="widget_3" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<widget class="QTableView" name="tableView"/>
<widget class="QWidget" name="widget_4" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_5" native="true">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QWidget {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #f8fafc,
stop:1 #f1f5f9);
}</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(6, 6, 6);</string>
</property>
<property name="text">
<string>状态信息</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>677</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -74,6 +74,12 @@ public:
bool ifMeasureExist(QString name,QUuid componentId);
QList<MeasurementInfo> getMeasurement(QUuid componentId);
/*********************************************************************************/
bool insertExtraProperty(ExtraProperty); //属性层级与连接信息
bool updateExtraProperty(ExtraProperty);
bool deleteExtraProperty(QString code);
bool ifExtraPropertyExist(QString code);
QList<ExtraProperty> getAllExtraProperty();
/*********************************************************************************/
bool deleteComponentById(int id);
QJsonObject QstringToJson(QString jsonString);

View File

@ -1558,6 +1558,155 @@ QList<MeasurementInfo> DataBase::getMeasurement(QUuid componentId)
}
}
/*****************************************************************************/
bool DataBase::insertExtraProperty(ExtraProperty pro)
{
QString strSQL = "INSERT INTO properties_setting(code, tag, name, grid_name, zone_name, station_name, current_level, bay_name, component_name, group_name, grid_tag, zone_tag, station_tag, page_tag, bay_tag, component_uuid, group_tag, source_type, source_config, connect_para) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
QJsonDocument configDoc(QJsonObject::fromVariantMap(pro.sourceConfig));
QString strConfig = configDoc.toJson(QJsonDocument::Compact);
QVariantList params;
params.append(pro.code);
params.append(pro.tag);
params.append(pro.name);
params.append(pro.grid_name);
params.append(pro.zone_name);
params.append(pro.station_name);
params.append(pro.currentLevel);
params.append(pro.bay_name);
params.append(pro.component_name);
params.append(pro.group_name);
params.append(pro.grid_tag);
params.append(pro.zone_tag);
params.append(pro.station_tag);
params.append(pro.page_tag);
params.append(pro.bay_tag);
params.append(pro.component_uuid.toString());
params.append(pro.group_tag);
params.append(pro.sourceType);
params.append(strConfig);
params.append(pro.connect_para);
try
{
executeSQL(strSQL,false,params);
return true;
}
catch (const std::exception& e)
{
LOG_ERROR("DB", QString("Insert properties_setting fail"));
return false;
}
}
bool DataBase::updateExtraProperty(ExtraProperty pro)
{
QJsonDocument configDoc(QJsonObject::fromVariantMap(pro.sourceConfig));
QString strConfig = configDoc.toJson(QJsonDocument::Compact);
QString strSQL = "UPDATE properties_setting SET source_config = ?,connect_para = ? WHERE code = ?";
QVariantList params;
params.append(strConfig);
params.append(pro.connect_para);
params.append(pro.code);
try
{
executeSQL(strSQL,false,params);
return true;
}
catch (const std::exception& e)
{
LOG_ERROR("DB", QString("Update properties_setting %1 fail").arg(pro.code));
return false;
}
}
bool DataBase::deleteExtraProperty(QString code)
{
QString strSQL = "DELETE FROM properties_setting WHERE code = ?";
QVariantList params;
params.append(code);
try
{
executeSQL(strSQL,false,params);
LOG_INFO("DB", QString("Delete properties_setting %1 success").arg(code));
return true;
}
catch (const std::exception& e)
{
LOG_ERROR("DB", QString("Delete properties_setting %1 failed").arg(code));
return false;
}
}
bool DataBase::ifExtraPropertyExist(QString code)
{
QString strSQL = "SELECT id FROM properties_setting WHERE code = ?";
QVariantList params;
params.append(code);
try
{
QSqlQuery query = executeSQL(strSQL,false,params);
while (query.next())
{
return true;
}
}
catch (const std::exception& e)
{
return false;
}
return false;
}
QList<ExtraProperty> DataBase::getAllExtraProperty()
{
QList<ExtraProperty> lst;
QString strSQL = "SELECT code, tag, name, grid_name, zone_name, station_name, current_level, bay_name, component_name, group_name, grid_tag, zone_tag, station_tag, page_tag, bay_tag, component_uuid, group_tag, source_type, source_config, connect_para FROM properties_setting";
try
{
QSqlQuery query = executeSQL(strSQL);
while (query.next())
{
ExtraProperty info;
info.code = query.value(0).toString();
info.tag = query.value(1).toString();
info.name = query.value(2).toString();
info.grid_name = query.value(3).toString();
info.zone_name = query.value(4).toString();
info.station_name = query.value(5).toString();
info.currentLevel = query.value(6).toString();
info.bay_name = query.value(7).toString();
info.component_name = query.value(8).toString();
info.group_name = query.value(9).toString();
info.grid_tag = query.value(10).toString();
info.zone_tag = query.value(11).toString();
info.station_tag = query.value(12).toString();
info.page_tag = query.value(13).toString();
info.bay_tag = query.value(14).toString();
info.component_uuid = QUuid(query.value(15).toString());
info.group_tag = query.value(16).toString();
info.sourceType = query.value(17).toString();
QString sConfig = query.value(18).toString();
QJsonObject objConfig = QstringToJson(sConfig);
info.sourceConfig = objConfig.toVariantMap();
info.connect_para = query.value(19).toString();
lst.append(info);
}
query.clear();
return lst;
}
catch (const std::exception& e)
{
return lst;
}
}
/*****************************************************************************/
void DataBase::readXML()
{

View File

@ -49,6 +49,7 @@ private slots:
void onAction_destroyGroup();
void onAction_editProject();
void onAction_editBay();
void onAction_previewData();
void onSignal_addItem(QGraphicsItem*);
void onSignal_deleteItem();
void onSignal_loadProject();

View File

@ -189,6 +189,9 @@ void CMainWindow::initializeAction()
QAction* actEditBay = ui->menuProject->addAction(QString::fromWCharArray(L"管理间隔"));
connect(actEditBay,&QAction::triggered,this,&CMainWindow::onAction_editBay);
QAction* actPreviewData = ui->menuProject->addAction(QString::fromWCharArray(L"数据查看"));
connect(actPreviewData,&QAction::triggered,this,&CMainWindow::onAction_previewData);
QAction* actEdit = ui->menuProject->addAction(QString::fromWCharArray(L"编辑工程模"));
connect(actEdit,&QAction::triggered,this,&CMainWindow::onAction_editProject);
@ -275,6 +278,11 @@ void CMainWindow::onAction_editBay()
m_pDiagramCavas->onSignl_openCurrentBay();
}
void CMainWindow::onAction_previewData()
{
m_pDiagramCavas->onSignal_openStructDataPreview();
}
void CMainWindow::onSignal_addItem(QGraphicsItem* item)
{
if(item)

View File

@ -14,7 +14,7 @@
<string>DiagramDesigner</string>
</property>
<property name="styleSheet">
<string notr="true"> QMenuBar {
<string notr="true"> QMenuBar#menubar {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #2c5282, /* 顶部颜色 */
stop:1 #1a365d); /* 底部颜色 */
@ -23,37 +23,37 @@
padding: 4px 0;
}
QMenuBar::item {
QMenuBar#menubar::item {
padding: 8px 16px;
border: 1px solid transparent;
}
QMenuBar::item:hover {
QMenuBar#menubar::item:hover {
background-color: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
}
QMenuBar::item:pressed {
QMenuBar#menubar::item:pressed {
background-color: rgba(255, 255, 255, 0.2);
}
QMenu {
QMenu#menubar {
background-color: white;
border: 1px solid #cbd5e1;
color: #1e293b;
padding: 4px;
}
QMenu::item {
QMenu#menubar::item {
padding: 6px 30px 6px 20px;
border-radius: 2px;
}
QMenu::item:selected {
QMenu#menubar::item:selected {
background-color: #2563eb;
color: white;
}
QMenu::separator {
QMenu#menubar::separator {
height: 1px;
background-color: #e2e8f0;
margin: 4px 8px;