// 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; }