diff --git a/common/core_model/data_transmission.h b/common/core_model/data_transmission.h index c64da6f..6dcaf55 100644 --- a/common/core_model/data_transmission.h +++ b/common/core_model/data_transmission.h @@ -9,6 +9,18 @@ struct HttpRecommandInfo{ //推荐数据服务 QString sInput; //输入的前缀 int nOffset = 0; //正确位置计数 QStringList lstRecommand; //推荐列表 + + QStringList generateCompleteNames() const + { + QStringList result; + for (const QString& str : lstRecommand) { + QString sCompleteName = sInput + str; + if (!result.contains(sCompleteName)) { + result.append(sCompleteName); + } + } + return result; + } }; #endif diff --git a/diagramCavas/CMakeLists.txt b/diagramCavas/CMakeLists.txt index 28ea2ff..a55d12d 100644 --- a/diagramCavas/CMakeLists.txt +++ b/diagramCavas/CMakeLists.txt @@ -5,6 +5,7 @@ set(DIAGRAMCAVAS_HEADER_FILES include/designerScene.h include/designerView.h include/diagramCavas.h + include/diagramCavas_p.h include/baseDrawingPanel.h include/monitorPanel.h include/monitorSideBarDlg.h @@ -149,6 +150,7 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/designerScene.cpp source/designerView.cpp source/diagramCavas.cpp + source/diagramCavas_p.cpp source/baseDrawingPanel.cpp source/monitorPanel.cpp source/monitorSideBarDlg.cpp diff --git a/diagramCavas/include/diagramCavas.h b/diagramCavas/include/diagramCavas.h index 568644d..c9b1ffe 100644 --- a/diagramCavas/include/diagramCavas.h +++ b/diagramCavas/include/diagramCavas.h @@ -7,6 +7,7 @@ #include "common/core_model/topology.h" #include "common/core_model/types.h" #include "common/core_model/diagram.h" +#include "common/core_model/data_transmission.h" #include "common/frontend/monitor_item.h" #include "export.hpp" @@ -14,45 +15,39 @@ QT_BEGIN_NAMESPACE namespace Ui { class diagramCavas; } QT_END_NAMESPACE +class DiagramCavasPrivate; // 前向声明私有实现类 + +// 只声明在公共接口中使用的类型 class DrawingPanel; class PowerEntity; -class GraphicsBaseModelItem; -class EditBaseItem; class MonitorPanel; -class CornerMonitorLauncher; -class LoadMonitorPageDlg; class DiagramConnectSetting; class DataAccessor; struct HttpRecommandInfo; -class StructDataPreviewDlg; class ExtraPropertyManager; -class DataSourceDlg; -class CreateHMIdlg; class PluginManager; class PluginItemFactory; -class QDetailsView; -class PropertyDlg; class DIAGRAM_DESIGNER_PUBLIC DiagramCavas : public QMdiArea { Q_OBJECT - + Q_DECLARE_PRIVATE(DiagramCavas) public: DiagramCavas(QWidget *parent = nullptr); - ~DiagramCavas(); + virtual ~DiagramCavas(); MonitorPanel* getMonitorPanel(QString); - DataAccessor* getDataAccessor() const {return _dataAccessor;} + DataAccessor* getDataAccessor() const; void updateSubPos(); void passRecommmandHttpData(HttpRecommandInfo); //传递推荐列表数据 - DiagramConnectSetting* getConnectSettingDlg() {return _connectSetting;} - ExtraPropertyManager* getExtraPropertyManager() {return _extraPropertyManager;} - QMap getPluginShapeInfo() {return m_pluginInfo;} + DiagramConnectSetting* getConnectSettingDlg(); + ExtraPropertyManager* getExtraPropertyManager(); + QMap getPluginShapeInfo(); public: void initial(); void setCurMode(int nMode); - int getCurMode(){return _curMode;} + int getCurMode(); void showPropertyDlg(); //加载运行时属性栏 void hidePropertyDlg(); @@ -119,37 +114,18 @@ public slots: void updateHMIlstFromDB(); //从数据库更新HMI列表 - QMap> getMapMonitor() {return m_mapMonitorPanel;} + //QMap> getMapMonitor() {return m_mapMonitorPanel;} void onTargetSelected(QObject*); //选中事件(属性显示) protected: void resizeEvent(QResizeEvent* event) override; private: - void removePanel(PowerEntity*); - void calculateLauncherVisible(); + // 将原有私有方法改为公有或保护,因为它们需要被私有类访问 + friend class DiagramCavasPrivate; - bool loadPluginConfig(const QString&); //载入插件配置文件 - bool parsePluginConfig(const QJsonObject& root); //解析插件配置文件 - - void addShortcuts(); //快捷键 -private: - QMap> m_mapMonitorPanel; //监控时panel - int _pageIndex; - QString _curPage; - CornerMonitorLauncher* _cornerButton; //简略菜单呼出按钮 - LoadMonitorPageDlg* _loadMonitorPageDlg; - DiagramConnectSetting* _connectSetting; - DataAccessor* _dataAccessor; - StructDataPreviewDlg* _structDataPreviewDlg; - ExtraPropertyManager* _extraPropertyManager; - CreateHMIdlg* _createHMIDlg; - QDetailsView* _pPropertyPage; //属性页 - PropertyDlg* _pPropertyDlg; //存放属性页dlg - - PluginManager* m_pluginManager; //插件管理类 - PluginItemFactory* m_itemFactory; //插件图元工厂类 - QMap m_pluginInfo; //插件对照信息 - int _curMode = 0; //当前运行模式 0编辑1运行 + // 私有实现指针 + DiagramCavasPrivate* d_ptr; + Q_DISABLE_COPY(DiagramCavas) // 禁止拷贝 }; #endif diff --git a/diagramCavas/include/diagramCavas_p.h b/diagramCavas/include/diagramCavas_p.h new file mode 100644 index 0000000..c8c2708 --- /dev/null +++ b/diagramCavas/include/diagramCavas_p.h @@ -0,0 +1,118 @@ +// diagramcanvas_p.h - 私有头文件,不对外公开 +#ifndef DIAGRAMCANVAS_P_H +#define DIAGRAMCANVAS_P_H + +#include "common/backend/project_model.h" +#include "common/core_model/topology.h" +#include "common/core_model/types.h" +#include "common/core_model/diagram.h" +#include "common/frontend/monitor_item.h" +#include "monitorpanel.h" +#include + +class CornerMonitorLauncher; +class LoadMonitorPageDlg; +class DiagramConnectSetting; +class DataAccessor; +struct HttpRecommandInfo; +class StructDataPreviewDlg; +class ExtraPropertyManager; +class DataSourceDlg; +class CreateHMIdlg; +class PluginManager; +class PluginItemFactory; +class QDetailsView; +class PropertyDlg; + +class DiagramCavasPrivate +{ +public: + DiagramCavasPrivate(DiagramCavas* q); + ~DiagramCavasPrivate(); + + // 原始私有成员 + QMap> m_mapMonitorPanel; + int _pageIndex = 0; + QString _curPage; + CornerMonitorLauncher* _cornerButton = nullptr; + LoadMonitorPageDlg* _loadMonitorPageDlg = nullptr; + DiagramConnectSetting* _connectSetting = nullptr; + DataAccessor* _dataAccessor = nullptr; + StructDataPreviewDlg* _structDataPreviewDlg = nullptr; + ExtraPropertyManager* _extraPropertyManager = nullptr; + CreateHMIdlg* _createHMIDlg = nullptr; + QDetailsView* _pPropertyPage = nullptr; + PropertyDlg* _pPropertyDlg = nullptr; + PluginManager* m_pluginManager = nullptr; + PluginItemFactory* m_itemFactory = nullptr; + QMap m_pluginInfo; + int _curMode = 0; + + // 私有方法 + void initialImpl(); + void removePanel(PowerEntity* p); + void calculateLauncherVisible(); + bool loadPluginConfig(const QString& path); + bool parsePluginConfig(const QJsonObject& root); + void addShortcuts(); + void updateCornerPos(); //更新右上角Button位置 + void showNewSettingDlg(); //显示网络设置对话框 + void showStructDataPreviewDlg(); //显示结构化数据预览 + void processRecommandData(const HttpRecommandInfo&); //处理推荐数据 + void onTargetSelected(QObject*); //对象选中事件(属性) + void onCreateHMI(); //创建HMI + void updateHMIFromDB(); //从数据库中更新HMI信息 + + //显示属性相关 + void showPropertyDlgImpl(); // 显示属性页 + void hidePropertyDlgImpl(); // 隐藏属性页 + void initPropertyPage(); // 初始化属性页面 + void centerPropertyDialogOnScreen(); // 居中属性对话框 + + //添加pannel相关 + void addDrawingPanelImpl(PowerEntity* pItem, DiagramMode mode, const QString& parent); + void addMonitorPanel(PowerEntity* pItem, const QString& parent); + void addEditorPanel(PowerEntity* pItem, const QString& parent); + void connectMonitorPanelSignals(MonitorPanel* panel, FixedPortsModel* model); + void updateCurrentPage(const QString& pageName); + bool hasPanel(const QString& name) const; + MonitorPanel* getPanel(const QString& name) const; + QMdiSubWindow* getSubWindow(const QString& name) const; + + //保存相关 + void savePageImpl(); + bool saveMonitorPanel(MonitorPanel* monitorPanel); + bool saveHMIImages(QMap& imageMap); + bool saveImageReferences(const QList& imageRefs, const QUuid& hmiId); + bool saveCustomImageReferences(const QList& customImageRefs, const QUuid& hmiId); + bool saveOrUpdateHMI(PowerEntity* entity, QJsonObject diagramInfo); + MonitorPanel* getCurrentMonitorPanel() const; + BaseDrawingPanel* getCurrentDrawingPanel() const; + // 批量保存 + bool saveAllPages(); + bool savePage(const QString& pageName); + int saveModifiedPages(); + // 修改状态跟踪 + void markPageModified(const QString& pageName, bool modified = true); + bool isPageModified(const QString& pageName) const; + QList getModifiedPages() const; + + //加载相关 + void loadMonitorImpl(PowerEntity* p); + bool createAndLoadMonitor(PowerEntity* p, const QJsonObject& context); + bool loadExistingMonitor(const QString& name); + QJsonObject loadHMIContext(const QString& hmiName); + void applyPageGeometry(MonitorPanel* panel, QMdiSubWindow* subWindow,const QJsonObject& pageAttr); + void activateAndSelectMonitor(const QString& name); + + // 创建HMI面板相关 + void createHMIClickedImpl(const QString& sHMI, const QString& sStructPage, int modelType); + bool createHMIDiagram(const QString& sHMI, int modelType, QUuid& outId, PowerEntity*& outEntity); + bool loadStructureToPanel(const QString& panelName, const QString& sStructPage); +private: + DiagramCavas* q_ptr; // 指向公共接口的指针 + QSet m_modifiedPages; // 记录修改过的页面 + Q_DECLARE_PUBLIC(DiagramCavas) +}; + +#endif // DIAGRAMCANVAS_P_H diff --git a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h index b3580b7..c0529bf 100644 --- a/diagramCavas/include/graphicsDataModel/fixedPortsModel.h +++ b/diagramCavas/include/graphicsDataModel/fixedPortsModel.h @@ -151,7 +151,6 @@ public: void setPageName(QString s) {_pageName = s;} //设置表名称 QString pageName() const {return _pageName;} void activateModel() {Q_EMIT activatePage(_pageName);} //发送激活信号(点击) - void startHttpRequest(); //开始请求数据(运行时) void setCavas(QPointer p) {_cavas = p;} //设置所属顶层容器 DiagramCavas* getCavas(); int getCurMode(); //获取当前模式 @@ -192,7 +191,6 @@ private: DesignerScene* _scene; BaseDrawingPanel* _widget; //顶层widget HttpInterface* _Interface; - QTimer* _timer; PowerEntity* _pEntity; //拓扑实体 QMap _projectModelName; //该图中所有元件对应的工程模类型(todo:扩展为每张图独立的结构体) uuid,工程模名称 diff --git a/diagramCavas/source/diagramCavas.cpp b/diagramCavas/source/diagramCavas.cpp index 4556c90..e6cde77 100644 --- a/diagramCavas/source/diagramCavas.cpp +++ b/diagramCavas/source/diagramCavas.cpp @@ -1,191 +1,75 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "monitorPanel.h" #include "diagramCavas.h" -#include "dataBase.h" -#include "graphicsItem/graphicsBaseItem.h" -#include "projectModelManager.h" -#include "topologyManager.h" -#include "powerEntity.h" -#include "cornerMonitorLauncher.h" -#include "loadMonitorPageDlg.h" -#include "diagramConnectSetting.h" -#include "diagramCommunication/include/communicationManager.h" -#include "diagramCommunication/include/configManager.h" -#include "instance/dataAccessor.h" -#include "uiCommunicationBus.h" -#include "itemPropertyDlg.h" -#include "monitorConfigDlg.h" -#include "structDataPreviewDlg.h" -#include "extraPropertyManager.h" -#include "createHMIdlg.h" -#include "pluginManager.h" -#include "graphicsItem/pluginItemFactory.h" - -#include "QQuickDetailsViewMananger.h" -#include "propertyType/propertyTypeCustomization_DataSourceType.h" -#include "propertyType/propertyTypeCustomization_ConfigEventData.h" -#include "propertyType/dataSourceType.h" - -#include "basePannelPropertyProxy.h" -#include "QDetailsView.h" -#include "propertyDialog.h" +#include "diagramCavas_p.h" DiagramCavas::DiagramCavas(QWidget *parent) : QMdiArea(parent) - ,_cornerButton(nullptr) - ,_loadMonitorPageDlg(nullptr) - ,_connectSetting(nullptr) - ,_dataAccessor(nullptr) - ,_structDataPreviewDlg(nullptr) - ,_extraPropertyManager(nullptr) - ,_createHMIDlg(nullptr) - ,m_pluginManager(nullptr) - ,m_itemFactory(nullptr) - ,_pPropertyPage(nullptr) - ,_pPropertyDlg(nullptr) + ,d_ptr(new DiagramCavasPrivate(this)) { - _pageIndex = 0; + Q_D(DiagramCavas); } DiagramCavas::~DiagramCavas() { + Q_D(DiagramCavas); + delete d; disconnect(); //断开连接避免动态库释放时信号问题 } MonitorPanel* DiagramCavas::getMonitorPanel(QString sPage) { - if(m_mapMonitorPanel.contains(sPage)) - return m_mapMonitorPanel[sPage].first; + Q_D(DiagramCavas); + if(d->m_mapMonitorPanel.contains(sPage)) + return d->m_mapMonitorPanel[sPage].first; return nullptr; } +DataAccessor* DiagramCavas::getDataAccessor() const +{ + Q_D(const DiagramCavas); + return d->_dataAccessor; +} + void DiagramCavas::updateSubPos() { - if(_cornerButton) - _cornerButton->positionAtCorner(); + Q_D(DiagramCavas); + d->updateCornerPos(); } void DiagramCavas::passRecommmandHttpData(HttpRecommandInfo info) { - if(_structDataPreviewDlg){ //数据预览dlg - QStringList lst; - for(auto &str:info.lstRecommand){ - QString sCompleteName = info.sInput+str; - if(!lst.contains(sCompleteName)) - lst.append(sCompleteName); - } - _structDataPreviewDlg->updateRecommandLst(lst); - } - //=============================================== - QMdiSubWindow* pSub = currentSubWindow(); - if(!pSub) - return; - QWidget* pWindow= pSub->widget(); - BaseDrawingPanel* pPanel = dynamic_cast(pWindow); - if(pPanel) - { - if(pPanel->getMode() == DM_run) - { - auto pMonitor = dynamic_cast(pPanel); - if(pMonitor){ - QStringList lst; - for(auto &str:info.lstRecommand){ - QString sCompleteName = info.sInput+str; - if(!lst.contains(sCompleteName)) - lst.append(sCompleteName); - } - //todo:推荐列表的使用 - } - } - } + Q_D(DiagramCavas); + d->processRecommandData(info); +} + +DiagramConnectSetting* DiagramCavas::getConnectSettingDlg() +{ + Q_D(DiagramCavas); + return d->_connectSetting; +} + +ExtraPropertyManager* DiagramCavas::getExtraPropertyManager() +{ + Q_D(DiagramCavas); + return d->_extraPropertyManager; +} + +QMap DiagramCavas::getPluginShapeInfo() +{ + Q_D(DiagramCavas); + return d->m_pluginInfo; } void DiagramCavas::initial() { - //todo:读取数据并初始化 - QList lst = DataBase::GetInstance()->getAllPage(); - for(auto &info:lst) - { - TopologyManager::instance().createDiagram(QString::number(info.id),info.name); - } - _cornerButton = new CornerMonitorLauncher(this); - _cornerButton->showDlg(); - _loadMonitorPageDlg = new LoadMonitorPageDlg(this); - connect(_cornerButton,&CornerMonitorLauncher::openLoadMonitorDlg,this,[&](){ - if(_loadMonitorPageDlg){ - updateMonitorListFromDB(1); - _loadMonitorPageDlg->show(); - } - }); - connect(_loadMonitorPageDlg,&LoadMonitorPageDlg::monitorSelected,this,&DiagramCavas::onSignal_monitorSelected); - _connectSetting = new DiagramConnectSetting(this); - - // 初始化通信管理器 - CommunicationManager* comm = CommunicationManager::instance(); - comm->initialize(); - - // 加载配置 - ConfigManager* config = ConfigManager::instance(); - config->loadConfig("config.json"); - - _extraPropertyManager = new ExtraPropertyManager(this); - _extraPropertyManager->initial(); - - // 应用配置 - comm->updateHttpConfig(config->getHttpConfig()); - comm->updateWebSocketConfig(config->getWebSocketConfig()); - - _dataAccessor = new DataAccessor(this); - _dataAccessor->setParent(this); - connect(UiCommunicationBus::instance(), - SIGNAL(httpDataProcessed(QString,QVariant)), - _dataAccessor, - SLOT(onReceiveHttpData(QString,QVariant)), - Qt::AutoConnection); - connect(UiCommunicationBus::instance(), - SIGNAL(websocketDataProcessed(QVariant)), - _dataAccessor, - SLOT(onReceiveWebsocketData(QVariant)), - Qt::AutoConnection); - _structDataPreviewDlg = new StructDataPreviewDlg(this); - _structDataPreviewDlg->setExtraPropertyManager(_extraPropertyManager); - _structDataPreviewDlg->loadData(); - - QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization(); - QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization(); - - _createHMIDlg = new CreateHMIdlg(this); - connect(_createHMIDlg,&CreateHMIdlg::createHMI,this,&DiagramCavas::onSignal_createHMIClicked); - updateHMIlstFromDB(); - - loadPluginConfig(QCoreApplication::applicationDirPath()+"/pluginConfig.json"); //加载plugin关联信息 - - m_pluginManager = PluginManager::instance(); - //创建Canvas项工厂 - m_itemFactory = PluginItemFactory::instance(); - m_itemFactory->setPluginManager(m_pluginManager); - //加载插件 - QString pluginsDir = QApplication::applicationDirPath() + "/plugins"; - m_pluginManager->addPluginDirectory(pluginsDir); - m_pluginManager->loadAllPlugins(pluginsDir); - - _pPropertyDlg = new PropertyDlg(parentWidget()); - _pPropertyDlg->hide(); - addShortcuts(); - //setViewMode(QMdiArea::TabbedView); + Q_D(DiagramCavas); + d->initialImpl(); // 调用私有实现 } void DiagramCavas::setCurMode(int nMode) { - _curMode = nMode; - if(_curMode == 1){ //运行模式下 + Q_D(DiagramCavas); + d->_curMode = nMode; + if(d->_curMode == 1){ //运行模式下 showPropertyDlg(); //setViewMode(QMdiArea::SubWindowView); } @@ -195,74 +79,43 @@ void DiagramCavas::setCurMode(int nMode) } } +int DiagramCavas::getCurMode() +{ + Q_D(DiagramCavas); + return d->_curMode; +} + void DiagramCavas::showPropertyDlg() { - if(_pPropertyPage == nullptr){ //未被初始化 - _pPropertyPage = new QDetailsView(); - _pPropertyPage->setObject(new QObject(this)); - } - _pPropertyDlg->setContent(_pPropertyPage); - _pPropertyDlg->show(); - - QScreen *screen = QGuiApplication::screenAt(parentWidget()->geometry().center()); - if (!screen) { - screen = QGuiApplication::primaryScreen(); - } - - QRect screenGeometry = screen->geometry(); - QRect dialogRect = _pPropertyDlg->geometry(); - - // 计算位置:水平靠右,垂直居中 - int x = screenGeometry.right() - dialogRect.width() - 10; // 留10像素边距 - int y = screenGeometry.center().y() - dialogRect.height() / 2; - - _pPropertyDlg->move(x, y); + Q_D(DiagramCavas); + d->showPropertyDlgImpl(); } void DiagramCavas::hidePropertyDlg() { - _pPropertyDlg->removeContent(_pPropertyPage); - _pPropertyDlg->hide(); + Q_D(DiagramCavas); + d->hidePropertyDlgImpl(); } void DiagramCavas::setHMIVisiblebyName(const QString& str,bool val) { + Q_D(DiagramCavas); PowerEntity* pEntity = TopologyManager::instance().findDiagramByName(str,ModelFunctionType::RuntimeModel); if(pEntity) { if(val) //显示 onSignal_loadMonitor(pEntity); else{ - if(m_mapMonitorPanel.contains(str)) - m_mapMonitorPanel[str].first->hide(); + if(d->m_mapMonitorPanel.contains(str)) + d->m_mapMonitorPanel[str].first->hide(); } } } void DiagramCavas::onSignal_addDrawingPanel(PowerEntity* pItem,DiagramMode mode,QString parent) { - if(mode == DM_run){ - MonitorPanel* pPanel = new MonitorPanel(pItem,this,mode); - _curPage = pItem->name(); - pPanel->setPageName(_curPage); - pPanel->setWindowTitle(_curPage); - pPanel->setParentPage(parent); - QMdiSubWindow* pSub = this->addSubWindow(pPanel); - m_mapMonitorPanel.insert(_curPage,qMakePair(pPanel,pSub)); - pPanel->show(); - - FixedPortsModel* pModel = pPanel->getModelController(); - pModel->setCavas(QPointer(this)); - connect(pModel,&FixedPortsModel::activatePage,this,&DiagramCavas::onSignal_activatePage); - connect(pPanel,&MonitorPanel::panelDelete,this,&DiagramCavas::onSignal_panelDelete); - connect(pModel,&FixedPortsModel::monitorCreated,this,&DiagramCavas::onSignal_monitorCreated); - connect(pModel,&FixedPortsModel::monitorItems,this,&DiagramCavas::onSignal_monitorItemCreated); - //connect(pModel,&FixedPortsModel::notifyUpdateMonitorTopology,this,&DiagramCavas::onSignal_updateMonitorTopology); ***使用属性构建拓扑层级,暂不使用260317 by - connect(pModel,&FixedPortsModel::updateTopologyItems,this,&DiagramCavas::onSignal_updateTopology); - - connect(pModel,&FixedPortsModel::HMIUpdated,this,&DiagramCavas::onSignal_updateHMI); - } - calculateLauncherVisible(); + Q_D(DiagramCavas); + d->addDrawingPanelImpl(pItem, mode, parent); } void DiagramCavas::onSignal_addGraphicsItem(ModelStateInfo& info) @@ -284,81 +137,24 @@ void DiagramCavas::onSignal_addPage() void DiagramCavas::onSignal_savePage() { - QWidget* pWindow= currentSubWindow()->widget(); - BaseDrawingPanel* pPanel = dynamic_cast(pWindow); - if(pPanel) - { - if(pPanel->getMode() == DM_run) - { - auto pMonitor = dynamic_cast(pPanel); - if(pMonitor){ - auto pEntity = pMonitor->getEntity(); - if(pEntity){ - QMap& mapResource = ProjectModelManager::instance().getHMIimageMap(); - DataBase::GetInstance()->insertHMIimagesWithCheck(mapResource.values()); //智能查重插入HMIsource - - QList& imgRefLst = pMonitor->getModelController()->getHMIimageRef(); //获取当前HMI所有img引用 - if(imgRefLst.size()){ - auto lstRef = DataBase::GetInstance()->getHMIRefAll(imgRefLst.first().hmiId); //检测HMI是否存储过,删除旧img引用 - if(lstRef.size()) - DataBase::GetInstance()->removeHMIRefAll(imgRefLst.first().hmiId); - DataBase::GetInstance()->insertHMIimageRefBatch(imgRefLst); //全部重新插入 - } - - QList& imgCustomRefLst = pMonitor->getModelController()->getHMICustomImageRef(); //获取当前HMI所有custom引用 - if(imgCustomRefLst.size()){ - auto lstRef = DataBase::GetInstance()->getHMICustomRefAll(imgCustomRefLst.first().hmiId); - if(lstRef.size()) - DataBase::GetInstance()->removeHMICustomRefAll(imgCustomRefLst.first().hmiId); - DataBase::GetInstance()->insertHMICustomRefBatch(imgCustomRefLst); - } - - if(DataBase::GetInstance()->getHMIdByName(pEntity->name()).isNull()) //不存在,创建 - DataBase::GetInstance()->insertHMI(QUuid(pEntity->id()),pEntity->name(),pEntity->name(),pMonitor->getDiagramInfo()); - else - DataBase::GetInstance()->updateHMI(pEntity->name(),pMonitor->getDiagramInfo()); - auto pControl = pMonitor->getModelController(); - if(pControl) - emit pControl->HMIUpdated(pEntity->name(),QUuid(pEntity->id()),1,QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm")); - QMessageBox::information(NULL, QString("提示"), QString::fromWCharArray(L"保存成功")); - } - } - } - } + Q_D(DiagramCavas); + d->savePageImpl(); } void DiagramCavas::onSignal_loadMonitor(PowerEntity* p) { - if(!m_mapMonitorPanel.contains(p->name())) - { - onSignal_addDrawingPanel(p,DiagramMode::DM_run); - QJsonObject context = DataBase::GetInstance()->getHMIContextByTag(p->name()); - m_mapMonitorPanel[p->name()].first->loadNodes(context); - - QJsonObject pageObj = context["pageAttr"].toObject(); - int x = pageObj["x"].toInt(); - int y = pageObj["y"].toInt(); - int nWidth = pageObj["width"].toInt(); - int nHeight = pageObj["height"].toInt(); - if(nWidth && nHeight){ - m_mapMonitorPanel[p->name()].second->setGeometry(x,y,nWidth,nHeight); - } - } - else //已存在 - { - m_mapMonitorPanel[p->name()].first->show(); - setActiveSubWindow(m_mapMonitorPanel[p->name()].second); - } - onTargetSelected(m_mapMonitorPanel[p->name()].first->getPropertyProxy()); + Q_D(DiagramCavas); + d->loadMonitorImpl(p); } void DiagramCavas::runPage(const QString sName) { + Q_D(DiagramCavas); QString pageName = sName+QString("_run"); - if(!m_mapMonitorPanel.contains(pageName)) + if(!d->m_mapMonitorPanel.contains(pageName)) { //onSignal_addDrawingPanel(pageName,DM_run); - QJsonObject context = DataBase::GetInstance()->getPageContextByName(sName); + //QJsonObject context = DataBase::GetInstance()->getPageContextByName(sName); //m_mapDrawPanel[pageName]->loadNodes(context); } else //已存在 @@ -369,7 +165,8 @@ void DiagramCavas::runPage(const QString sName) void DiagramCavas::onSignal_runPage() { - runPage(_curPage); + Q_D(DiagramCavas); + runPage(d->_curPage); } void DiagramCavas::onSignal_deletePage() @@ -379,17 +176,19 @@ void DiagramCavas::onSignal_deletePage() void DiagramCavas::onSignal_activatePage(const QString& name) { - _curPage = name; + Q_D(DiagramCavas); + d->_curPage = name; } void DiagramCavas::onSignal_panelDelete(const QString& name,int nType) { + Q_D(DiagramCavas); if(nType == 2){ - MonitorPanel* pPanel = m_mapMonitorPanel.take(name).first; + MonitorPanel* pPanel = d->m_mapMonitorPanel.take(name).first; this->removeSubWindow(pPanel); delete pPanel; } - calculateLauncherVisible(); + d->calculateLauncherVisible(); } void DiagramCavas::onSignal_createEntity(EntityInfo info) @@ -427,6 +226,7 @@ void DiagramCavas::onSignal_changeEntity(EntityInfo info) void DiagramCavas::onSignal_deleteEntity(EntityInfo info) { + Q_D(DiagramCavas); PowerEntity* pEntity = TopologyManager::instance().findEntity(info.sUuid); if(pEntity) { @@ -437,7 +237,7 @@ void DiagramCavas::onSignal_deleteEntity(EntityInfo info) TopologyManager::instance().deleteEntity(info.sUuid); break; case EntityType::ConfigurationDiagram: - removePanel(pEntity); + d->removePanel(pEntity); TopologyManager::instance().deleteEntity(info.sUuid); break; default: @@ -495,10 +295,11 @@ void DiagramCavas::onSignal_changeDiagram(DiagramInfo info) void DiagramCavas::onSignal_deleteDiagram(DiagramInfo info) { + Q_D(DiagramCavas); PowerEntity* pEntity = TopologyManager::instance().findDiagram(info.id.toString()); if(pEntity) { - removePanel(pEntity); + d->removePanel(pEntity); TopologyManager::instance().deleteEntity(info.id.toString()); } } @@ -518,15 +319,14 @@ void DiagramCavas::onSignal_selectDiagram(DiagramInfo info) void DiagramCavas::onSignal_openNetSetting() { - if(_connectSetting){ - _connectSetting->showDlg(); - } + Q_D(DiagramCavas); + d->showNewSettingDlg(); } void DiagramCavas::onSignal_openStructDataPreview() { - if(_structDataPreviewDlg) - _structDataPreviewDlg->showDlg(); + Q_D(DiagramCavas); + d->showStructDataPreviewDlg(); } void DiagramCavas::onSignal_createHMI(QString sName,QUuid id) @@ -539,111 +339,16 @@ void DiagramCavas::onSignal_updateHMI(QString sName,QUuid id,int nState,QString emit updateHMI(sName,id,nState,sTime); } -void DiagramCavas::removePanel(PowerEntity* pEntity) -{ - QMap>::Iterator iter; - for(iter = m_mapMonitorPanel.begin(); iter != m_mapMonitorPanel.end();++iter) - { - if(pEntity->name() == iter.value().first->pageName()) - { - MonitorPanel* pPanel = m_mapMonitorPanel.take(iter.key()).first; - - QWidget* pWindow = static_cast(pPanel); - setActiveSubWindow(iter->second); - closeActiveSubWindow(); - //removeSubWindow(pPanel); - //todo:记录删除组态图,从数据库中删除 - delete pPanel; - break; - } - } -} - -void DiagramCavas::calculateLauncherVisible() -{ - if(_cornerButton){ - if (m_mapMonitorPanel.isEmpty()) { - _cornerButton->setVisible(true); - } else { - _cornerButton->setVisible(false); - } - } -} - -bool DiagramCavas::loadPluginConfig(const QString& configPath) -{ - QFile file(configPath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Cannot open config file:" << configPath; - return false; - } - - QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); - if (doc.isNull() || !doc.isObject()) { - qWarning() << "Invalid JSON config"; - return false; - } - - return parsePluginConfig(doc.object()); -} - -bool DiagramCavas::parsePluginConfig(const QJsonObject& root) -{ - if (!root.contains("shapes")) { - qWarning() << "Missing 'shapes' key"; - return false; - } - - QJsonArray items = root["shapes"].toArray(); - - for (const QJsonValue& itemVal : items) { - QJsonObject itemObj = itemVal.toObject(); - - int type = itemObj["type"].toInt(); - QString shapeName = itemObj["shapeName"].toString(); - QString modelName = itemObj["modelName"].toString(); - - // 解析枚举类型 - PluginTypeInfo info; - info.baseType = type; - info.shapeName = shapeName; - info.modelName = modelName; - m_pluginInfo[shapeName] = info; - } - - qDebug() << "Loaded" << m_pluginInfo.size() << "shapes types from config"; - return true; -} - -void DiagramCavas::addShortcuts() -{ - QShortcut* toggleProp = new QShortcut(QKeySequence("Ctrl+P"), this); - connect(toggleProp, &QShortcut::activated, [this]() { - if(_pPropertyDlg->isVisible()){ - hidePropertyDlg(); - } - else{ - if(_curMode == 1) - showPropertyDlg(); - } - }); -} - void DiagramCavas::resizeEvent(QResizeEvent* event) { - if(_cornerButton) - _cornerButton->positionAtCorner(); + Q_D(DiagramCavas); + d->updateCornerPos(); } void DiagramCavas::onTargetSelected(QObject* obj) { - if(obj){ - if(_curMode == 0) - emit selectTarget(obj); - else - _pPropertyPage->setObject(obj); - } - + Q_D(DiagramCavas); + d->onTargetSelected(obj); } /****************************************************/ @@ -672,19 +377,14 @@ void DiagramCavas::onSignl_openCurrentBay() void DiagramCavas::onCreateHMIClicked() { - if(_createHMIDlg) - _createHMIDlg->showDlg(); + Q_D(DiagramCavas); + d->onCreateHMI(); } void DiagramCavas::onSignal_createHMIClicked(QString sHMI,QString sStructPage,int modelType) { - QUuid id = QUuid::createUuid(); - auto *pEntity = TopologyManager::instance().createDiagram(id.toString(),sHMI,ModelFunctionType::RuntimeModel); - onSignal_addDrawingPanel(pEntity,DiagramMode::DM_run); - QJsonObject context = DataBase::GetInstance()->getMonitorContextByTag(sStructPage); - m_mapMonitorPanel[sHMI].first->loadNodes(context); //加载系统图结构 - onSignal_createHMI(sHMI,id); - onTargetSelected(m_mapMonitorPanel[sHMI].first->getPropertyProxy()); + Q_D(DiagramCavas); + d->createHMIClickedImpl(sHMI, sStructPage, modelType); } void DiagramCavas::onSignal_updateCurItems(QList lst,bool refresh) @@ -718,7 +418,9 @@ void DiagramCavas::onSignal_monitorSelected(DiagramInfo info) void DiagramCavas::onSignal_saveMonitor(QList> lst) { - for(auto &pair:lst){ + //生成monitor相关,GridFrame中处理 + + /*for(auto &pair:lst){ auto pMonitor = m_mapMonitorPanel.value(pair.first).first; if(pMonitor){ if(DataBase::GetInstance()->getPageIdByName(pMonitor->getParentPage()) == -1){ @@ -737,12 +439,14 @@ void DiagramCavas::onSignal_saveMonitor(QList> lst) DataBase::GetInstance()->updateMonitor(pair.first,pMonitor->getDiagramInfo()); } } - QMessageBox::information(NULL, QString("提示"), QString::fromWCharArray(L"保存成功")); + QMessageBox::information(NULL, QString("提示"), QString::fromWCharArray(L"保存成功"));*/ } void DiagramCavas::updateMonitorListFromDB(int dest) { - if(dest != 0) + //加载monitor列表,GridFrame中处理 + + /*if(dest != 0) _loadMonitorPageDlg->clearItems(); QList lstMonitor = DataBase::GetInstance()->getAllMonitor(); @@ -764,7 +468,7 @@ void DiagramCavas::updateMonitorListFromDB(int dest) _loadMonitorPageDlg->updateItems(info.parent,qMakePair(info.name,info.uid)); } } - } + }*/ } void DiagramCavas::onSignal_updateMonitorTopology(QList lst) @@ -774,12 +478,6 @@ void DiagramCavas::onSignal_updateMonitorTopology(QList lst) void DiagramCavas::updateHMIlstFromDB() { - QList lstMonitor = DataBase::GetInstance()->getAllHMI(); - for(auto &info:lstMonitor) - { - auto p = TopologyManager::instance().findDiagram(info.uid.toString(),ModelFunctionType::RuntimeModel); - if(!p){ - TopologyManager::instance().createDiagram(info.uid.toString(),info.name,ModelFunctionType::RuntimeModel); - } - } + Q_D(DiagramCavas); + d->updateHMIFromDB(); } diff --git a/diagramCavas/source/diagramCavas_p.cpp b/diagramCavas/source/diagramCavas_p.cpp new file mode 100644 index 0000000..3e7dd9b --- /dev/null +++ b/diagramCavas/source/diagramCavas_p.cpp @@ -0,0 +1,1216 @@ +// diagramcavas_p.cpp +#include "diagramCavas_p.h" +#include "diagramCavas.h" +#include "dataBase.h" +#include "projectModelManager.h" +#include "diagramCommunication/include/communicationManager.h" +#include "diagramCommunication/include/configManager.h" +#include "uiCommunicationBus.h" +#include "itemPropertyDlg.h" +#include "QQuickDetailsViewMananger.h" +#include "propertyType/propertyTypeCustomization_DataSourceType.h" +#include "propertyType/propertyTypeCustomization_ConfigEventData.h" +#include "propertyType/dataSourceType.h" +#include +#include +#include +#include +#include +#include +#include +#include "graphicsItem/graphicsBaseItem.h" +#include "topologyManager.h" +#include "powerEntity.h" +#include "cornerMonitorLauncher.h" +#include "loadMonitorPageDlg.h" +#include "diagramConnectSetting.h" +#include "instance/dataAccessor.h" +#include "monitorConfigDlg.h" +#include "structDataPreviewDlg.h" +#include "extraPropertyManager.h" +#include "createHMIdlg.h" +#include "pluginManager.h" +#include "graphicsItem/pluginItemFactory.h" +#include "QDetailsView.h" +#include "propertyDialog.h" + +#include "basePannelPropertyProxy.h" +#include "QDetailsView.h"" +#include +#include +#include +#include + +DiagramCavasPrivate::DiagramCavasPrivate(DiagramCavas* q) + : q_ptr(q) + , _pageIndex(0) + , _curMode(0) + , _cornerButton(nullptr) + , _loadMonitorPageDlg(nullptr) + , _connectSetting(nullptr) + , _dataAccessor(nullptr) + , _structDataPreviewDlg(nullptr) + , _extraPropertyManager(nullptr) + , _createHMIDlg(nullptr) + , _pPropertyPage(nullptr) + , _pPropertyDlg(nullptr) + , m_pluginManager(nullptr) + , m_itemFactory(nullptr) +{ + // 初始化代码 +} + +DiagramCavasPrivate::~DiagramCavasPrivate() +{ + // 清理代码 + if (_cornerButton) delete _cornerButton; + if (_loadMonitorPageDlg) delete _loadMonitorPageDlg; + if (_connectSetting) delete _connectSetting; + if (_dataAccessor) delete _dataAccessor; + if (_structDataPreviewDlg) delete _structDataPreviewDlg; + if (_extraPropertyManager) delete _extraPropertyManager; + if (_createHMIDlg) delete _createHMIDlg; +} + +void DiagramCavasPrivate::initialImpl() +{ + Q_Q(DiagramCavas); + + // 1. 读取数据并初始化页面 + QList lst = DataBase::GetInstance()->getAllPage(); + for (auto &info : lst) { + TopologyManager::instance().createDiagram(QString::number(info.id), info.name); + } + + // 2. 初始化角落监控启动器 + _cornerButton = new CornerMonitorLauncher(q); + _cornerButton->showDlg(); + + // 3. 初始化加载监控页面对话框 + _loadMonitorPageDlg = new LoadMonitorPageDlg(q); + QObject::connect(_cornerButton, &CornerMonitorLauncher::openLoadMonitorDlg, q, [this, q]() { + if (_loadMonitorPageDlg) { + q->updateMonitorListFromDB(1); + _loadMonitorPageDlg->show(); + } + }); + QObject::connect(_loadMonitorPageDlg, &LoadMonitorPageDlg::monitorSelected, q, &DiagramCavas::onSignal_monitorSelected); + + // 4. 初始化连接设置 + _connectSetting = new DiagramConnectSetting(q); + + // 5. 初始化通信管理器 + CommunicationManager* comm = CommunicationManager::instance(); + comm->initialize(); + + // 6. 加载配置 + ConfigManager* config = ConfigManager::instance(); + config->loadConfig("config.json"); + + // 7. 初始化额外属性管理器 + _extraPropertyManager = new ExtraPropertyManager(q); + _extraPropertyManager->initial(); + + // 8. 应用配置到通信管理器 + comm->updateHttpConfig(config->getHttpConfig()); + comm->updateWebSocketConfig(config->getWebSocketConfig()); + + // 9. 初始化数据访问器 + _dataAccessor = new DataAccessor(q); + _dataAccessor->setParent(q); + QObject::connect(UiCommunicationBus::instance(), + SIGNAL(httpDataProcessed(QString, QVariant)), + _dataAccessor, + SLOT(onReceiveHttpData(QString, QVariant)), + Qt::AutoConnection); + QObject::connect(UiCommunicationBus::instance(), + SIGNAL(websocketDataProcessed(QVariant)), + _dataAccessor, + SLOT(onReceiveWebsocketData(QVariant)), + Qt::AutoConnection); + + // 10. 初始化结构数据预览对话框 + _structDataPreviewDlg = new StructDataPreviewDlg(q); + _structDataPreviewDlg->setExtraPropertyManager(_extraPropertyManager); + _structDataPreviewDlg->loadData(); + + // 11. 注册自定义属性类型 + QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization(); + QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization(); + + // 12. 初始化创建HMI对话框 + _createHMIDlg = new CreateHMIdlg(q); + QObject::connect(_createHMIDlg, &CreateHMIdlg::createHMI, q, &DiagramCavas::onSignal_createHMIClicked); + + // 13. 从数据库更新HMI列表 + q->updateHMIlstFromDB(); + + // 14. 加载插件配置 + QString pluginConfigPath = QCoreApplication::applicationDirPath() + "/pluginConfig.json"; + loadPluginConfig(pluginConfigPath); + + // 15. 初始化插件管理器 + m_pluginManager = PluginManager::instance(); + + // 16. 创建Canvas项工厂 + m_itemFactory = PluginItemFactory::instance(); + m_itemFactory->setPluginManager(m_pluginManager); + + // 17. 加载插件 + QString pluginsDir = QApplication::applicationDirPath() + "/plugins"; + m_pluginManager->addPluginDirectory(pluginsDir); + m_pluginManager->loadAllPlugins(pluginsDir); + + // 18. 初始化属性对话框 + _pPropertyDlg = new PropertyDlg(q->parentWidget()); + _pPropertyDlg->hide(); + + // 19. 添加快捷键 + addShortcuts(); + + // 20. 设置视图模式 + // q->setViewMode(QMdiArea::TabbedView); +} + +void DiagramCavasPrivate::removePanel(PowerEntity* pEntity) +{ + Q_Q(DiagramCavas); + QMap>::Iterator iter; + for(iter = m_mapMonitorPanel.begin(); iter != m_mapMonitorPanel.end();++iter) + { + if(pEntity->name() == iter.value().first->pageName()) + { + MonitorPanel* pPanel = m_mapMonitorPanel.take(iter.key()).first; + + QWidget* pWindow = static_cast(pPanel); + q->setActiveSubWindow(iter->second); + q->closeActiveSubWindow(); + //removeSubWindow(pPanel); + //todo:记录删除组态图,从数据库中删除 + delete pPanel; + break; + } + } +} + + +void DiagramCavasPrivate::calculateLauncherVisible() +{ + if(_cornerButton){ + if (m_mapMonitorPanel.isEmpty()) { + _cornerButton->setVisible(true); + } else { + _cornerButton->setVisible(false); + } + } +} + +bool DiagramCavasPrivate::loadPluginConfig(const QString& path) +{ + QFile file(path); + if (!file.open(QIODevice::ReadOnly)) { + return false; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + file.close(); + + if (doc.isObject()) { + return parsePluginConfig(doc.object()); + } + + return false; +} + +bool DiagramCavasPrivate::parsePluginConfig(const QJsonObject& root) +{ + if (!root.contains("shapes")) { + qWarning() << "Missing 'shapes' key"; + return false; + } + + QJsonArray items = root["shapes"].toArray(); + + for (const QJsonValue& itemVal : items) { + QJsonObject itemObj = itemVal.toObject(); + + int type = itemObj["type"].toInt(); + QString shapeName = itemObj["shapeName"].toString(); + QString modelName = itemObj["modelName"].toString(); + + // 解析枚举类型 + PluginTypeInfo info; + info.baseType = type; + info.shapeName = shapeName; + info.modelName = modelName; + m_pluginInfo[shapeName] = info; + } + + qDebug() << "Loaded" << m_pluginInfo.size() << "shapes types from config"; + return true; +} + +void DiagramCavasPrivate::addShortcuts() +{ + Q_Q(DiagramCavas); + // 添加快捷键 + QShortcut* shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_S), q); + QObject::connect(shortcut, &QShortcut::activated, q, [q]() { + q->onSignal_savePage(); + }); + + QShortcut* toggleProp = new QShortcut(QKeySequence("Ctrl+P"), q); + QObject::connect(toggleProp, &QShortcut::activated, q,[&,q]() { + if(_pPropertyDlg->isVisible()){ + q->hidePropertyDlg(); + } + else{ + if(_curMode == 1) + q->showPropertyDlg(); + } + }); +} + +void DiagramCavasPrivate::updateCornerPos() +{ + if(_cornerButton) + _cornerButton->positionAtCorner(); +} + +void DiagramCavasPrivate::showNewSettingDlg() +{ + if(_connectSetting){ + _connectSetting->showDlg(); + } +} + +void DiagramCavasPrivate::showStructDataPreviewDlg() +{ + if(_structDataPreviewDlg) + _structDataPreviewDlg->showDlg(); +} + +void DiagramCavasPrivate::processRecommandData(const HttpRecommandInfo& info) +{ + Q_Q(DiagramCavas); + + // 1. 生成完整名称列表 + QStringList completeNames = info.generateCompleteNames(); + + // 2. 更新数据预览对话框 + if (_structDataPreviewDlg) { + _structDataPreviewDlg->updateRecommandLst(completeNames); + qDebug() << "Updated data preview dialog with" << completeNames.size() << "items"; + } + + // 3. 获取当前子窗口 + QMdiSubWindow* currentSubWindow = q->currentSubWindow(); + if (!currentSubWindow) { + qDebug() << "No active window, skipping panel update"; + return; + } + + // 4. 获取当前面板 + QWidget* windowWidget = currentSubWindow->widget(); + BaseDrawingPanel* panel = dynamic_cast(windowWidget); + + if (!panel) { + qDebug() << "Current window is not a drawing panel"; + return; + } + + // 5. 只处理运行模式的面板 + if (panel->getMode() == DM_run) { + MonitorPanel* monitorPanel = dynamic_cast(panel); + if (monitorPanel) { + qDebug() << "Monitor panel found:" << monitorPanel->pageName(); + // todo: 推荐列表的使用 + // 这里可以根据需要调用监控面板的方法 + } + } + + qDebug() << "Recommand data processed:" + << "input =" << info.sInput + << "offset =" << info.nOffset + << "items =" << info.lstRecommand.size(); +} + +void DiagramCavasPrivate::onTargetSelected(QObject* obj) +{ + Q_Q(DiagramCavas); + if(obj){ + if(_curMode == 0) + emit q->selectTarget(obj); + else + _pPropertyPage->setObject(obj); + } +} + +void DiagramCavasPrivate::onCreateHMI() +{ + if(_createHMIDlg) + _createHMIDlg->showDlg(); +} + +void DiagramCavasPrivate::updateHMIFromDB() +{ + QList lstMonitor = DataBase::GetInstance()->getAllHMI(); + for(auto &info:lstMonitor) + { + auto p = TopologyManager::instance().findDiagram(info.uid.toString(),ModelFunctionType::RuntimeModel); + if(!p){ + TopologyManager::instance().createDiagram(info.uid.toString(),info.name,ModelFunctionType::RuntimeModel); + } + } +} + +void DiagramCavasPrivate::initPropertyPage() +{ + if (_pPropertyPage == nullptr) { + _pPropertyPage = new QDetailsView(); + _pPropertyPage->setObject(new QObject(q_ptr)); + + // 可以在这里配置属性页的更多设置 + _pPropertyPage->setWindowTitle("属性面板"); + _pPropertyPage->setMinimumSize(300, 400); + + // 连接属性变化的信号 + // connect(_pPropertyPage, &QDetailsView::propertyChanged, + // q_ptr, &DiagramCavas::onPropertyChanged); + } +} + +void DiagramCavasPrivate::showPropertyDlgImpl() +{ + Q_Q(DiagramCavas); + + // 确保属性页面已初始化 + initPropertyPage(); + + // 确保属性对话框已创建 + if (_pPropertyDlg == nullptr) { + _pPropertyDlg = new PropertyDlg(q->parentWidget()); + _pPropertyDlg->setWindowTitle("属性设置"); + _pPropertyDlg->setModal(false); // 非模态对话框 + + // 连接对话框关闭信号 + QObject::connect(_pPropertyDlg, &PropertyDlg::finished, q, [this]() { + // 对话框关闭时的处理 + qDebug() << "Property dialog closed"; + }); + } + + // 设置内容 + _pPropertyDlg->setContent(_pPropertyPage); + _pPropertyDlg->show(); + + // 居中显示 + centerPropertyDialogOnScreen(); + + // 激活窗口 + _pPropertyDlg->raise(); + _pPropertyDlg->activateWindow(); +} + +void DiagramCavasPrivate::hidePropertyDlgImpl() +{ + if (_pPropertyDlg) { + _pPropertyDlg->hide(); + } +} + +void DiagramCavasPrivate::centerPropertyDialogOnScreen() +{ + if (!_pPropertyDlg || !_pPropertyDlg->isVisible()) { + return; + } + + Q_Q(DiagramCavas); + + // 获取屏幕 + QScreen* screen = nullptr; + if (q->parentWidget()) { + screen = QGuiApplication::screenAt(q->parentWidget()->geometry().center()); + } + + if (!screen) { + screen = QGuiApplication::primaryScreen(); + } + + if (!screen) { + qWarning() << "No screen available for centering dialog"; + return; + } + + QRect screenGeometry = screen->geometry(); + QRect dialogGeometry = _pPropertyDlg->geometry(); + + // 计算位置:水平靠右,垂直居中 + int x = screenGeometry.right() - dialogGeometry.width() - 10; // 留10像素边距 + int y = screenGeometry.center().y() - dialogGeometry.height() / 2; + + // 确保对话框不超出屏幕 + y = qMax(screenGeometry.top(), qMin(y, screenGeometry.bottom() - dialogGeometry.height())); + x = qMax(screenGeometry.left(), qMin(x, screenGeometry.right() - dialogGeometry.width())); + + _pPropertyDlg->move(x, y); + + // 可选:保存位置到配置 + // saveDialogPositionToConfig(x, y); +} + +void DiagramCavasPrivate::addDrawingPanelImpl(PowerEntity* pItem, DiagramMode mode, const QString& parent) +{ + if (!pItem) { + qWarning() << "Cannot add drawing panel: PowerEntity is null"; + return; + } + + if (mode == DM_run) { + addMonitorPanel(pItem, parent); + } else { + addEditorPanel(pItem, parent); + } + + calculateLauncherVisible(); +} + +void DiagramCavasPrivate::addMonitorPanel(PowerEntity* pItem, const QString& parent) +{ + Q_Q(DiagramCavas); + + // 创建监控面板 + MonitorPanel* pPanel = new MonitorPanel(pItem, q, DM_run); + + // 更新当前页面信息 + QString panelName = pItem->name(); + updateCurrentPage(panelName); + + // 配置面板 + pPanel->setPageName(_curPage); + pPanel->setWindowTitle(_curPage); + pPanel->setParentPage(parent); + + // 添加到MDI区域 + QMdiSubWindow* pSub = q->addSubWindow(pPanel); + m_mapMonitorPanel.insert(_curPage, qMakePair(pPanel, pSub)); + + // 显示面板 + pPanel->show(); + + // 获取模型控制器并设置连接 + FixedPortsModel* pModel = pPanel->getModelController(); + if (pModel) { + pModel->setCavas(QPointer(q)); + connectMonitorPanelSignals(pPanel, pModel); + } else { + qWarning() << "Failed to get model controller for monitor panel:" << _curPage; + } + + qDebug() << "Monitor panel added:" << _curPage << "parent:" << parent; +} + +void DiagramCavasPrivate::addEditorPanel(PowerEntity* pItem, const QString& parent) +{ + Q_Q(DiagramCavas); + + // 编辑器面板的添加 + qWarning() << "Editor panel not implemented yet for:" << pItem->name(); + + // 示例代码: + // DrawingPanel* pPanel = new DrawingPanel(pItem, q, DM_edit); + // pPanel->setPageName(pItem->name()); + // pPanel->setWindowTitle(pItem->name()); + // pPanel->setParentPage(parent); + // + // QMdiSubWindow* pSub = q->addSubWindow(pPanel); + // pPanel->show(); + // + // qDebug() << "Editor panel added:" << pItem->name() << "parent:" << parent; +} + +void DiagramCavasPrivate::connectMonitorPanelSignals(MonitorPanel* panel, FixedPortsModel* model) +{ + Q_Q(DiagramCavas); + + if (!panel || !model) { + return; + } + + // 连接面板删除信号 + QObject::connect(panel, &MonitorPanel::panelDelete, q, + &DiagramCavas::onSignal_panelDelete); + + // 连接模型信号 + QObject::connect(model, &FixedPortsModel::activatePage, q, + &DiagramCavas::onSignal_activatePage); + + QObject::connect(model, &FixedPortsModel::monitorCreated, q, + &DiagramCavas::onSignal_monitorCreated); + + QObject::connect(model, &FixedPortsModel::monitorItems, q, + &DiagramCavas::onSignal_monitorItemCreated); + + // 注释掉的连接(根据原始代码) + // connect(model, &FixedPortsModel::notifyUpdateMonitorTopology, q, + // &DiagramCavas::onSignal_updateMonitorTopology); + + QObject::connect(model, &FixedPortsModel::updateTopologyItems, q, + &DiagramCavas::onSignal_updateTopology); + + QObject::connect(model, &FixedPortsModel::HMIUpdated, q, + &DiagramCavas::onSignal_updateHMI); + + // 可选:连接其他信号 + // connect(panel, &MonitorPanel::panelActivated, q, + // [this, q](const QString& name) { + // updateCurrentPage(name); + // }); + + qDebug() << "Monitor panel signals connected for:" << _curPage; +} + +void DiagramCavasPrivate::updateCurrentPage(const QString& pageName) +{ + _curPage = pageName; + qDebug() << "Current page updated to:" << _curPage; +} + +bool DiagramCavasPrivate::hasPanel(const QString& name) const +{ + return m_mapMonitorPanel.contains(name); +} + +MonitorPanel* DiagramCavasPrivate::getPanel(const QString& name) const +{ + if (m_mapMonitorPanel.contains(name)) { + return m_mapMonitorPanel[name].first; + } + return nullptr; +} + +QMdiSubWindow* DiagramCavasPrivate::getSubWindow(const QString& name) const +{ + if (m_mapMonitorPanel.contains(name)) { + return m_mapMonitorPanel[name].second; + } + return nullptr; +} + +void DiagramCavasPrivate::savePageImpl() +{ + Q_Q(DiagramCavas); + + // 获取当前子窗口 + QMdiSubWindow* currentSubWindow = q->currentSubWindow(); + if (!currentSubWindow) { + qWarning() << "No active subwindow for saving"; + QMessageBox::warning(nullptr, QString("警告"), + QString::fromWCharArray(L"没有活动的页面可以保存")); + return; + } + + // 获取面板 + BaseDrawingPanel* pPanel = getCurrentDrawingPanel(); + if (!pPanel) { + qWarning() << "Cannot cast to BaseDrawingPanel"; + return; + } + + // 只保存监控面板 + if (pPanel->getMode() != DM_run) { + qDebug() << "Only run mode panels can be saved, current mode:" << pPanel->getMode(); + return; + } + + // 保存监控面板 + auto pMonitor = dynamic_cast(pPanel); + if (!pMonitor) { + qWarning() << "Failed to cast to MonitorPanel"; + return; + } + + bool success = saveMonitorPanel(pMonitor); + + if (success) { + QMessageBox::information(nullptr, QString("提示"), + QString::fromWCharArray(L"保存成功")); + } else { + QMessageBox::warning(nullptr, QString("警告"), + QString::fromWCharArray(L"保存失败")); + } +} + +bool DiagramCavasPrivate::saveMonitorPanel(MonitorPanel* monitorPanel) +{ + if (!monitorPanel) { + return false; + } + + PowerEntity* entity = monitorPanel->getEntity(); + if (!entity) { + qWarning() << "MonitorPanel has no entity"; + return false; + } + + Q_Q(DiagramCavas); + + // 1. 保存HMI图片 + QMap& imageMap = ProjectModelManager::instance().getHMIimageMap(); + if (!saveHMIImages(imageMap)) { + qWarning() << "Failed to save HMI images"; + return false; + } + + // 2. 保存图片引用 + FixedPortsModel* controller = monitorPanel->getModelController(); + if (!controller) { + qWarning() << "MonitorPanel has no model controller"; + return false; + } + + QList imageRefs = controller->getHMIimageRef(); + if (!imageRefs.isEmpty()) { + QUuid hmiId = imageRefs.first().hmiId; + if (!saveImageReferences(imageRefs, hmiId)) { + qWarning() << "Failed to save image references"; + return false; + } + } + + // 3. 保存自定义图片引用 + QList customImageRefs = controller->getHMICustomImageRef(); + if (!customImageRefs.isEmpty()) { + QUuid hmiId = customImageRefs.first().hmiId; + if (!saveCustomImageReferences(customImageRefs, hmiId)) { + qWarning() << "Failed to save custom image references"; + return false; + } + } + + // 4. 保存或更新HMI + QJsonObject diagramInfo = monitorPanel->getDiagramInfo(); + if (!saveOrUpdateHMI(entity, diagramInfo)) { + qWarning() << "Failed to save/update HMI"; + return false; + } + + // 5. 发送更新信号 + QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm"); + emit controller->HMIUpdated(entity->name(), QUuid(entity->id()), 1, timestamp); + + qDebug() << "HMI saved successfully:" << entity->name() << "at" << timestamp; + return true; +} + +bool DiagramCavasPrivate::saveHMIImages(QMap& imageMap) +{ + if (imageMap.isEmpty()) { + qDebug() << "No HMI images to save"; + return true; + } + + QList imageList = imageMap.values(); + bool success = DataBase::GetInstance()->insertHMIimagesWithCheck(imageList); + + if (success) { + qDebug() << "Saved" << imageList.size() << "HMI images"; + } else { + qWarning() << "Failed to save HMI images"; + } + + return success; +} + +bool DiagramCavasPrivate::saveImageReferences(const QList& imageRefs, const QUuid& hmiId) +{ + if (imageRefs.isEmpty() || hmiId.isNull()) { + return true; + } + + DataBase* db = DataBase::GetInstance(); + + // 检查是否已存在引用 + QList existingRefs = db->getHMIRefAll(hmiId); + if (!existingRefs.isEmpty()) { + // 删除旧的引用 + bool deleted = db->removeHMIRefAll(hmiId); + if (!deleted) { + qWarning() << "Failed to remove old image references for HMI:" << hmiId; + return false; + } + } + + // 插入新的引用 + bool inserted = db->insertHMIimageRefBatch(imageRefs); + + if (inserted) { + qDebug() << "Saved" << imageRefs.size() << "image references for HMI:" << hmiId; + } else { + qWarning() << "Failed to save image references for HMI:" << hmiId; + } + + return inserted; +} + +bool DiagramCavasPrivate::saveCustomImageReferences(const QList& customImageRefs, const QUuid& hmiId) +{ + if (customImageRefs.isEmpty() || hmiId.isNull()) { + return true; + } + + DataBase* db = DataBase::GetInstance(); + + // 检查是否已存在自定义引用 + QList existingRefs = db->getHMICustomRefAll(hmiId); + if (!existingRefs.isEmpty()) { + // 删除旧的引用 + bool deleted = db->removeHMICustomRefAll(hmiId); + if (!deleted) { + qWarning() << "Failed to remove old custom image references for HMI:" << hmiId; + return false; + } + } + + // 插入新的自定义引用 + bool inserted = db->insertHMICustomRefBatch(customImageRefs); + + if (inserted) { + qDebug() << "Saved" << customImageRefs.size() << "custom image references for HMI:" << hmiId; + } else { + qWarning() << "Failed to save custom image references for HMI:" << hmiId; + } + + return inserted; +} + +bool DiagramCavasPrivate::saveOrUpdateHMI(PowerEntity* entity, QJsonObject diagramInfo) +{ + if (!entity) { + return false; + } + + QString hmiName = entity->name(); + QUuid hmiUuid = QUuid(entity->id()); + QString hmiDesc = entity->name(); // 使用名称作为描述 + + DataBase* db = DataBase::GetInstance(); + + // 检查HMI是否已存在 + QUuid existingHmiId = db->getHMIdByName(hmiName); + + if (existingHmiId.isNull()) { + // 创建新的HMI + bool inserted = db->insertHMI(hmiUuid, hmiName, hmiDesc, diagramInfo); + if (inserted) { + qDebug() << "Created new HMI:" << hmiName << "ID:" << hmiUuid; + } + return inserted; + } else { + // 更新现有HMI + bool updated = db->updateHMI(hmiName, diagramInfo); + if (updated) { + qDebug() << "Updated existing HMI:" << hmiName; + } + return updated; + } +} + +MonitorPanel* DiagramCavasPrivate::getCurrentMonitorPanel() const +{ + BaseDrawingPanel* drawingPanel = getCurrentDrawingPanel(); + if (!drawingPanel) { + return nullptr; + } + + if (drawingPanel->getMode() == DM_run) { + return dynamic_cast(drawingPanel); + } + + return nullptr; +} + +BaseDrawingPanel* DiagramCavasPrivate::getCurrentDrawingPanel() const +{ + Q_Q(const DiagramCavas); + + QMdiSubWindow* currentSubWindow = q->currentSubWindow(); + if (!currentSubWindow) { + return nullptr; + } + + QWidget* windowWidget = currentSubWindow->widget(); + if (!windowWidget) { + return nullptr; + } + + return dynamic_cast(windowWidget); +} + +bool DiagramCavasPrivate::saveAllPages() +{ + if (m_mapMonitorPanel.isEmpty()) { + qDebug() << "No pages to save"; + return true; + } + + int successCount = 0; + int totalCount = 0; + + for (auto it = m_mapMonitorPanel.begin(); it != m_mapMonitorPanel.end(); ++it) { + MonitorPanel* panel = it.value().first; + if (panel && panel->getMode() == DM_run) { + totalCount++; + + if (saveMonitorPanel(panel)) { + successCount++; + m_modifiedPages.remove(it.key()); // 从修改列表中移除 + } + } + } + + qDebug() << "Saved" << successCount << "of" << totalCount << "pages"; + return successCount == totalCount; +} + +bool DiagramCavasPrivate::savePage(const QString& pageName) +{ + if (!hasPanel(pageName)) { + qWarning() << "Page not found:" << pageName; + return false; + } + + MonitorPanel* panel = getPanel(pageName); + if (!panel || panel->getMode() != DM_run) { + return false; + } + + bool success = saveMonitorPanel(panel); + if (success) { + m_modifiedPages.remove(pageName); + } + + return success; +} + +int DiagramCavasPrivate::saveModifiedPages() +{ + if (m_modifiedPages.isEmpty()) { + return 0; + } + + int savedCount = 0; + + for (const QString& pageName : m_modifiedPages) { + if (savePage(pageName)) { + savedCount++; + } + } + + m_modifiedPages.clear(); + return savedCount; +} + +void DiagramCavasPrivate::markPageModified(const QString& pageName, bool modified) +{ + if (modified) { + m_modifiedPages.insert(pageName); + } else { + m_modifiedPages.remove(pageName); + } +} + +bool DiagramCavasPrivate::isPageModified(const QString& pageName) const +{ + return m_modifiedPages.contains(pageName); +} + +QList DiagramCavasPrivate::getModifiedPages() const +{ + return m_modifiedPages.values(); +} + +void DiagramCavasPrivate::loadMonitorImpl(PowerEntity* p) +{ + if (!p) { + qWarning() << "Cannot load monitor: PowerEntity is null"; + return; + } + + QString monitorName = p->name(); + + if (!hasPanel(monitorName)) { + // 加载HMI上下文 + QJsonObject context = loadHMIContext(monitorName); + + if (createAndLoadMonitor(p, context)) { + qDebug() << "Monitor created and loaded:" << monitorName; + } else { + qWarning() << "Failed to create and load monitor:" << monitorName; + } + } else { + // 激活已存在的监控面板 + if (loadExistingMonitor(monitorName)) { + qDebug() << "Existing monitor activated:" << monitorName; + } else { + qWarning() << "Failed to activate existing monitor:" << monitorName; + } + } + + // 选中目标属性 + activateAndSelectMonitor(monitorName); +} + +bool DiagramCavasPrivate::createAndLoadMonitor(PowerEntity* p, const QJsonObject& context) +{ + Q_Q(DiagramCavas); + + // 1. 创建监控面板 + q->onSignal_addDrawingPanel(p, DiagramMode::DM_run); + + // 获取新创建的面板 + QString monitorName = p->name(); + if (!hasPanel(monitorName)) { + qWarning() << "Failed to create monitor panel:" << monitorName; + return false; + } + + MonitorPanel* panel = getPanel(monitorName); + QMdiSubWindow* subWindow = getSubWindow(monitorName); + + if (!panel || !subWindow) { + qWarning() << "Failed to get created monitor components:" << monitorName; + return false; + } + + // 2. 加载节点 + if (!context.isEmpty()) { + panel->loadNodes(context); + + // 3. 应用页面几何属性 + if (context.contains("pageAttr") && context["pageAttr"].isObject()) { + QJsonObject pageAttr = context["pageAttr"].toObject(); + applyPageGeometry(panel, subWindow, pageAttr); + } + } else { + qDebug() << "No context data for monitor, using default:" << monitorName; + } + + return true; +} + +bool DiagramCavasPrivate::loadExistingMonitor(const QString& name) +{ + if (!hasPanel(name)) { + return false; + } + + MonitorPanel* panel = getPanel(name); + QMdiSubWindow* subWindow = getSubWindow(name); + + if (!panel || !subWindow) { + return false; + } + + // 显示面板 + panel->show(); + + // 设置为活动子窗口 + Q_Q(DiagramCavas); + q->setActiveSubWindow(subWindow); + + return true; +} + +QJsonObject DiagramCavasPrivate::loadHMIContext(const QString& hmiName) +{ + if (hmiName.isEmpty()) { + return QJsonObject(); + } + + DataBase* db = DataBase::GetInstance(); + if (!db) { + qWarning() << "Database instance is null"; + return QJsonObject(); + } + + QJsonObject context = db->getHMIContextByTag(hmiName); + + if (context.isEmpty()) { + qDebug() << "No HMI context found for:" << hmiName; + } else { + qDebug() << "Loaded HMI context for:" << hmiName + << "keys:" << context.keys(); + } + + return context; +} + +void DiagramCavasPrivate::applyPageGeometry(MonitorPanel* panel, + QMdiSubWindow* subWindow, + const QJsonObject& pageAttr) +{ + if (!panel || !subWindow || pageAttr.isEmpty()) { + return; + } + + // 解析几何属性 + int x = pageAttr.value("x").toInt(); + int y = pageAttr.value("y").toInt(); + int width = pageAttr.value("width").toInt(); + int height = pageAttr.value("height").toInt(); + + // 验证几何属性 + if (width <= 0 || height <= 0) { + qDebug() << "Invalid geometry, using default:" + << "width =" << width << "height =" << height; + return; + } + + // 确保窗口在屏幕范围内 + QRect screenGeometry = QGuiApplication::primaryScreen()->geometry(); + + // 调整坐标和大小 + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x + width > screenGeometry.width()) { + width = qMin(width, screenGeometry.width() - x); + } + if (y + height > screenGeometry.height()) { + height = qMin(height, screenGeometry.height() - y); + } + + // 应用几何属性 + subWindow->setGeometry(x, y, width, height); + + qDebug() << "Applied page geometry:" + << "x =" << x << "y =" << y + << "width =" << width << "height =" << height; +} + +void DiagramCavasPrivate::activateAndSelectMonitor(const QString& name) +{ + if (!hasPanel(name)) { + return; + } + + MonitorPanel* panel = getPanel(name); + if (!panel) { + return; + } + + Q_Q(DiagramCavas); + + // 选中目标属性 + QObject* propertyProxy = panel->getPropertyProxy(); + if (propertyProxy) { + q->onTargetSelected(propertyProxy); + } else { + qWarning() << "No property proxy for monitor:" << name; + } +} + +void DiagramCavasPrivate::createHMIClickedImpl(const QString& sHMI, const QString& sStructPage, int modelType) +{ + if (sHMI.isEmpty() || sStructPage.isEmpty()) { + qWarning() << "Cannot create HMI: empty HMI name or structure page"; + return; + } + + Q_Q(DiagramCavas); + + // 1. 创建HMI图 + QUuid hmiId; + PowerEntity* entity = nullptr; + + if (!createHMIDiagram(sHMI, modelType, hmiId, entity)) { + qWarning() << "Failed to create HMI diagram:" << sHMI; + return; + } + + // 2. 添加绘图面板 + q->onSignal_addDrawingPanel(entity, DiagramMode::DM_run); + + // 3. 加载结构到面板 + if (!loadStructureToPanel(sHMI, sStructPage)) { + qWarning() << "Failed to load structure to panel:" << sHMI; + return; + } + + // 4. 发送创建HMI信号 + q->onSignal_createHMI(sHMI, hmiId); + + // 5. 选中目标属性 + if (hasPanel(sHMI)) { + MonitorPanel* panel = getPanel(sHMI); + if (panel) { + QObject* propertyProxy = panel->getPropertyProxy(); + if (propertyProxy) { + q->onTargetSelected(propertyProxy); + } + } + } + + qDebug() << "HMI created successfully:" + << "name =" << sHMI + << "id =" << hmiId + << "model type =" << modelType; +} + +bool DiagramCavasPrivate::createHMIDiagram(const QString& sHMI, int modelType, QUuid& outId, PowerEntity*& outEntity) +{ + // 生成UUID + outId = QUuid::createUuid(); + + // 创建拓扑图 + outEntity = TopologyManager::instance().createDiagram( + outId.toString(), + sHMI, + ModelFunctionType::RuntimeModel + ); + + if (!outEntity) { + qWarning() << "TopologyManager failed to create diagram:" << sHMI; + return false; + } + + qDebug() << "Diagram created:" + << "name =" << sHMI + << "id =" << outId.toString(); + + return true; +} + +bool DiagramCavasPrivate::loadStructureToPanel(const QString& panelName, const QString& sStructPage) +{ + if (!hasPanel(panelName)) { + qWarning() << "Panel not found:" << panelName; + return false; + } + + // 获取监控上下文 + QJsonObject context = DataBase::GetInstance()->getMonitorContextByTag(sStructPage); + + if (context.isEmpty()) { + qWarning() << "No monitor context found for structure page:" << sStructPage; + return false; + } + + // 获取面板 + MonitorPanel* panel = getPanel(panelName); + if (!panel) { + qWarning() << "Failed to get monitor panel:" << panelName; + return false; + } + + // 加载节点 + panel->loadNodes(context); + + qDebug() << "Structure loaded to panel:" + << panelName + << "context keys:" << context.keys(); + + return true; +} diff --git a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp index f4f537f..01dae43 100644 --- a/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp +++ b/diagramCavas/source/graphicsDataModel/fixedPortsModel.cpp @@ -74,13 +74,11 @@ FixedPortsModel::FixedPortsModel(PowerEntity* pEntity) loadNodeDataFromDataBase(); ProjectModelManager::instance().initialHMISourcr(); _Interface = new HttpInterface(this); - _timer = new QTimer(this); m_dataTimer = new QTimer(this); _modelStateInfo = DataManager::instance().modelState(); _modelDataInfo = DataManager::instance().modelData(); initialPropertyDlg(); - connect(_timer,SIGNAL(timeout()),this,SLOT(onTimeOut())); connect(m_dataTimer,&QTimer::timeout,this,&FixedPortsModel::onDataTimerOut); m_dataTimer->setInterval(2000); connect(_Interface,&HttpInterface::sendPointData,this,&FixedPortsModel::onSignal_GetPointData); @@ -1817,15 +1815,6 @@ void FixedPortsModel::onScriptExec(QString script) } -void FixedPortsModel::startHttpRequest() -{ - if(_timer) - { - _timer->setInterval(1000); - _timer->start(); - } -} - DiagramCavas* FixedPortsModel::getCavas() { if(_cavas)