diff --git a/Release/XNEditor b/Release/XNEditor
deleted file mode 100755
index e429bca..0000000
Binary files a/Release/XNEditor and /dev/null differ
diff --git a/Release/XNIDLGen b/Release/XNIDLGen
deleted file mode 100755
index 3d163e0..0000000
Binary files a/Release/XNIDLGen and /dev/null differ
diff --git a/Release/XNMonitor b/Release/XNMonitor
deleted file mode 100755
index 3d5fa65..0000000
Binary files a/Release/XNMonitor and /dev/null differ
diff --git a/Release/XNPortal b/Release/XNPortal
deleted file mode 100755
index f2dfeab..0000000
Binary files a/Release/XNPortal and /dev/null differ
diff --git a/Release/XNPortal.desktop b/Release/XNPortal.desktop
deleted file mode 100644
index ba2f5c9..0000000
--- a/Release/XNPortal.desktop
+++ /dev/null
@@ -1,8 +0,0 @@
-[Desktop Entry]
-Type=Application
-Exec=/media/jin/E/MyCode/xnsim/Release/XNPortal
-Name=XNPortal
-GenericName=XNPortal
-Icon=/media/jin/E/MyCode/xnsim/Release/resource/XNSim.png
-Terminal=false
-Categories=Development;
diff --git a/Release/XNRunner b/Release/XNRunner
deleted file mode 100755
index e82a78b..0000000
Binary files a/Release/XNRunner and /dev/null differ
diff --git a/Release/XNSetEnvironment.sh b/Release/XNSetEnvironment.sh
index c088ce4..d8028f0 100755
--- a/Release/XNSetEnvironment.sh
+++ b/Release/XNSetEnvironment.sh
@@ -11,8 +11,6 @@ fi
echo "export XNCore=${CURRENT_PATH}" >> "$CURRENT_PATH/shell/XNCore.sh"
echo "export PATH=\$XNCore:\$PATH" >> "$CURRENT_PATH/shell/XNCore.sh"
echo "export LD_LIBRARY_PATH=\$XNCore/lib:\$LD_LIBRARY_PATH" >> "$CURRENT_PATH/shell/XNCore.sh"
-echo "export QT_QPA_PLATFORM=xcb" >> "$CURRENT_PATH/shell/XNCore.sh"
-echo "export QT_PLUGIN_PATH=\$XNCore/platforms" >> "$CURRENT_PATH/shell/XNCore.sh"
chmod +x "$CURRENT_PATH/shell/XNCore.sh"
echo "$CURRENT_PATH/lib" >> "$CURRENT_PATH/shell/XNCore.conf"
echo "$CURRENT_PATH/Models" >> "$CURRENT_PATH/shell/XNCore.conf"
diff --git a/Release/XNSetIcon.sh b/Release/XNSetIcon.sh
index 5d0f7a7..efe43ec 100755
--- a/Release/XNSetIcon.sh
+++ b/Release/XNSetIcon.sh
@@ -1,11 +1,4 @@
#!/bin/bash
CURRENT_PATH=$(pwd)
-gio set -t string $CURRENT_PATH/XNPortal "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNSim.png"
gio set -t string $CURRENT_PATH/XNEngine "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNEngine.png"
-gio set -t string $CURRENT_PATH/XNEditor "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNEditor.png"
-gio set -t string $CURRENT_PATH/XNIDLGen "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNIDLGen.png"
-gio set -t string $CURRENT_PATH/XNMonitor "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNMonitor.png"
-gio set -t string $CURRENT_PATH/XNRunner "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNRunner.png"
-gio set -t string $CURRENT_PATH/XNSysMonitor "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNSysMonitor.png"
-gio set -t string $CURRENT_PATH/XNWrapper "metadata::custom-icon" "file://$CURRENT_PATH/resource/XNWrapper.png"
diff --git a/Release/XNSysMonitor b/Release/XNSysMonitor
deleted file mode 100755
index f2b0ae0..0000000
Binary files a/Release/XNSysMonitor and /dev/null differ
diff --git a/Release/XNWrapper b/Release/XNWrapper
deleted file mode 100755
index 157a9b5..0000000
Binary files a/Release/XNWrapper and /dev/null differ
diff --git a/Release/config/XNWrapper.xml b/Release/config/XNWrapper.xml
deleted file mode 100755
index 36c4716..0000000
--- a/Release/config/XNWrapper.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-1
diff --git a/Release/database/XNSim.db b/Release/database/XNSim.db
index d72255d..999b2e6 100644
Binary files a/Release/database/XNSim.db and b/Release/database/XNSim.db differ
diff --git a/Release/resource/XNEditor.png b/Release/resource/XNEditor.png
deleted file mode 100755
index f7d8397..0000000
Binary files a/Release/resource/XNEditor.png and /dev/null differ
diff --git a/Release/resource/XNIDLGen.png b/Release/resource/XNIDLGen.png
deleted file mode 100755
index b5602b7..0000000
Binary files a/Release/resource/XNIDLGen.png and /dev/null differ
diff --git a/Release/resource/XNMonitor.png b/Release/resource/XNMonitor.png
deleted file mode 100755
index c229c77..0000000
Binary files a/Release/resource/XNMonitor.png and /dev/null differ
diff --git a/Release/resource/XNRunner.png b/Release/resource/XNRunner.png
deleted file mode 100755
index 741ee8e..0000000
Binary files a/Release/resource/XNRunner.png and /dev/null differ
diff --git a/Release/resource/XNSim.png b/Release/resource/XNSim.png
deleted file mode 100755
index 92c5fbc..0000000
Binary files a/Release/resource/XNSim.png and /dev/null differ
diff --git a/Release/resource/XNSysMonitor.png b/Release/resource/XNSysMonitor.png
deleted file mode 100755
index 99515b0..0000000
Binary files a/Release/resource/XNSysMonitor.png and /dev/null differ
diff --git a/Release/resource/XNWrapper.png b/Release/resource/XNWrapper.png
deleted file mode 100755
index 2c85ee4..0000000
Binary files a/Release/resource/XNWrapper.png and /dev/null differ
diff --git a/XNEditor/.vscode/c_cpp_properties.json b/XNEditor/.vscode/c_cpp_properties.json
deleted file mode 100755
index 0b3cbd5..0000000
--- a/XNEditor/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "configurations": [
- {
- "compileCommands": "${workspaceFolder}/build/compile_commands.json",
- "configurationProvider": "ms-vscode.cmake-tools"
- }
- ],
- "version": 4
-}
\ No newline at end of file
diff --git a/XNEditor/.vscode/settings.json b/XNEditor/.vscode/settings.json
deleted file mode 100755
index 69b7356..0000000
--- a/XNEditor/.vscode/settings.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "files.associations": {
- "*.cpp": "cpp",
- "qhboxlayout": "cpp",
- "deque": "cpp",
- "list": "cpp",
- "string": "cpp",
- "vector": "cpp",
- "qtextstream": "cpp",
- "qxmlstreamattributes": "cpp"
- }
-}
\ No newline at end of file
diff --git a/XNEditor/CMakeLists.txt b/XNEditor/CMakeLists.txt
deleted file mode 100755
index c96a0e6..0000000
--- a/XNEditor/CMakeLists.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-project(XNEditor VERSION 0.1 LANGUAGES CXX)
-
-set(CMAKE_AUTOUIC ON)
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Xml)
-find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Xml)
-
-set(QT_SOURCE_FILE ../qdarkstyle/dark/darkstyle.qrc)
-
-# 根据 Qt 版本选择正确的资源添加函数
-qt6_add_resources(QT_RESOURCES ${QT_SOURCE_FILE})
-
-set(PROJECT_SOURCES
- main.cpp
- mainwindow.cpp
- mainwindow.h
- mainwindow.ui
- ${QT_RESOURCES}
-)
-
-if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
- qt_add_executable(XNEditor
- MANUAL_FINALIZATION
- ${PROJECT_SOURCES}
- )
-# Define target properties for Android with Qt 6 as:
-# set_property(TARGET XNEditor APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
-# ${CMAKE_CURRENT_SOURCE_DIR}/android)
-# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
-else()
- if(ANDROID)
- add_library(XNEditor SHARED
- ${PROJECT_SOURCES}
- )
-# Define properties for Android with Qt 5 after find_package() calls as:
-# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
- else()
- add_executable(XNEditor
- ${PROJECT_SOURCES}
- )
- endif()
-endif()
-
-target_link_libraries(XNEditor PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Xml)
-
-# Check if CMAKE_INSTALL_PREFIX is set to its default value
-if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/../Release" CACHE PATH "Install path prefix" FORCE)
-endif()
-
-include(GNUInstallDirs)
-install(TARGETS XNEditor
- BUNDLE DESTINATION .
- LIBRARY DESTINATION .
- RUNTIME DESTINATION .
-)
-
-# Add a post-installation command to set the application icon using gio
-install(CODE "
- execute_process(COMMAND gio set -t string ${CMAKE_INSTALL_PREFIX}/XNEditor \"metadata::custom-icon\" \"file://${CMAKE_INSTALL_PREFIX}/resource/XNEditor.png\")
-")
-
-if(QT_VERSION_MAJOR EQUAL 6)
- qt_finalize_executable(XNEditor)
-endif()
diff --git a/XNEditor/CMakeLists.txt.user b/XNEditor/CMakeLists.txt.user
deleted file mode 100755
index 18e9dc3..0000000
--- a/XNEditor/CMakeLists.txt.user
+++ /dev/null
@@ -1,423 +0,0 @@
-
-
-
-
-
- EnvironmentId
- {c0015c8c-17e0-44a4-897e-eb0bda6a867e}
-
-
- ProjectExplorer.Project.ActiveTarget
- 0
-
-
- ProjectExplorer.Project.EditorSettings
-
- true
- false
- true
-
- Cpp
-
- CppGlobal
-
-
-
- QmlJS
-
- QmlJSGlobal
-
-
- 2
- UTF-8
- false
- 4
- false
- 80
- true
- true
- 1
- 0
- false
- true
- false
- 2
- true
- true
- 0
- 8
- true
- false
- 1
- true
- true
- true
- *.md, *.MD, Makefile
- false
- true
- true
-
-
-
- ProjectExplorer.Project.PluginSettings
-
-
- true
- false
- true
- true
- true
- true
-
- false
-
-
- 0
- true
-
- true
- true
- Builtin.DefaultTidyAndClazy
- 10
- true
-
-
-
- true
-
-
-
-
- ProjectExplorer.Project.Target.0
-
- Desktop
- Desktop Qt 6.5.3 MinGW 64-bit
- Desktop Qt 6.5.3 MinGW 64-bit
- qt.qt6.653.win64_mingw_kit
- 0
- 0
- 0
-
- Debug
- 2
- false
-
- -DCMAKE_BUILD_TYPE:STRING=Debug
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- 0
- I:\MyPrj\XNSim\XNEditor\build\Desktop_Qt_6_5_3_MinGW_64_bit-Debug
-
-
-
-
- all
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Debug
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- Release
- 2
- false
-
- -DCMAKE_BUILD_TYPE:STRING=Release
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- I:\MyPrj\XNSim\XNEditor\build\Desktop_Qt_6_5_3_MinGW_64_bit-Release
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- I:\MyPrj\XNSim\XNEditor\build\Desktop_Qt_6_5_3_MinGW_64_bit-RelWithDebInfo
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release with Debug Information
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- 0
- I:\MyPrj\XNSim\XNEditor\build\Desktop_Qt_6_5_3_MinGW_64_bit-Profile
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Profile
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- MinSizeRel
- 2
- false
-
- -DCMAKE_BUILD_TYPE:STRING=MinSizeRel
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- I:\MyPrj\XNSim\XNEditor\build\Desktop_Qt_6_5_3_MinGW_64_bit-MinSizeRel
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Minimum Size Release
- CMakeProjectManager.CMakeBuildConfiguration
-
- 5
-
-
- 0
- 部署
- 部署
- ProjectExplorer.BuildSteps.Deploy
-
- 1
-
- false
- ProjectExplorer.DefaultDeployConfiguration
-
- 1
-
- true
- true
- 0
- true
-
-
- 2
-
- false
- -e cpu-cycles --call-graph "dwarf,4096" -F 250
- XNEditor
- CMakeProjectManager.CMakeRunConfiguration.XNEditor
- XNEditor
- false
- true
- true
- true
- I:/MyPrj/XNSim/XNEditor/build/Desktop_Qt_6_5_3_MinGW_64_bit-Debug
-
- 1
-
-
-
- ProjectExplorer.Project.TargetCount
- 1
-
-
- ProjectExplorer.Project.Updater.FileVersion
- 22
-
-
- Version
- 22
-
-
diff --git a/XNEditor/main.cpp b/XNEditor/main.cpp
deleted file mode 100755
index 6d3b499..0000000
--- a/XNEditor/main.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file main.cpp
- * @author jinchao
- * @brief 主函数
- * @version 1.0
- * @date 2025-02-14
- *
- * @copyright Copyright (c) 2025 COMAC
- *
- */
-
-#include "mainwindow.h"
-
-#include
-#include
-#include
-
-/**
- * @brief 主函数
- * @param argc 参数个数
- * @param argv 参数列表
- * @return 返回值
- */
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
- // 设置主题
- QFile file(":qdarkstyle/dark/darkstyle.qss");
- if (file.open(QFile::ReadOnly)) {
- QTextStream stream(&file);
- QString styleSheet = stream.readAll();
- a.setStyleSheet(styleSheet);
- }
- // 创建主窗口
- MainWindow w;
- // 显示主窗口
- w.show();
- // 执行应用程序
- return a.exec();
-}
diff --git a/XNEditor/mainwindow.cpp b/XNEditor/mainwindow.cpp
deleted file mode 100755
index 232f09c..0000000
--- a/XNEditor/mainwindow.cpp
+++ /dev/null
@@ -1,2225 +0,0 @@
-/**
- * @file mainwindow.cpp
- * @author jinchao
- * @brief 主窗口类实现
- * @version 1.0
- * @date 2025-02-14
- *
- * @copyright Copyright (c) 2025 COMAC
- *
- */
-#include "mainwindow.h"
-#include "./ui_mainwindow.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-//构造函数
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
- isModified = false; // 初始化
-
- // 设置窗口标题
- setWindowTitle("XNEditor");
- // 设置窗口图标
- setWindowIcon(QIcon(":/icon/XNEditor.png"));
-
- // 设置窗口大小
- resize(700, 1000);
-
- // 初始化菜单栏
- initMenu();
-
- //初始化中央控件
- initCentralWidget(0);
-}
-
-// 构造函数
-MainWindow::MainWindow(QString fileName, QWidget *parent)
- : QMainWindow(parent), ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
-
- // 设置窗口标题
- setWindowTitle("XNEditor");
- // 设置窗口图标
- setWindowIcon(QIcon(":/icon/XNEditor.png"));
-
- // 设置窗口大小
- resize(500, 1000);
-
- // 初始化菜单栏
- initMenu();
-
- // 设置当前文件路径
- currentFilePath = fileName;
- isModified = false;
-
- // 根据文件类型初始化中央控件
- if (currentFilePath.endsWith(".mcfg")) { // 模型配置文件
- initCentralWidget(1);
- currentFileType = 1;
- // 打开模型配置文件
- openModelFile();
- } else if (currentFilePath.endsWith(".scfg")) { // 服务配置文件
- initCentralWidget(1);
- currentFileType = 2;
- // 打开服务配置文件
- openServiceFile();
- } else if (currentFilePath.endsWith(".idl")) { // IDL文件
- initCentralWidget(2);
- currentFileType = 3;
- // 打开IDL文件
- openIDLFile();
- }
-}
-
-// 析构函数
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-// 初始化菜单栏
-void MainWindow::initMenu()
-{
- // 初始化文件菜单
- initFileMenu();
- //初始化编辑菜单
- initEditMenu();
-}
-
-// 初始化文件菜单
-void MainWindow::initFileMenu()
-{
- // 获取菜单栏
- QMenuBar *menuBar = ui->menubar;
-
- // 设置菜单
- QMenu *fileMenu = new QMenu("&File", this);
- menuBar->addMenu(fileMenu);
-
- // New菜单项
- QAction *newAction = new QAction("&New Scenario", this);
- fileMenu->addAction(newAction);
- newAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N));
- connect(newAction, &QAction::triggered, this, &MainWindow::onNewFileTriggered);
-
- // 添加分隔
- fileMenu->addSeparator();
-
- // Open菜单项
- QAction *openAction = new QAction("&Open", this);
- openAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_O));
- fileMenu->addAction(openAction);
- connect(openAction, &QAction::triggered, this, &MainWindow::onOpenFileTriggered);
-
- // 添加分隔
- fileMenu->addSeparator();
-
- // Save菜单项
- QAction *saveAction = new QAction("&Save", this);
- fileMenu->addAction(saveAction);
- saveAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_S));
- connect(saveAction, &QAction::triggered, [this]() {
- if (currentFilePath.isEmpty()) {
- return;
- }
- //保存文件
- saveFile(currentFilePath);
- });
-
- //Save As 菜单项
- QAction *saveAsAction = new QAction("Save As...", this);
- fileMenu->addAction(saveAsAction);
- saveAsAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_S));
- connect(saveAsAction, &QAction::triggered, [this]() {
- // 打开选择保存路径对话框
- QString filePath = QFileDialog::getSaveFileName(
- this, tr("Save As"), "", tr("Scenario Files (*.sce);;All Files (*)"));
- if (!filePath.isEmpty()) {
- currentFilePath = filePath;
- //保存文件
- saveFile(filePath);
- }
- });
-
- // 添加分隔
- fileMenu->addSeparator();
-
- // Close 菜单项
- QAction *closeAction = new QAction("&Close File", this);
- fileMenu->addAction(closeAction);
- closeAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_W));
- connect(closeAction, &QAction::triggered, this, &MainWindow::onCloseFileTriggered);
-
- // 添加分隔
- fileMenu->addSeparator();
-
- // Exit 菜单项
- QAction *exitAction = new QAction("&Exit", this);
- fileMenu->addAction(exitAction);
- exitAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q));
- connect(exitAction, &QAction::triggered, [this]() { close(); });
-}
-
-// 初始化编辑菜单
-void MainWindow::initEditMenu()
-{
- // 获取菜单栏
- QMenuBar *menuBar = ui->menubar;
- //TODO 添加编辑相关菜单项
-}
-
-// 初始化中心组件
-void MainWindow::initCentralWidget(int style)
-{
- // 清理旧中心组件
- QWidget *oldCentralWidget = centralWidget();
- if (oldCentralWidget) {
- delete oldCentralWidget;
- }
-
- // 新建新中心组件
- QWidget *centralWidget = new QWidget(this);
- setCentralWidget(centralWidget);
-
- // 中心组件水平布局
- QHBoxLayout *layout = new QHBoxLayout(centralWidget);
-
- if (style == 0) { //如果是运行环境配置文件类型
- // 创建一个水平分割器
- QSplitter *splitter = new QSplitter(Qt::Horizontal, centralWidget);
- splitter->setObjectName("splitter");
- layout->addWidget(splitter);
-
- // 创建左边窗口
- QWidget *leftWidget = new QWidget(splitter);
- leftWidget->setObjectName("leftWidget");
- //左侧窗口垂直布局
- QVBoxLayout *leftLayout = new QVBoxLayout(leftWidget);
- // 创建模型配置文件树型控件
- QTreeWidget *ModelWidget = new QTreeWidget(leftWidget);
- ModelWidget->setObjectName("ModelWidget");
- ModelWidget->setHeaderLabels(QStringList() << "Models");
- leftLayout->addWidget(ModelWidget);
- // 创建服务配置文件树型控件
- QTreeWidget *ServiceWidget = new QTreeWidget(leftWidget);
- ServiceWidget->setObjectName("ServiceWidget");
- ServiceWidget->setHeaderLabels(QStringList() << "Services");
- leftLayout->addWidget(ServiceWidget);
- // 为模型配置文件树型控件添加右键菜单
- ModelWidget->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(ModelWidget, &QTreeWidget::customContextMenuRequested, this,
- [=](const QPoint &pos) {
- //获取点击右键时选中的元素
- QTreeWidgetItem *item = ModelWidget->itemAt(pos);
- if (item) {
- //新建右键菜单
- QMenu contextMenu;
- //添加在新窗口打开的选项
- QAction *openAction = new QAction("Open in New Window", this);
- contextMenu.addAction(openAction);
- // 链接打开选项的槽
- connect(openAction, &QAction::triggered, this, [this, item]() {
- //获取选中元素的文件名
- QString fileName = modelPath + "/" + item->text(0);
- //在新窗口打开文件
- openFileInNewWindow(fileName);
- });
- //显示右键菜单
- contextMenu.exec(ModelWidget->mapToGlobal(pos));
- }
- });
-
- // 为服务配置文件树型控件添加右键菜单
- ServiceWidget->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(ServiceWidget, &QTreeWidget::customContextMenuRequested, this,
- [=](const QPoint &pos) {
- //获取点击右键时选中的元素
- QTreeWidgetItem *item = ServiceWidget->itemAt(pos);
- if (item) {
- //新建右键菜单
- QMenu contextMenu;
- //添加在新窗口打开的选项
- QAction *openAction = new QAction("Open in New Window", this);
- contextMenu.addAction(openAction);
- // 链接打开选项的槽
- connect(openAction, &QAction::triggered, this, [this, item]() {
- //获取选中元素的文件名
- QString fileName = ServicePath + "/" + item->text(0);
- //在新窗口打开文件
- openFileInNewWindow(fileName);
- });
- //显示右键菜单
- contextMenu.exec(ServiceWidget->mapToGlobal(pos));
- }
- });
-
- // 将左边窗口添加到分割器
- splitter->addWidget(leftWidget);
-
- // 创建右边窗口
- QWidget *rightWidget = new QWidget(splitter);
- rightWidget->setObjectName("rightWidget");
- //右侧窗口垂直布局
- QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
- rightLayout->setObjectName("rightLayout");
-
- // 将右边窗口添加到分割器
- splitter->addWidget(rightWidget);
-
- // 设置分割器两侧大小
- splitter->setSizes({200, 400});
- } else if (style == 1) { //如果是模型/服务配置文件类型
- // 创建右边窗口
- QWidget *rightWidget = new QWidget(centralWidget);
- rightWidget->setObjectName("rightWidget");
- //右侧窗口垂直布局
- QVBoxLayout *rightLayout = new QVBoxLayout(rightWidget);
- rightLayout->setObjectName("rightLayout");
-
- layout->addWidget(rightWidget);
- } else if (style == 2) { //如果是IDL文件类型
- // 创建一个水平分割器
- QSplitter *splitter = new QSplitter(Qt::Horizontal, centralWidget);
- splitter->setObjectName("splitter");
- layout->addWidget(splitter);
-
- // 创建左边窗口,为树型控件,显示IDL结构
- QTreeWidget *leftWidget = new QTreeWidget(splitter);
- leftWidget->setObjectName("leftWidget");
- // 初始化该树型控件
- initIDLTreeWidget();
- // 将左边窗口添加到分割器
- splitter->addWidget(leftWidget);
-
- // 创建右边窗口,为表格控件,显示结构体内容
- QTableWidget *rightWidget = new QTableWidget(splitter);
- rightWidget->setObjectName("rightWidget");
- // 设置表格为4列
- rightWidget->setColumnCount(4);
- // 设置列标题
- QStringList headers;
- headers << "Name" << "Type" << "Size" << "Description";
- rightWidget->setHorizontalHeaderLabels(headers);
- // 设置表格只能单选
- rightWidget->setSelectionMode(QAbstractItemView::SingleSelection);
- // 设置表头自动伸缩
- rightWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
-
- // 将右边窗口添加到分割器
- splitter->addWidget(rightWidget);
-
- // 设置分割器两侧大小
- splitter->setSizes({200, 400}); // Adjust these values as needed
- }
-}
-
-// 初始化IDL文件结构窗口
-void MainWindow::initIDLTreeWidget()
-{
- // 获取左边窗口
- QTreeWidget *leftWidget = findChild("leftWidget");
- if (leftWidget) {
- // 设置右键菜单策略
- leftWidget->setContextMenuPolicy(Qt::CustomContextMenu);
-
- // 连接右键菜单信号
- connect(
- leftWidget, &QTreeWidget::customContextMenuRequested, this,
- [this, leftWidget](const QPoint &pos) {
- // 获取点击右键时选择的元素
- QTreeWidgetItem *item = leftWidget->itemAt(pos);
- QMenu contextMenu;
- if (!item) { // 在空白处右键,只能添加顶层namespace
- // 新建添加namespace的选项
- QAction *addNamespaceAction = new QAction("Add Module", this);
- // 链接添加namespace的槽
- connect(addNamespaceAction, &QAction::triggered, [this, leftWidget]() {
- bool ok;
- QString name;
- do {
- // 打开输入namespace名称的对话框
- name = QInputDialog::getText(
- this, tr("Add Module"),
- tr("Module name (must be a valid C++ identifier):"),
- QLineEdit::Normal, "", &ok);
-
- if (!ok)
- return; // 用户点击取消
-
- // 只能输入c++标准的类名
- QRegularExpression regex("^[A-Za-z_][A-Za-z0-9_]*$");
- if (!regex.match(name).hasMatch()) {
- // 如果输入的名称不符合c++标准的类名,则提示错误
- QMessageBox::warning(
- this, tr("Invalid Name"),
- tr("Module name must start with a letter or underscore and "
- "contain only letters, numbers and underscores."));
- ok = false;
- }
- } while (!ok || name.isEmpty());
- // 新建一个namespace
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList() << name);
- // 将namespace添加到树型控件
- leftWidget->addTopLevelItem(newItem);
- // 将namespace添加到存储好的结构中
- NamespaceDefinition newNamespace;
- newNamespace.namespaceName = name;
- namespaces.push_back(QSharedPointer(&newNamespace));
- // 设置修改状态
- isModified = true;
- // 更新窗口标题
- updateWindowTitle();
- });
- contextMenu.addAction(addNamespaceAction);
- } else { //如果不是空白处
- //计算在第几层
- int level = 0;
- QTreeWidgetItem *parent = item;
- while (parent->parent()) {
- parent = parent->parent();
- level++;
- }
-
- if (level < 2) { // 第一层或第二层可以添加module和struct
- // 新建添加module的选项
- QAction *addNamespaceAction = new QAction("Add Module", this);
- // 链接添加module的槽
- connect(addNamespaceAction, &QAction::triggered, [this, item]() {
- bool ok;
- QString name;
- do {
- // 打开输入namespace名称的对话框
- name = QInputDialog::getText(
- this, tr("Add Module"),
- tr("Module name (must be a valid C++ identifier):"),
- QLineEdit::Normal, "", &ok);
-
- if (!ok)
- return; // 用户点击取消
- // 只能输入c++标准的类名
- QRegularExpression regex("^[A-Za-z_][A-Za-z0-9_]*$");
- if (!regex.match(name).hasMatch()) {
- QMessageBox::warning(
- this, tr("Invalid Name"),
- tr("Module name must start with a letter or underscore and "
- "contain only letters, numbers and underscores."));
- ok = false;
- }
- } while (!ok || name.isEmpty());
- // 将namespace添加为该元素的子元素
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList() << name);
- item->addChild(newItem);
- item->setExpanded(true);
- isModified = true;
- updateWindowTitle();
- });
- contextMenu.addAction(addNamespaceAction);
- // 新建添加Struct的选项
- QAction *addStructAction = new QAction("Add Struct", this);
- // 链接添加Struct的槽
- connect(addStructAction, &QAction::triggered, [this, item]() {
- bool ok;
- QString name;
- do {
- // 打开输入Struct名称的对话框
- name = QInputDialog::getText(
- this, tr("Add Struct"),
- tr("Struct name (must be a valid C++ identifier):"),
- QLineEdit::Normal, "", &ok);
-
- if (!ok)
- return; // 用户点击取消
- // 只能输入c++标准的类名
- QRegularExpression regex("^[A-Za-z_][A-Za-z0-9_]*$");
- if (!regex.match(name).hasMatch()) {
- QMessageBox::warning(
- this, tr("Invalid Name"),
- tr("Struct name must start with a letter or underscore and "
- "contain only letters, numbers and underscores."));
- ok = false;
- }
- } while (!ok || name.isEmpty());
- // 新建一个Struct
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList() << name);
- // 将Struct添加为该元素的子元素
- item->addChild(newItem);
- item->setExpanded(true);
- // 设置修改状态
- isModified = true;
- // 更新窗口标题
- updateWindowTitle();
- });
- contextMenu.addAction(addStructAction);
- } else if (level == 2) { // 第三层只能添加struct
- // 新建添加Struct的选项
- QAction *addStructAction = new QAction("Add Struct", this);
- // 链接添加Struct的槽
- connect(addStructAction, &QAction::triggered, [this, item]() {
- bool ok;
- QString name;
- do {
- // 打开输入Struct名称的对话框
- name = QInputDialog::getText(
- this, tr("Add Struct"),
- tr("Struct name (must be a valid C++ identifier):"),
- QLineEdit::Normal, "", &ok);
-
- if (!ok)
- return; // 用户点击取消
- // 只能输入c++标准的类名
- QRegularExpression regex("^[A-Za-z_][A-Za-z0-9_]*$");
- if (!regex.match(name).hasMatch()) {
- QMessageBox::warning(
- this, tr("Invalid Name"),
- tr("Struct name must start with a letter or underscore and "
- "contain only letters, numbers and underscores."));
- ok = false;
- }
- } while (!ok || name.isEmpty());
- // 新建一个Struct
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList() << name);
- // 将Struct添加为该元素的子元素
- item->addChild(newItem);
- item->setExpanded(true);
- // 设置修改状态
- isModified = true;
- // 更新窗口标题
- updateWindowTitle();
- });
- contextMenu.addAction(addStructAction);
- }
-
- // 所有层级都可以删除
- contextMenu.addSeparator();
- QAction *deleteAction = new QAction("Delete", this);
- connect(deleteAction, &QAction::triggered, [this, item]() {
- delete item;
- isModified = true;
- updateWindowTitle();
- });
- contextMenu.addAction(deleteAction);
- }
-
- if (!contextMenu.actions().isEmpty()) {
- contextMenu.exec(leftWidget->mapToGlobal(pos));
- }
- });
- }
-}
-
-// 新建文件
-void MainWindow::onNewFileTriggered()
-{
- // 如果文件被修改,则先关闭文件
- if (isModified) {
- // 关闭文件
- onCloseFileTriggered();
- }
- // 打开新建环境配置文件对话框
- QString filePath = QFileDialog::getSaveFileName(this, tr("New Scenario"), "",
- tr("Scenario Files (*.sce);;All Files (*)"));
- // 如果文件路径不为空
- if (!filePath.isEmpty()) {
- // 打开模板文件
- QFile templateFile("template/Template.sce.tmp");
- // 如果模板文件存在
- if (templateFile.exists()) {
- // 打开模板文件
- if (templateFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QFile newFile(filePath);
- if (newFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
- // 读取模板文件
- QTextStream in(&templateFile);
- // 写入新文件
- QTextStream out(&newFile);
- out << in.readAll();
- // 关闭模板文件
- templateFile.close();
- // 关闭新文件
- newFile.close();
- // 设置当前文件路径
- currentFilePath = filePath;
- // 设置当前文件类型
- currentFileType = 0;
- // 打开环境配置文件
- openScenarioFile();
- } else {
- // 如果新建文件失败,则提示错误
- QMessageBox::warning(this, tr("Error"),
- tr("Failed to create new scenario file."));
- }
- } else {
- // 如果打开模板文件失败,则提示错误
- QMessageBox::warning(this, tr("Error"), tr("Failed to open template file."));
- }
- } else {
- // 如果模板文件不存在,则提示错误
- QMessageBox::warning(this, tr("Error"), tr("Template file does not exist."));
- }
- }
-}
-
-// 打开文件
-void MainWindow::onOpenFileTriggered()
-{
- // 如果文件被修改,则先关闭文件
- if (isModified) {
- // 关闭文件
- onCloseFileTriggered();
- }
- // 打开打开文件对话框
- QString filePath = QFileDialog::getOpenFileName(
- this, tr("Open File"), "",
- tr("All Supported Files (*.sce *.xml *.mcfg *.scfg *.idl);;All Files (*)"));
- // 如果文件路径不为空
- if (!filePath.isEmpty()) {
- // 设置当前文件路径
- currentFilePath = filePath;
- if (filePath.endsWith(".idl")) { //如果是IDL文件
- currentFileType = 3;
- // 重新初始化布局
- initCentralWidget(2);
- // 打开IDL文件
- openIDLFile();
- return;
- }
- // 打开文件
- QFile file(filePath);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- // 读取文件
- QXmlStreamReader xmlReader(&file);
- while (!xmlReader.atEnd() && !xmlReader.hasError()) {
- // 读取下一个元素
- QXmlStreamReader::TokenType token = xmlReader.readNext();
- if (token == QXmlStreamReader::StartElement) {
- // 获取元素名称
- QString rootElement = xmlReader.name().toString();
- if (rootElement == "Scenario") { //如果是环境配置文件
- currentFileType = 0;
- resize(700, 1000);
- initCentralWidget(0); // 重新初始化布局
- file.close();
- // 打开环境配置文件
- openScenarioFile();
- return;
- } else if (rootElement == "Model") { //如果是模型文件
- currentFileType = 1;
- resize(500, 1000);
- initCentralWidget(1); // 重新初始化布局
- file.close();
- // 打开模型文件
- openModelFile();
- return;
- } else if (rootElement == "Service") { //如果是服务文件
- currentFileType = 2;
- resize(500, 1000);
- initCentralWidget(1); // 重新初始化布局
- file.close();
- // 打开服务文件
- openServiceFile();
- return;
- }
- break;
- }
- }
- file.close();
- } else {
- // 如果打开文件失败,则提示错误
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file."));
- }
- }
-}
-
-// 关闭文件
-void MainWindow::onCloseFileTriggered()
-{
- if (isModified) { // 只在文件被修改时提示保存
- // 提示保存
- QMessageBox::StandardButton reply;
- reply = QMessageBox::question(this, tr("Save Changes"),
- tr("Do you want to save changes to the current file?"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
- if (reply == QMessageBox::Yes) { // 如果选择保存
- if (currentFilePath.isEmpty()) { // 如果当前文件路径为空
- // 打开保存文件对话框
- QString filePath =
- QFileDialog::getSaveFileName(this, tr("Save As"), "", tr("All Files (*)"));
- if (!filePath.isEmpty()) { // 如果文件路径不为空
- // 保存文件
- saveFile(filePath);
- }
- } else {
- // 保存文件
- saveFile(currentFilePath);
- }
- } else if (reply == QMessageBox::Cancel) { // 如果选择取消
- return;
- }
- }
- // 清除内容
- QTreeWidget *ModelWidget = findChild("ModelWidget");
- if (ModelWidget) {
- ModelWidget->clear();
- }
- QTreeWidget *ServiceWidget = findChild("ServiceWidget");
- if (ServiceWidget) {
- ServiceWidget->clear();
- }
- QVBoxLayout *layout = findChild("rightLayout");
- if (layout) {
- QLayoutItem *child;
- while ((child = layout->takeAt(0)) != nullptr) {
- if (child->widget()) {
- child->widget()->setParent(nullptr);
- }
- delete child;
- }
- }
- isModified = false; // 重置修改状态
- currentFilePath = "";
- currentFileType = 0;
- // 更新窗口标题
- updateWindowTitle();
-}
-
-// 打开场景配置文件
-void MainWindow::openScenarioFile()
-{
- // 获取右布局
- QVBoxLayout *layout = findChild("rightLayout");
- if (!layout) {
- QMessageBox::warning(this, tr("Error"), tr("Software error."));
- return;
- }
-
- // 打开文件
- QFile file(currentFilePath);
- if (!file.open(QIODevice::ReadOnly)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file."));
- return;
- }
-
- // 创建DOM文档
- QDomDocument doc;
- if (!doc.setContent(&file)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to parse scenario file."));
- file.close();
- return;
- }
-
- // 重置模型路径和服务路径
- modelPath = "";
- ServicePath = "";
-
- // 获取根元素
- QDomElement root = doc.documentElement();
- if (root.tagName() == "Scenario") {
- // 遍历子元素
- QDomNode node = root.firstChild();
- while (!node.isNull()) {
- QDomElement element = node.toElement();
- if (!element.isNull()) {
- QString elementName = element.tagName();
- if (elementName == "Environment") {
- QDomNamedNodeMap elementAttributes = element.attributes();
- addGroupBox(layout, elementName, elementAttributes);
- } else if (elementName == "ConsoleOutput" || elementName == "Log") {
- // 添加控制台输出/日志组框
- QDomNamedNodeMap elementAttributes = element.attributes();
- addGroupBox2(layout, elementName, elementAttributes);
- } else if (elementName == "ModelGroup") {
- QDomNamedNodeMap elementAttributes = element.attributes();
- // 处理模型列表
- QVector modelList;
- QDomNodeList models = element.elementsByTagName("Model");
-
- for (int i = 0; i < models.count(); i++) {
- QDomElement modelElement = models.at(i).toElement();
- QDomNamedNodeMap attributes = modelElement.attributes();
-
- modelList.append(attributes);
- }
-
- // 添加模型列表组框
- addGroupBox3(layout, elementName, elementAttributes, modelList, 0);
-
- } else if (elementName == "ServicesList") {
- QDomNamedNodeMap elementAttributes = element.attributes();
- // 处理服务列表
- QVector serviceList;
- QDomNodeList services = element.elementsByTagName("Service");
-
- for (int i = 0; i < services.count(); i++) {
- QDomElement serviceElement = services.at(i).toElement();
- QDomNamedNodeMap attributes = serviceElement.attributes();
-
- serviceList.append(attributes);
- }
-
- // 添加服务列表组框
- addGroupBox3(layout, elementName, elementAttributes, serviceList, 1);
- }
- }
- node = node.nextSibling();
- }
-
- // // 更新模型和服务列表
- // QTableWidget *modelsTable = findChild();
- // if (modelsTable) {
- // UpdateModelList(modelsTable);
- // }
- // QTableWidget *servicesTable = findChild();
- // if (servicesTable) {
- // UpdateServiceList(servicesTable);
- // }
-
- updateWindowTitle();
- }
- file.close();
-}
-
-// 打开模型文件
-void MainWindow::openModelFile()
-{
- // 获取右布局
- QVBoxLayout *layout = findChild("rightLayout");
- if (!layout) {
- QMessageBox::warning(this, tr("Error"), tr("Software error."));
- return;
- }
-
- // 打开文件
- QFile file(currentFilePath);
- if (!file.open(QIODevice::ReadOnly)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file."));
- return;
- }
-
- // 创建DOM文档
- QDomDocument doc;
- if (!doc.setContent(&file)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to parse model config file."));
- file.close();
- return;
- }
-
- // 获取根元素
- QDomElement root = doc.documentElement();
- if (root.tagName() == "Model") {
- // 添加组框
- QGroupBox *groupBox = new QGroupBox("Model Info", this);
- groupBox->setObjectName("Model Info");
- layout->addWidget(groupBox);
- QGridLayout *groupBoxLayout = new QGridLayout(groupBox);
- groupBox->setLayout(groupBoxLayout);
-
- // 遍历子元素
- QDomNode node = root.firstChild();
- while (!node.isNull()) {
- QDomElement element = node.toElement();
- if (!element.isNull()) {
- QString elementName = element.tagName();
- if (elementName == "Name" || elementName == "Description" || elementName == "Author"
- || elementName == "Version" || elementName == "Node"
- || elementName == "Priority" || elementName == "MathLib") {
- // 添加基本信息
- addItemIntoGroupBox(groupBoxLayout, elementName, element.text(), 0);
- } else if (elementName == "CreateTime" || elementName == "ChangeTime") {
- // 添加时间信息
- addItemIntoGroupBox(groupBoxLayout, elementName, element.text(), 3);
- } else if (elementName == "CommandList") {
- // 处理命令列表
- QVector commandList;
- QDomNodeList commands = element.elementsByTagName("Command");
-
- for (int i = 0; i < commands.count(); i++) {
- QDomElement commandElement = commands.at(i).toElement();
- QDomNamedNodeMap attributes = commandElement.attributes();
- commandList.append(attributes);
- }
-
- // 添加命令列表组框
- addGroupBox3(layout, "CommandList", QDomNamedNodeMap(), commandList, 2);
- } else {
- QGroupBox *otherGroupBox = new QGroupBox("Other Info", this);
- otherGroupBox->setObjectName("Other Info");
- layout->addWidget(otherGroupBox);
- QGridLayout *otherGroupBoxLayout = new QGridLayout(otherGroupBox);
- otherGroupBox->setLayout(otherGroupBoxLayout);
-
- // 递归处理其他自定义元素
- std::function processChildNodes =
- [&](QGridLayout *subLayout, QDomNode &subNode) {
- QDomElement subElement = subNode.toElement();
- QString subElementName = subElement.nodeName();
- if (subNode.hasChildNodes() && !subNode.firstChild().isText()) {
- QGroupBox *groupBox = new QGroupBox(subElementName, this);
- subLayout->addWidget(groupBox);
- QGridLayout *subGroupBoxLayout = new QGridLayout(groupBox);
- groupBox->setLayout(subGroupBoxLayout);
- QDomNode childNode = subNode.firstChild();
- while (!childNode.isNull()) {
- processChildNodes(subGroupBoxLayout, childNode);
- childNode = childNode.nextSibling();
- }
- addPlusButton(subGroupBoxLayout);
- } else {
- addItemIntoGroupBox(subLayout, subElementName, subElement.text(),
- 99);
- }
- };
- processChildNodes(otherGroupBoxLayout, node);
- }
- }
- node = node.nextSibling();
- }
-
- // 添加"+"按钮用于添加新属性
- addPlusButton(groupBoxLayout);
- updateWindowTitle();
- }
- file.close();
-}
-
-// 打开服务文件
-void MainWindow::openServiceFile()
-{
- // 获取右布局
- QVBoxLayout *layout = findChild("rightLayout");
- if (!layout) {
- QMessageBox::warning(this, tr("Error"), tr("Software error."));
- return;
- }
- // 打开文件
- QFile file(currentFilePath);
- if (!file.open(QIODevice::ReadOnly)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file."));
- return;
- }
- // 创建DOM文档
- QDomDocument doc;
- if (!doc.setContent(&file)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to parse service config file."));
- file.close();
- return;
- }
- // 获取根元素
- QDomElement root = doc.documentElement();
- if (root.tagName() == "Service") {
- // 添加组框
- QGroupBox *groupBox = new QGroupBox("Service Info", this);
- groupBox->setObjectName("Service Info");
- layout->addWidget(groupBox);
- QGridLayout *groupBoxLayout = new QGridLayout(groupBox);
- groupBox->setLayout(groupBoxLayout);
-
- // 遍历子元素
- QDomNode node = root.firstChild();
- while (!node.isNull()) {
- QDomElement element = node.toElement();
- if (!element.isNull()) {
- QString elementName = element.tagName();
- if (elementName == "Name" || elementName == "Description" || elementName == "Author"
- || elementName == "Version" || elementName == "Priority") {
- // 添加基本信息
- addItemIntoGroupBox(groupBoxLayout, elementName, element.text(), 0);
- } else if (elementName == "CreateTime" || elementName == "ChangeTime") {
- // 添加时间信息
- addItemIntoGroupBox(groupBoxLayout, elementName, element.text(), 3);
- } else if (elementName == "CommandList") {
- // 处理命令列表
- QVector commandList;
- QDomNodeList commands = element.elementsByTagName("Command");
-
- for (int i = 0; i < commands.count(); i++) {
- QDomElement commandElement = commands.at(i).toElement();
- QDomNamedNodeMap attributes = commandElement.attributes();
-
- commandList.append(attributes);
- }
-
- // 添加命令列表组框
- addGroupBox3(layout, "CommandList", QDomNamedNodeMap(), commandList, 2);
- } else {
- QGroupBox *otherGroupBox = new QGroupBox("Other Info", this);
- otherGroupBox->setObjectName("Other Info");
- layout->addWidget(otherGroupBox);
- QGridLayout *otherGroupBoxLayout = new QGridLayout(otherGroupBox);
- otherGroupBox->setLayout(otherGroupBoxLayout);
- // 递归处理其他自定义元素
- std::function processChildNodes =
- [&](QGridLayout *subLayout, QDomNode &subNode) {
- QDomElement subElement = subNode.toElement();
- QString subElementName = subElement.nodeName();
- if (subNode.hasChildNodes() && !subNode.firstChild().isText()) {
- QGroupBox *groupBox = new QGroupBox(subElementName, this);
- subLayout->addWidget(groupBox);
- QGridLayout *subGroupBoxLayout = new QGridLayout(groupBox);
- groupBox->setLayout(subGroupBoxLayout);
- QDomNode childNode = subNode.firstChild();
- while (!childNode.isNull()) {
- processChildNodes(subGroupBoxLayout, childNode);
- childNode = childNode.nextSibling();
- }
- addPlusButton(subGroupBoxLayout);
- } else {
- addItemIntoGroupBox(subLayout, subElementName, subElement.text(),
- 99);
- }
- };
- processChildNodes(otherGroupBoxLayout, node);
- }
- }
- node = node.nextSibling();
- }
-
- // 添加"+"按钮用于添加新属性
- addPlusButton(groupBoxLayout);
- updateWindowTitle();
- }
- file.close();
-}
-
-void MainWindow::addPlusButton(QGridLayout *layout)
-{
- QPushButton *addButton = new QPushButton("+", this);
- addButton->setFlat(true);
- layout->addWidget(addButton, layout->rowCount(), 0, 1, 3);
- connect(addButton, &QPushButton::clicked, [this, layout, addButton]() {
- bool ok;
- QString attributeName = QInputDialog::getText(
- this, tr("Add Attribute"), tr("Attribute Name:"), QLineEdit::Normal, "", &ok);
- if (ok && !attributeName.isEmpty()) {
- isModified = true;
- updateWindowTitle();
- layout->removeWidget(addButton);
- addItemIntoGroupBox(layout, attributeName, "", 99);
- layout->addWidget(addButton, layout->rowCount(), 0, 1, 3);
- }
- });
-}
-
-// 打开IDL文件
-void MainWindow::openIDLFile()
-{
- // 打开文件
- QFile file(currentFilePath);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to open file."));
- return;
- }
-
- // 清空现有数据
- namespaces.clear();
-
- // 读取文件
- QTextStream in(&file);
- // 命名空间栈
- QStack> namespaceStack;
- // 当前结构体
- QSharedPointer currentStruct;
- QString line;
- bool inStruct = false;
- int braceCount = 0;
-
- // 逐行读取IDL文件
- while (!in.atEnd()) {
- line = in.readLine().trimmed();
-
- // 跳过空行和注释
- if (line.isEmpty() || line.startsWith("//"))
- continue;
-
- // 处理命名空间开始
- if (line.startsWith("module")) {
- braceCount++;
- // 创建新的命名空间
- QSharedPointer newNS =
- QSharedPointer::create();
-
- // 获取命名空间名称
- QString nsNames = line.mid(7).trimmed();
- newNS->namespaceName = nsNames.split(" ").first(); // 直接使用完整名称
- namespaceStack.push(newNS);
- continue;
- }
-
- // 处理结构体开始
- if (line.startsWith("struct")) {
- if (inStruct && currentStruct && !currentStruct->structName.isEmpty()) {
- namespaceStack.top()->structDefinitions.append(currentStruct);
- currentStruct = QSharedPointer::create();
- }
- inStruct = true;
- braceCount++;
- if (!currentStruct) {
- currentStruct = QSharedPointer::create();
- }
- currentStruct->structName = line.split(" ").at(1);
- continue;
- }
-
- // 处理成员变量
- if (inStruct && currentStruct) {
- if (!line.startsWith("{") && !line.startsWith("}")) {
- QString description;
- int commentPos = line.indexOf("//");
- if (commentPos != -1) {
- description = line.mid(commentPos + 2).trimmed();
- line = line.left(commentPos).trimmed();
- }
-
- QStringList parts = line.split(";").first().split(" ", Qt::SkipEmptyParts);
- if (parts[0].startsWith("@")) {
- parts.pop_front();
- }
- if (parts.size() >= 2) {
- QSharedPointer var = QSharedPointer::create();
- var->dataType = parts[0];
- QString varDecl = parts[1];
-
- if (varDecl.contains("[")) {
- var->isArray = true;
- var->variableName = varDecl.split("[").first();
-
- QRegularExpression re("\\[(\\d+)\\]");
- QRegularExpressionMatchIterator i = re.globalMatch(varDecl);
- while (i.hasNext()) {
- QRegularExpressionMatch match = i.next();
- var->arraySizes.append(match.captured(1).toInt());
- }
- } else {
- var->isArray = false;
- var->variableName = varDecl;
- }
-
- var->description = description;
- currentStruct->memberVariables.append(var);
- }
- }
- }
-
- // 处理花括号闭合
- if (line.contains("}")) {
- braceCount--;
- if (inStruct) {
- inStruct = false;
- if (currentStruct && !currentStruct->structName.isEmpty()) {
- namespaceStack.top()->structDefinitions.append(currentStruct);
- currentStruct = QSharedPointer::create();
- }
- } else {
- if (!namespaceStack.isEmpty()) {
- QSharedPointer completedNS = namespaceStack.pop();
- if (namespaceStack.isEmpty()) {
- namespaces.append(completedNS);
- } else {
- namespaceStack.top()->childNamespaces.append(completedNS);
- }
- }
- }
- }
- }
-
- file.close();
- // 更新IDL Tree
- updateIDLTreeWidget();
-
- updateWindowTitle();
-}
-
-// 根据namespaces更新树形控件
-void MainWindow::updateIDLTreeWidget()
-{
- QTreeWidget *treeWidget = findChild("leftWidget");
- if (!treeWidget)
- return;
-
- // 清空现有项
- treeWidget->clear();
-
- // 递归添加命名空间及其子命名空间的辅助函数
- std::function &)>
- addNamespaceToTree = [&addNamespaceToTree](QTreeWidgetItem *parentItem,
- const QSharedPointer &ns) {
- // 添加结构体
- for (const auto &structDef : ns->structDefinitions) {
- if (structDef && !structDef->structName.isEmpty()) {
- QTreeWidgetItem *structItem =
- new QTreeWidgetItem(QStringList() << structDef->structName);
- if (parentItem) {
- parentItem->addChild(structItem);
- }
- }
- }
-
- // 递归处理子命名空间
- for (const auto &childNS : ns->childNamespaces) {
- if (childNS && !childNS->namespaceName.isEmpty()) {
- QTreeWidgetItem *childItem =
- new QTreeWidgetItem(QStringList() << childNS->namespaceName);
- if (parentItem) {
- parentItem->addChild(childItem);
- addNamespaceToTree(childItem, childNS);
- }
- }
- }
- };
-
- // 处理顶层命名空间
- for (const auto &ns : namespaces) {
- if (ns && !ns->namespaceName.isEmpty()) {
- QTreeWidgetItem *nsItem = new QTreeWidgetItem(QStringList() << ns->namespaceName);
- treeWidget->addTopLevelItem(nsItem);
- addNamespaceToTree(nsItem, ns);
- }
- }
-
- // 展开整个树形控件
- treeWidget->expandAll();
-
- // 连接树形控件的项目选择信号
- disconnect(treeWidget, &QTreeWidget::itemClicked, this, &MainWindow::onTreeWidgetItemClicked);
- connect(treeWidget, &QTreeWidget::itemClicked, this, &MainWindow::onTreeWidgetItemClicked);
-}
-
-void MainWindow::onTreeWidgetItemClicked(QTreeWidgetItem *item)
-{
- if (!item->parent())
- return; // 如果是顶层项目(命名空间),则返回
-
- QTableWidget *tableWidget = findChild("rightWidget");
- if (!tableWidget)
- return;
-
- // 清空表格
- tableWidget->setRowCount(0);
-
- // 获取选中的结构体名称
- QString structName = item->text(0);
-
- std::function(const QString &,
- QSharedPointer &)>
- findStruct =
- [&findStruct](
- const QString &structName,
- QSharedPointer &ns) -> QSharedPointer {
- // 在当前命名空间中查找结构体
- for (auto &structDef : ns->structDefinitions) {
- if (structDef && structDef->structName == structName) {
- return structDef;
- }
- }
- // 在子命名空间中递归查找
- for (auto &childNS : ns->childNamespaces) {
- auto result = findStruct(structName, childNS);
- if (result) {
- return result;
- }
- }
- return QSharedPointer();
- };
-
- QSharedPointer structDef;
- for (auto &ns : namespaces) {
- structDef = findStruct(structName, ns);
- if (structDef) {
- break;
- }
- }
-
- if (structDef) {
- // 找到对应的结构体,显示其成员变量
- tableWidget->setRowCount(structDef->memberVariables.size());
- int row = 0;
- for (const auto &member : structDef->memberVariables) {
- // 变量名
- QTableWidgetItem *nameItem = new QTableWidgetItem(member->variableName);
- tableWidget->setItem(row, 0, nameItem);
-
- // 数据类型
- QTableWidgetItem *typeItem = new QTableWidgetItem(member->dataType);
- tableWidget->setItem(row, 1, typeItem);
-
- // 数组大小
- QString sizeStr;
- if (member->isArray) {
- QStringList sizes;
- for (int size : member->arraySizes) {
- sizes << QString::number(size);
- }
- sizeStr = "[" + sizes.join("][") + "]";
- } else {
- sizeStr = "1";
- }
- QTableWidgetItem *sizeItem = new QTableWidgetItem(sizeStr);
- tableWidget->setItem(row, 2, sizeItem);
-
- // 描述(注释)
- QTableWidgetItem *descItem = new QTableWidgetItem(member->description);
- tableWidget->setItem(row, 3, descItem);
-
- row++;
- }
- }
-}
-
-// 添加组框1
-void MainWindow::addGroupBox(QVBoxLayout *layout, QString name, QDomNamedNodeMap attributes)
-{
- // 工作路径
- QString workPath;
- // 创建组框
- QGroupBox *groupBox = new QGroupBox(name, this);
- // 设置组框名称
- groupBox->setObjectName(name);
- // 添加到布局
- layout->addWidget(groupBox);
- // 创建网格布局
- QGridLayout *gridLayout = new QGridLayout(groupBox);
- // 设置布局
- groupBox->setLayout(gridLayout);
- // 遍历属性添加控件
- for (int i = 0; i < attributes.count(); i++) {
- QDomNode attr = attributes.item(i);
- if (attr.nodeName() == "WorkPath") {
- // 如果是WorkPath,多添加一个选择路径按钮
- addItemIntoGroupBox(gridLayout, attr.nodeName(), attr.nodeValue(), 1);
- } else if (attr.nodeName() == "ModelsPath") {
- // 如果是ModelsPath,正常添加
- addItemIntoGroupBox(gridLayout, attr.nodeName(), attr.nodeValue(), 0);
- // 记录ModelsPath
- modelPath = attr.nodeValue();
- } else if (attr.nodeName() == "ServicesPath") {
- // 如果是ServicesPath,正常添加
- addItemIntoGroupBox(gridLayout, attr.nodeName(), attr.nodeValue(), 0);
- // 记录ServicesPath
- ServicePath = attr.nodeValue();
- } else if (attr.nodeName() == "OSName" || attr.nodeName() == "Version"
- || attr.nodeName() == "RTXVersion" || attr.nodeName() == "CPUAffinity"
- || attr.nodeName() == "BaseFrequency" || attr.nodeName() == "DomainID") {
- // 如果是OSName、Version、RTXVersion、CPUAffinity、BaseFrequency、DomainID,正常添加
- addItemIntoGroupBox(gridLayout, attr.nodeName(), attr.nodeValue(), 0);
- } else {
- // 如果是其他属性,添加一个删除按钮
- addItemIntoGroupBox(gridLayout, attr.nodeName(), attr.nodeValue(), 99);
- }
- }
- // 如果工作路径不为空
- if (!workPath.isEmpty()) {
- // 如果工作路径不以"/"结尾
- if (!workPath.endsWith("/")) {
- // 添加"/"
- workPath.append("/");
- }
- // 添加工作路径到模型路径和服务路径
- modelPath = workPath + modelPath;
- ServicePath = workPath + ServicePath;
- }
- // 添加"+"按钮
- addPlusButton(gridLayout);
-}
-
-// 添加组框2
-void MainWindow::addGroupBox2(QVBoxLayout *layout, QString name, QDomNamedNodeMap attributes)
-{
- // 创建组框
- QGroupBox *groupBox = new QGroupBox(name, this);
- // 设置组框名称
- groupBox->setObjectName(name);
- // 添加到布局
- layout->addWidget(groupBox);
- // 创建水平布局
- QHBoxLayout *hLayout = new QHBoxLayout(groupBox);
- // 设置布局
- groupBox->setLayout(hLayout);
- // 遍历属性添加控件
- for (int i = 0; i < attributes.count(); i++) {
- QDomNode attr = attributes.item(i);
- // 创建复选框
- QCheckBox *checkBox = new QCheckBox(attr.nodeName(), this);
- // 如果属性值为true或1或True或TRUE,则设置为选中
- if (attr.nodeValue() == "true" || attr.nodeValue() == "1" || attr.nodeValue() == "True"
- || attr.nodeValue() == "TRUE") {
- checkBox->setChecked(true);
- } else {
- checkBox->setChecked(false);
- }
- // 添加到布局
- hLayout->addWidget(checkBox);
- // 连接修改信号
- connectModificationSignals(checkBox);
- }
-}
-
-// 添加组框3
-void MainWindow::addGroupBox3(QVBoxLayout *layout, QString name, QDomNamedNodeMap groupAttributes,
- QVector vecAttributes, int type)
-{
- // 创建组框
- QGroupBox *groupBox = new QGroupBox(name, this);
- // 设置组框名称
- groupBox->setObjectName(name);
- // 添加到布局
- layout->addWidget(groupBox);
- // 创建垂直布局
- QGridLayout *groupBoxLayout = new QGridLayout(groupBox);
-
- // 遍历组属性
- for (int i = 0; i < groupAttributes.count(); i++) {
- QDomNode attr = groupAttributes.item(i);
- addItemIntoGroupBox(groupBoxLayout, attr.nodeName(), attr.nodeValue(), 0);
- }
- // 创建水平布局
- QHBoxLayout *buttonLayout = new QHBoxLayout();
- // 创建添加按钮
- QPushButton *addButton = new QPushButton("Add", this);
- // 创建删除按钮
- QPushButton *removeButton = new QPushButton("Remove", this);
- // 添加按钮到水平布局
- buttonLayout->addWidget(addButton);
- // 添加按钮到水平布局
- buttonLayout->addWidget(removeButton);
- // 添加水平布局到垂直布局
- groupBoxLayout->addLayout(buttonLayout, groupBoxLayout->rowCount(), 0, 1,
- groupBoxLayout->columnCount());
- // 创建表格
- QTableWidget *tableWidget = new QTableWidget(groupBox);
- // 设置表格拉伸模式
- tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
- // 设置表格行数
- tableWidget->setRowCount(vecAttributes.size());
- // 设置表格选择模式
- tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
- // 如果类型为0或1,即模型列表或服务列表
- if (type == 0 || type == 1) {
- // 设置表格列数
- tableWidget->setColumnCount(2);
- // 创建表头
- QStringList headers;
- // 设置表头
- headers << "Name" << "ClassName";
- // 设置表头
- tableWidget->setHorizontalHeaderLabels(headers);
- } else if (type == 2) { // 如果类型为2,即命令列表
- // 设置表格列数
- tableWidget->setColumnCount(3);
- // 创建表头
- QStringList headers;
- // 设置表头
- headers << "Name" << "Description" << "Call";
- // 设置表头
- tableWidget->setHorizontalHeaderLabels(headers);
- }
-
- // 添加表格到组框布局
- groupBoxLayout->addWidget(tableWidget, groupBoxLayout->rowCount(), 0, 1,
- groupBoxLayout->columnCount());
-
- int rowCount = 0;
- // 遍历属性
- for (QDomNamedNodeMap &attributes : vecAttributes) {
- // 遍历属性
- for (int i = 0; i < attributes.count(); i++) {
- // 如果类型为0或1,即模型列表或服务列表
- if (type == 0 || type == 1) {
- if (attributes.item(i).nodeName() == "ClassName") {
- // 如果属性名称为ClassName,设置表格项第2列
- tableWidget->setItem(rowCount, 1,
- new QTableWidgetItem(attributes.item(i).nodeValue()));
- } else if (attributes.item(i).nodeName() == "Name") {
- // 如果属性名称为Name,设置表格项第1列
- tableWidget->setItem(rowCount, 0,
- new QTableWidgetItem(attributes.item(i).nodeValue()));
- }
- } else if (type == 2) { // 如果类型为2,即命令列表
- if (attributes.item(i).nodeName() == "Name") {
- // 如果属性名称为Name,设置表格项第1列
- tableWidget->setItem(rowCount, 0,
- new QTableWidgetItem(attributes.item(i).nodeValue()));
- } else if (attributes.item(i).nodeName() == "Description") {
- // 如果属性名称为Description,设置表格项第2列
- tableWidget->setItem(rowCount, 1,
- new QTableWidgetItem(attributes.item(i).nodeValue()));
- } else if (attributes.item(i).nodeName() == "Call") {
- // 如果属性名称为Call,设置表格项第3列
- tableWidget->setItem(rowCount, 2,
- new QTableWidgetItem(attributes.item(i).nodeValue()));
- }
- }
- }
- rowCount++;
- }
-
- // 更新模型列表或服务列表
- if (type == 0) {
- UpdateModelList(tableWidget);
- } else if (type == 1) {
- UpdateServiceList(tableWidget);
- }
-
- // 链接add按钮的槽
- connect(addButton, &QPushButton::clicked, [tableWidget]() {
- int row = tableWidget->rowCount();
- tableWidget->insertRow(row);
- });
-
- // 链接remove的槽
- connect(removeButton, &QPushButton::clicked, [this, tableWidget]() {
- int currentRow = tableWidget->currentRow();
- if (currentRow >= 0) {
- if (!tableWidget->item(currentRow, 0)->text().isEmpty()) {
- isModified = true;
- updateWindowTitle();
- }
- tableWidget->removeRow(currentRow);
- tableWidget->clearSelection();
- }
- });
- // 链接元素改变的槽
- connect(tableWidget, &QTableWidget::itemChanged, [this, tableWidget, type]() {
- if (type == 0) {
- UpdateModelList(tableWidget);
- } else if (type == 1) {
- UpdateServiceList(tableWidget);
- }
- isModified = true;
- updateWindowTitle();
- });
-}
-
-// 向组框1添加元素
-void MainWindow::addItemIntoGroupBox(QGridLayout *gridLayout, QString itemName, QString itemValue,
- int itemStyle)
-{
- int row = gridLayout->rowCount();
- QLabel *label = new QLabel(itemName, this);
- gridLayout->addWidget(label, row, 0);
- if (itemStyle == 0) { //普通模式
- QLineEdit *lineEdit = new QLineEdit(itemValue, this);
- gridLayout->addWidget(lineEdit, row, 1);
- setLineEditRules(lineEdit, itemName);
- connectModificationSignals(lineEdit);
- } else if (itemStyle == 1) { //路径模式
- QLineEdit *lineEdit = new QLineEdit(itemValue, this);
- gridLayout->addWidget(lineEdit, row, 1);
- QPushButton *openPathButton = new QPushButton("...", this);
- gridLayout->addWidget(openPathButton, row, 2);
- connect(openPathButton, &QPushButton::clicked, [this, lineEdit]() {
- QString newPath =
- QFileDialog::getExistingDirectory(this, tr("Select Directory"), lineEdit->text());
- if (!newPath.isEmpty()) {
- lineEdit->setText(newPath);
- }
- });
- connectModificationSignals(lineEdit);
- } else if (itemStyle == 2) { //文件选择模式
- QLineEdit *lineEdit = new QLineEdit(itemValue, this);
- gridLayout->addWidget(lineEdit, row, 1);
- QPushButton *openFileButton = new QPushButton("...", this);
- gridLayout->addWidget(openFileButton, row, 2);
- connect(openFileButton, &QPushButton::clicked, [this, lineEdit]() {
- QString newPath = QFileDialog::getOpenFileName(this, tr("Select File"),
- lineEdit->text(), tr("All Files (*)"));
- if (!newPath.isEmpty()) {
- lineEdit->setText(newPath);
- }
- });
- connectModificationSignals(lineEdit);
- } else if (itemStyle == 3) { //时间选择模式
- QDateTimeEdit *dateTimeEdit = new QDateTimeEdit(this);
- gridLayout->addWidget(dateTimeEdit, row, 1);
- dateTimeEdit->setCalendarPopup(true);
- dateTimeEdit->setDateTime(QDateTime::currentDateTime());
- connectModificationSignals(dateTimeEdit);
- } else if (itemStyle == 99) { //自定义模式,支持删除
- QLineEdit *lineEdit = new QLineEdit(itemValue, this);
- gridLayout->addWidget(lineEdit, row, 1);
- QPushButton *minuseButton = new QPushButton("-", this);
- minuseButton->setFixedSize(20, 20);
- connect(minuseButton, &QPushButton::clicked,
- [this, gridLayout, label, lineEdit, minuseButton]() {
- QMessageBox::StandardButton reply;
- reply =
- QMessageBox::question(this, tr("Confirm Deletion"),
- tr("Are you sure you want to delete this attribute?"),
- QMessageBox::Yes | QMessageBox::No);
- if (reply == QMessageBox::Yes) {
- isModified = true;
- updateWindowTitle();
- gridLayout->removeWidget(label);
- gridLayout->removeWidget(lineEdit);
- gridLayout->removeWidget(minuseButton);
- delete label;
- delete lineEdit;
- delete minuseButton;
- }
- });
- gridLayout->addWidget(minuseButton, row, 2);
- connectModificationSignals(lineEdit);
- }
-}
-
-void MainWindow::setLineEditRules(QLineEdit *lineEdit, QString name)
-{
- if (name == "WorkPath" || name == "ModelsPath" || name == "ServicesPath") {
- // 实时验证目录是否存在
- connect(lineEdit, &QLineEdit::textChanged, [this, lineEdit, name](const QString &text) {
- QDir dir(text);
- if (!dir.exists()) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(tr("Directory does not exist"));
- } else {
- lineEdit->setStyleSheet("");
- lineEdit->setToolTip("");
- }
- });
- } else if (name == "Name") {
- connect(lineEdit, &QLineEdit::textChanged, [this, lineEdit, name](const QString &text) {
- // 检查是否是C++标准的名称
- QRegularExpression regex("^[A-Za-z_][A-Za-z0-9_]*$");
- if (!regex.match(text).hasMatch()) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(tr("Invalid class name. Must start with letter/underscore and "
- "contain only letters, numbers and underscores"));
- } else {
- lineEdit->setStyleSheet("");
- lineEdit->setToolTip("");
- }
- });
- } else if (name == "CPUAffinity") {
- // 检查是否是逗号分割的数字列表
- connect(lineEdit, &QLineEdit::textChanged, [this, lineEdit, name](const QString &text) {
- QRegularExpression regex("^[0-9,]+$");
- if (!regex.match(text).hasMatch()) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(
- tr("Invalid CPU affinity format. Must be a comma-separated list of numbers"));
- } else {
- lineEdit->setStyleSheet("");
- lineEdit->setToolTip("");
- }
- });
- } else if (name == "BaseFrequency" || name == "DomainID" || name == "Priority") {
- // 检查是否是数字
- connect(lineEdit, &QLineEdit::textChanged, [this, lineEdit, name](const QString &text) {
- QRegularExpression regex("^[0-9]+$");
- if (!regex.match(text).hasMatch()) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(tr("Invalid base frequency. Must be a number"));
- } else {
- lineEdit->setStyleSheet("");
- lineEdit->setToolTip("");
- }
- });
- } else if (name == "Node") {
- connect(lineEdit, &QLineEdit::textChanged, [this, lineEdit, name](const QString &text) {
- // 验证"数字-数字"的格式
- QRegularExpression regex("^\\d+-\\d+$");
- if (!regex.match(text).hasMatch()) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(
- tr("Invalid format. Must be in the form of 'number-number' (e.g. 3-5)"));
- } else {
- // 进一步验证第一个数字是否小于第二个数字
- QStringList parts = text.split('-');
- int first = parts[0].toInt();
- int second = parts[1].toInt();
- if (first > 5) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(tr("First number must be less than 5"));
- } else {
- if (second >= pow(2, first)) {
- lineEdit->setStyleSheet("border: 2px solid red;");
- lineEdit->setToolTip(tr(
- "Second number must be less than 2 to the power of the first number"));
- } else {
- lineEdit->setStyleSheet("");
- lineEdit->setToolTip("");
- }
- }
- }
- });
- }
-}
-
-// 寻找模型
-bool MainWindow::findModel(QString modelName, QString ModelPath)
-{
- //查找模型动态库是否存在
- QFile modelsoFile(ModelPath + "/lib" + modelName + ".so");
- if (!modelsoFile.exists()) {
- return false;
- }
-
- //查找模型配置文件是否存在
- QFile modelFile(ModelPath + "/" + modelName + ".mcfg");
- if (!modelFile.exists()) {
- return false;
- }
-
- QTreeWidget *modelWidget = findChild("ModelWidget");
- if (modelWidget) {
- // 检查模型列表中是否已存在同名模型
- bool exists = false;
- for (int i = 0; i < modelWidget->topLevelItemCount(); i++) {
- if (modelWidget->topLevelItem(i)->text(0) == modelName + ".mcfg") {
- exists = true;
- break;
- }
- }
- if (!exists)
- modelWidget->addTopLevelItem(new QTreeWidgetItem(QStringList() << modelName + ".mcfg"));
- else
- return false;
- }
- return true;
-}
-
-// 寻找服务
-bool MainWindow::findService(QString serviceName, QString ServicePath)
-{
- // 查找服务动态库是否存在
- QFile servicesoFile(ServicePath + "/lib" + serviceName + ".so");
- if (!servicesoFile.exists()) {
- return false;
- }
-
- // 查找服务配置文件是否存在
- QFile serviceFile(ServicePath + "/" + serviceName + ".scfg");
- if (!serviceFile.exists()) {
- return false;
- }
-
- QTreeWidget *serviceWidget = findChild("ServiceWidget");
- if (serviceWidget) {
- // 检查服务列表中是否已存在同名模型
- bool exists = false;
- for (int i = 0; i < serviceWidget->topLevelItemCount(); i++) {
- if (serviceWidget->topLevelItem(i)->text(0) == serviceName + ".scfg") {
- exists = true;
- break;
- }
- }
- if (!exists)
- serviceWidget->addTopLevelItem(
- new QTreeWidgetItem(QStringList() << serviceName + ".scfg"));
- else
- return false;
- }
- return true;
-}
-
-// 更新模型配置文件列表
-void MainWindow::UpdateModelList(QTableWidget *tabWidget)
-{
- if (currentFileType != 0 || tabWidget == nullptr)
- return;
- QTreeWidget *modelWidget = findChild("ModelWidget");
- if (modelWidget) {
- modelWidget->clear();
- }
- for (int row = 0; row < tabWidget->rowCount(); row++) {
- QTableWidgetItem *item = tabWidget->item(row, 1); // Get item from ClassName column
- if (item) {
- QString className = item->text();
- if (!findModel(className, modelPath)) {
- item->setForeground(Qt::red);
- item->setToolTip("Model not found or already exists");
- } else {
- item->setForeground(Qt::white);
- item->setToolTip("");
- }
- }
- }
-}
-
-// 更新服务配置文件列表
-void MainWindow::UpdateServiceList(QTableWidget *tabWidget)
-{
- if (currentFileType != 0 || tabWidget == nullptr)
- return;
- QTreeWidget *serviceWidget = findChild("ServiceWidget");
- if (serviceWidget) {
- serviceWidget->clear();
- }
- for (int row = 0; row < tabWidget->rowCount(); row++) {
- QTableWidgetItem *item = tabWidget->item(row, 1); // Get item from ClassName column
- if (item) {
- QString className = item->text();
- if (!findService(className, ServicePath)) {
- item->setForeground(Qt::red);
- item->setToolTip("Service not found or already exists");
- } else {
- item->setForeground(Qt::white);
- item->setToolTip("");
- }
- }
- }
-}
-
-// 保存文件
-void MainWindow::saveFile(QString filePath)
-{
- if (!filePath.isEmpty()) {
- if (currentFileType == 0) {
- saveScenarioFile(filePath);
- } else if (currentFileType == 1) {
- saveModelFile(filePath);
- } else if (currentFileType == 2) {
- saveServiceFile(filePath);
- } else if (currentFileType == 3) {
- saveIDLFile(filePath);
- }
- isModified = false; // 文件保存后重置修改状态
- updateWindowTitle();
- }
-}
-
-// 保存运行环境配置文件
-void MainWindow::saveScenarioFile(QString filePath)
-{
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to save file."));
- return;
- }
-
- QXmlStreamWriter xmlWriter(&file);
- xmlWriter.setAutoFormatting(true);
- xmlWriter.writeStartDocument();
- xmlWriter.writeStartElement("Scenario");
-
- // 保存Environment部分
- QGroupBox *envGroupBox = findChild("Environment");
- if (envGroupBox) {
- xmlWriter.writeStartElement("Environment");
- QGridLayout *gridLayout = qobject_cast(envGroupBox->layout());
- if (gridLayout) {
- for (int i = 0; i < gridLayout->rowCount(); ++i) {
- QLayoutItem *labelItem = gridLayout->itemAtPosition(i, 0);
- QLayoutItem *lineEditItem = gridLayout->itemAtPosition(i, 1);
- if (labelItem && lineEditItem) {
- QLabel *label = qobject_cast(labelItem->widget());
- QLineEdit *lineEdit = qobject_cast(lineEditItem->widget());
- if (label && lineEdit) {
- xmlWriter.writeAttribute(label->text(), lineEdit->text());
- }
- }
- }
- }
- xmlWriter.writeEndElement(); // Environment
- }
-
- // 保存ConsoleOutput和Log部分
- QGroupBox *consoleGroupBox = findChild("ConsoleOutput");
- if (consoleGroupBox) {
- xmlWriter.writeStartElement("ConsoleOutput");
- QHBoxLayout *hLayout = qobject_cast(consoleGroupBox->layout());
- if (hLayout) {
- for (int i = 0; i < hLayout->count(); ++i) {
- QCheckBox *checkBox = qobject_cast(hLayout->itemAt(i)->widget());
- if (checkBox) {
- xmlWriter.writeAttribute(checkBox->text(),
- checkBox->isChecked() ? "true" : "false");
- }
- }
- }
- xmlWriter.writeEndElement(); // ConsoleOutput
- }
-
- QGroupBox *logGroupBox = findChild("Log");
- if (logGroupBox) {
- xmlWriter.writeStartElement("Log");
- QHBoxLayout *hLayout = qobject_cast(logGroupBox->layout());
- if (hLayout) {
- for (int i = 0; i < hLayout->count(); ++i) {
- QCheckBox *checkBox = qobject_cast(hLayout->itemAt(i)->widget());
- if (checkBox) {
- xmlWriter.writeAttribute(checkBox->text(),
- checkBox->isChecked() ? "true" : "false");
- }
- }
- }
- xmlWriter.writeEndElement(); // Log
- }
-
- // 保存ModelsList部分
- QGroupBox *modelsGroupBox = findChild("ModelsList");
- if (modelsGroupBox) {
- xmlWriter.writeStartElement("ModelsList");
- QTableWidget *tableWidget = modelsGroupBox->findChild();
- if (tableWidget) {
- for (int row = 0; row < tableWidget->rowCount(); ++row) {
- if (!tableWidget->item(row, 1)->text().isEmpty()) {
- xmlWriter.writeStartElement("Model");
- for (int col = 0; col < tableWidget->columnCount(); ++col) {
- QTableWidgetItem *item = tableWidget->item(row, col);
- if (item) {
- xmlWriter.writeAttribute(tableWidget->horizontalHeaderItem(col)->text(),
- item->text());
- }
- }
- xmlWriter.writeEndElement(); // Model
- }
- }
- }
- xmlWriter.writeEndElement(); // ModelsList
- }
-
- // 保存ServicesList部分
- QGroupBox *servicesGroupBox = findChild("ServicesList");
- if (servicesGroupBox) {
- xmlWriter.writeStartElement("ServicesList");
- QTableWidget *tableWidget = servicesGroupBox->findChild();
- if (tableWidget) {
- for (int row = 0; row < tableWidget->rowCount(); ++row) {
- if (!tableWidget->item(row, 1)->text().isEmpty()) {
- xmlWriter.writeStartElement("Service");
- for (int col = 0; col < tableWidget->columnCount(); ++col) {
- QTableWidgetItem *item = tableWidget->item(row, col);
- if (item) {
- xmlWriter.writeAttribute(tableWidget->horizontalHeaderItem(col)->text(),
- item->text());
- }
- }
- xmlWriter.writeEndElement(); // Service
- }
- }
- }
- xmlWriter.writeEndElement(); // ServicesList
- }
-
- xmlWriter.writeEndElement(); // Scenario
- xmlWriter.writeEndDocument();
- file.close();
-}
-
-// 保存模型配置文件
-void MainWindow::saveModelFile(QString filePath)
-{
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to save file."));
- return;
- }
-
- QXmlStreamWriter xmlWriter(&file);
- xmlWriter.setAutoFormatting(true);
- xmlWriter.writeStartDocument();
- xmlWriter.writeStartElement("Model");
-
- // 保存Model Info部分
- QGroupBox *modelInfoBox = findChild("Model Info");
- if (modelInfoBox) {
- QGridLayout *gridLayout = qobject_cast(modelInfoBox->layout());
- if (gridLayout) {
- for (int i = 0; i < gridLayout->rowCount(); ++i) {
- QLayoutItem *labelItem = gridLayout->itemAtPosition(i, 0);
- QLayoutItem *valueItem = gridLayout->itemAtPosition(i, 1);
-
- if (labelItem && valueItem) {
- QLabel *label = qobject_cast(labelItem->widget());
- if (QLineEdit *lineEdit = qobject_cast(valueItem->widget())) {
- if (label) {
- xmlWriter.writeStartElement(label->text());
- xmlWriter.writeCharacters(lineEdit->text());
- xmlWriter.writeEndElement();
- }
- } else if (QDateTimeEdit *dateTimeEdit =
- qobject_cast(valueItem->widget())) {
- if (label) {
- xmlWriter.writeStartElement(label->text());
- xmlWriter.writeCharacters(
- dateTimeEdit->dateTime().toString(Qt::ISODate));
- xmlWriter.writeEndElement();
- }
- }
- }
- }
- }
- }
-
- // 保存CommandList部分
- QGroupBox *commandListBox = findChild("CommandList");
- if (commandListBox) {
- xmlWriter.writeStartElement("CommandList");
- QTableWidget *tableWidget = commandListBox->findChild();
- if (tableWidget) {
- for (int row = 0; row < tableWidget->rowCount(); ++row) {
- if (!tableWidget->item(row, 0)->text().isEmpty()) {
- xmlWriter.writeStartElement("Command");
- for (int col = 0; col < tableWidget->columnCount(); ++col) {
- QTableWidgetItem *item = tableWidget->item(row, col);
- if (item) {
- xmlWriter.writeAttribute(tableWidget->horizontalHeaderItem(col)->text(),
- item->text());
- }
- }
- xmlWriter.writeEndElement(); // Command
- }
- }
- }
- xmlWriter.writeEndElement(); // CommandList
- }
-
- // 保存Other Info部分
- QGroupBox *otherInfoBox = findChild("Other Info");
- if (otherInfoBox) {
- // 创建递归处理GroupBox的lambda函数
- std::function processGroupBox = [&](QGridLayout *layout) {
- for (int i = 0; i < layout->rowCount(); ++i) {
- QLayoutItem *labelItem = layout->itemAtPosition(i, 0);
- QLayoutItem *valueItem = layout->itemAtPosition(i, 1);
-
- if (labelItem && valueItem) {
- QLabel *label = qobject_cast(labelItem->widget());
- if (QLineEdit *lineEdit = qobject_cast(valueItem->widget())) {
- if (label && !lineEdit->text().isEmpty()) {
- // 写入最终元素及其值
- xmlWriter.writeStartElement(label->text());
- xmlWriter.writeCharacters(lineEdit->text());
- xmlWriter.writeEndElement();
- }
- }
- } else if (QGroupBox *groupBox =
- qobject_cast(layout->itemAt(i)->widget())) {
- // 递归处理子GroupBox
- xmlWriter.writeStartElement(groupBox->title());
- QGridLayout *subLayout = qobject_cast(groupBox->layout());
- if (subLayout) {
- processGroupBox(subLayout);
- }
- xmlWriter.writeEndElement();
- }
- }
- };
-
- // 开始处理Other Info GroupBox
- QGridLayout *gridLayout = qobject_cast(otherInfoBox->layout());
- if (gridLayout) {
- processGroupBox(gridLayout);
- }
- }
-
- xmlWriter.writeEndElement(); // Model
- xmlWriter.writeEndDocument();
- file.close();
-}
-
-// 保存服务配置文件
-void MainWindow::saveServiceFile(QString filePath)
-{
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- QMessageBox::warning(this, tr("Error"), tr("Failed to save file."));
- return;
- }
-
- QXmlStreamWriter xmlWriter(&file);
- xmlWriter.setAutoFormatting(true);
- xmlWriter.writeStartDocument();
- xmlWriter.writeStartElement("Service");
-
- // 保存Service Info部分
- QGroupBox *serviceInfoBox = findChild("Service Info");
- if (serviceInfoBox) {
- QGridLayout *gridLayout = qobject_cast(serviceInfoBox->layout());
- if (gridLayout) {
- for (int i = 0; i < gridLayout->rowCount(); ++i) {
- QLayoutItem *labelItem = gridLayout->itemAtPosition(i, 0);
- QLayoutItem *valueItem = gridLayout->itemAtPosition(i, 1);
-
- if (labelItem && valueItem) {
- QLabel *label = qobject_cast(labelItem->widget());
- if (QLineEdit *lineEdit = qobject_cast(valueItem->widget())) {
- if (label && !lineEdit->text().isEmpty()) {
- xmlWriter.writeStartElement(label->text());
- xmlWriter.writeCharacters(lineEdit->text());
- xmlWriter.writeEndElement();
- }
- } else if (QDateTimeEdit *dateTimeEdit =
- qobject_cast(valueItem->widget())) {
- if (label) {
- xmlWriter.writeStartElement(label->text());
- xmlWriter.writeCharacters(
- dateTimeEdit->dateTime().toString(Qt::ISODate));
- xmlWriter.writeEndElement();
- }
- }
- }
- }
- }
- }
-
- // 保存CommandList部分
- QGroupBox *commandListBox = findChild("CommandList");
- if (commandListBox) {
- xmlWriter.writeStartElement("CommandList");
- QTableWidget *tableWidget = commandListBox->findChild();
- if (tableWidget) {
- for (int row = 0; row < tableWidget->rowCount(); ++row) {
- // 只保存非空行
- if (!tableWidget->item(row, 0)->text().isEmpty()) {
- xmlWriter.writeStartElement("Command");
- for (int col = 0; col < tableWidget->columnCount(); ++col) {
- QTableWidgetItem *item = tableWidget->item(row, col);
- if (item) {
- xmlWriter.writeAttribute(tableWidget->horizontalHeaderItem(col)->text(),
- item->text());
- }
- }
- xmlWriter.writeEndElement(); // Command
- }
- }
- }
- xmlWriter.writeEndElement(); // CommandList
- }
-
- // 保存Other Info部分
- QGroupBox *otherInfoBox = findChild("Other Info");
- if (otherInfoBox) {
- // 创建递归处理GroupBox的lambda函数
- std::function processGroupBox = [&](QGridLayout *layout) {
- for (int i = 0; i < layout->rowCount(); ++i) {
- QLayoutItem *labelItem = layout->itemAtPosition(i, 0);
- QLayoutItem *valueItem = layout->itemAtPosition(i, 1);
-
- if (labelItem && valueItem) {
- QLabel *label = qobject_cast(labelItem->widget());
- if (QLineEdit *lineEdit = qobject_cast(valueItem->widget())) {
- if (label && !lineEdit->text().isEmpty()) {
- // 写入最终元素及其值
- xmlWriter.writeStartElement(label->text());
- xmlWriter.writeCharacters(lineEdit->text());
- xmlWriter.writeEndElement();
- }
- }
- } else if (QGroupBox *groupBox =
- qobject_cast(layout->itemAt(i)->widget())) {
- // 递归处理子GroupBox
- xmlWriter.writeStartElement(groupBox->title());
- QGridLayout *subLayout = qobject_cast(groupBox->layout());
- if (subLayout) {
- processGroupBox(subLayout);
- }
- xmlWriter.writeEndElement();
- }
- }
- };
-
- // 开始处理Other Info GroupBox
- QGridLayout *gridLayout = qobject_cast(otherInfoBox->layout());
- if (gridLayout) {
- processGroupBox(gridLayout);
- }
- }
-
- xmlWriter.writeEndElement(); // Service
- xmlWriter.writeEndDocument();
- file.close();
-}
-
-// 保存IDL文件
-void MainWindow::saveIDLFile(QString filePath)
-{
- //TODO 还没实现
-}
-
-// 在新窗口打开文件
-void MainWindow::openFileInNewWindow(QString fileName)
-{
- MainWindow *newWindow = new MainWindow(fileName, nullptr);
- newWindow->show();
-}
-
-// 添加一个辅助函数来连接控件的修改信号
-void MainWindow::connectModificationSignals(QWidget *widget)
-{
- if (QLineEdit *lineEdit = qobject_cast(widget)) {
- connect(lineEdit, &QLineEdit::textChanged, [this]() {
- isModified = true;
- updateWindowTitle();
- });
- } else if (QCheckBox *checkBox = qobject_cast(widget)) {
- connect(checkBox, &QCheckBox::checkStateChanged, [this]() {
- isModified = true;
- updateWindowTitle();
- });
- } else if (QTableWidget *tableWidget = qobject_cast(widget)) {
- connect(tableWidget, &QTableWidget::itemChanged, [this]() {
- isModified = true;
- updateWindowTitle();
- });
- } else if (QDateTimeEdit *dateTimeEdit = qobject_cast(widget)) {
- connect(dateTimeEdit, &QDateTimeEdit::dateTimeChanged, [this]() {
- isModified = true;
- updateWindowTitle();
- });
- }
- // 递归处理子控件
- for (QObject *child : widget->children()) {
- if (QWidget *childWidget = qobject_cast(child)) {
- connectModificationSignals(childWidget);
- }
- }
-}
-
-// 添加一个辅助函数来更新标题
-void MainWindow::updateWindowTitle()
-{
- QString title = "XNEditor";
- if (!currentFilePath.isEmpty()) {
- title += " - " + QFileInfo(currentFilePath).fileName();
- }
- if (isModified) {
- title += " *";
- }
- setWindowTitle(title);
-}
-
-// 窗口关闭事件的响应
-void MainWindow::closeEvent(QCloseEvent *event)
-{
- if (isModified) {
- onCloseFileTriggered();
- // 如果用户选择了Cancel,我们需要阻止窗口关闭
- if (isModified) {
- event->ignore();
- return;
- }
- }
- event->accept();
-}
diff --git a/XNEditor/mainwindow.h b/XNEditor/mainwindow.h
deleted file mode 100755
index b455e90..0000000
--- a/XNEditor/mainwindow.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/**
- * @file mainwindow.h
- * @author jinchao
- * @brief 主窗口类
- * @version 1.0
- * @date 2025-02-14
- *
- * @copyright Copyright (c) 2025 COMAC
- *
- */
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui
-{
-class MainWindow;
-}
-QT_END_NAMESPACE
-
-/**
- * @brief 成员变量结构体
- */
-struct MemberVariable {
- QString dataType;
- QString variableName;
- bool isArray;
- QVector arraySizes;
- QString description;
-};
-
-/**
- * @brief 结构体定义结构体
- */
-struct StructDefinition {
- QString structName;
- QVector> memberVariables;
-};
-
-/**
- * @brief 命名空间定义结构体
- */
-struct NamespaceDefinition {
- QString namespaceName;
- QVector> structDefinitions;
- QVector> childNamespaces;
-};
-
-/**
- * @brief 主窗口类
- */
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- /**
- * @brief 构造函数
- * @param parent 父窗口
- */
- MainWindow(QWidget *parent = nullptr);
- /**
- * @brief 构造函数
- * @param fileName 文件名
- * @param parent 父窗口
- */
- MainWindow(QString fileName, QWidget *parent = nullptr);
- /**
- * @brief 析构函数
- */
- ~MainWindow();
-
-public slots:
- /**
- * @brief 新建文件槽函数
- */
- void onNewFileTriggered();
- /**
- * @brief 打开文件槽函数
- */
- void onOpenFileTriggered();
- /**
- * @brief 关闭文件槽函数
- */
- void onCloseFileTriggered();
- /**
- * @brief IDL树型结构元素点击响应,
- * @param item: 树型结构元素
- */
- void onTreeWidgetItemClicked(QTreeWidgetItem *item);
-
-private:
- /**
- * @brief 初始化菜单
- */
- void initMenu();
- /**
- * @brief 初始化文件菜单
- */
- void initFileMenu();
- /**
- * @brief 初始化编辑菜单
- */
- void initEditMenu();
- /**
- * @brief 初始化中心组件
- * @param style: 中心组件类型 0:运行环境配置文件类型 1:模型/服务配置文件类型 2:IDL文件类型
- */
- void initCentralWidget(int style = 0);
- /**
- * @brief 初始化IDL树形控件
- */
- void initIDLTreeWidget();
- /**
- * @brief 打开场景配置文件
- */
- void openScenarioFile();
- /**
- * @brief 打开模型配置文件
- */
- void openModelFile();
- /**
- * @brief 打开服务配置文件
- */
- void openServiceFile();
- /**
- * @brief 打开IDL文件
- */
- void openIDLFile();
- /**
- * @brief 保存文件
- */
- void saveFile(QString filePath);
- /**
- * @brief 保存场景配置文件
- */
- void saveScenarioFile(QString filePath);
- /**
- * @brief 保存模型配置文件
- */
- void saveModelFile(QString filePath);
- /**
- * @brief 保存服务配置文件
- */
- void saveServiceFile(QString filePath);
- /**
- * @brief 保存IDL文件
- */
- void saveIDLFile(QString filePath);
- /**
- * @brief 添加组框1,label,lineEdit类型
- * @param layout 布局
- * @param name 名称
- * @param attributes 属性
- */
- void addGroupBox(QVBoxLayout *layout, QString name, QDomNamedNodeMap attributes);
- /**
- * @brief 添加组框2,comboBox类型
- * @param layout 布局
- * @param name 名称
- * @param attributes 属性
- */
- void addGroupBox2(QVBoxLayout *layout, QString name, QDomNamedNodeMap attributes);
- /**
- * @brief 添加组框3,tabwidget类型
- * @param layout 布局
- * @param name 名称
- * @param groupAttributes 组属性
- * @param vecAttributes 属性
- * @param type 类型
- */
- void addGroupBox3(QVBoxLayout *layout, QString name, QDomNamedNodeMap groupAttributes,
- QVector vecAttributes, int type);
- /**
- * @brief 向组框1中添加item
- * @param gridLayout 布局
- * @param itemName 名称
- * @param itemValue 值
- * @param itemStyle 样式
- */
- void addItemIntoGroupBox(QGridLayout *gridLayout, QString itemName, QString itemValue,
- int itemStyle);
- /**
- * @brief 设置lineEdit的规则
- * @param lineEdit lineEdit
- * @param name 名称
- */
- void setLineEditRules(QLineEdit *lineEdit, QString name);
-
- /**
- * @brief 查找模型
- * @param modelName 模型名称
- * @param ModelPath 模型路径
- * @return true 找到
- * @return false 未找到
- */
- bool findModel(QString modelName, QString ModelPath);
- /**
- * @brief 查找服务
- * @param serviceName 服务名称
- * @param ServicePath 服务路径
- * @return true 找到
- * @return false 未找到
- */
- bool findService(QString serviceName, QString ServicePath);
- /**
- * @brief 更新模型列表
- * @param tabWidget 表格
- */
- void UpdateModelList(QTableWidget *tabWidget);
- /**
- * @brief 更新服务列表
- * @param tabWidget 表格
- */
- void UpdateServiceList(QTableWidget *tabWidget);
- /**
- * @brief 在新的窗口中打开文件
- * @param fileName 文件名
- */
- void openFileInNewWindow(QString fileName);
- /**
- * @brief 连接修改信号
- * @param widget 窗口
- */
- void connectModificationSignals(QWidget *widget);
- /**
- * @brief 更新窗口标题
- */
- void updateWindowTitle();
- /**
- * @brief 添加加号按钮
- * @param layout 布局
- */
- void addPlusButton(QGridLayout *layout);
-
-public:
- /**
- * @brief 当前文件路径
- */
- QString currentFilePath;
- /**
- * @brief 当前文件类型 0: 场景配置文件 1: 模型配置文件 2: 服务配置文件 3: IDL文件
- */
- int currentFileType;
-
-private:
- /**
- * @brief 主窗口ui
- */
- Ui::MainWindow *ui;
- /**
- * @brief 模型路径
- */
- QString modelPath;
- /**
- * @brief 服务路径
- */
- QString ServicePath;
- /**
- * @brief 是否修改
- */
- bool isModified;
- /**
- * @brief 命名空间定义
- */
- QVector> namespaces;
- /**
- * @brief 根据namespaces更新IDL树形控件
- */
- void updateIDLTreeWidget();
-
-protected:
- /**
- * @brief 关闭事件
- * @param event 事件
- */
- void closeEvent(QCloseEvent *event) override;
-};
-#endif // MAINWINDOW_H
diff --git a/XNEditor/mainwindow.ui b/XNEditor/mainwindow.ui
deleted file mode 100755
index 2b1cb81..0000000
--- a/XNEditor/mainwindow.ui
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- MainWindow
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- MainWindow
-
-
-
-
-
-
-
-
diff --git a/XNIDLGen/.vscode/c_cpp_properties.json b/XNIDLGen/.vscode/c_cpp_properties.json
deleted file mode 100755
index 0b3cbd5..0000000
--- a/XNIDLGen/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "configurations": [
- {
- "compileCommands": "${workspaceFolder}/build/compile_commands.json",
- "configurationProvider": "ms-vscode.cmake-tools"
- }
- ],
- "version": 4
-}
\ No newline at end of file
diff --git a/XNIDLGen/.vscode/settings.json b/XNIDLGen/.vscode/settings.json
deleted file mode 100755
index c452776..0000000
--- a/XNIDLGen/.vscode/settings.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "files.associations": {
- "*.cpp": "cpp",
- "qfiledialog": "cpp",
- "array": "cpp",
- "chrono": "cpp",
- "compare": "cpp",
- "functional": "cpp",
- "istream": "cpp",
- "memory_resource": "cpp",
- "ostream": "cpp",
- "ranges": "cpp",
- "ratio": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "utility": "cpp",
- "variant": "cpp",
- "*.tcc": "cpp"
- }
-}
\ No newline at end of file
diff --git a/XNIDLGen/CMakeLists.txt b/XNIDLGen/CMakeLists.txt
deleted file mode 100755
index 29947b8..0000000
--- a/XNIDLGen/CMakeLists.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-project(XNIDLGen VERSION 0.1 LANGUAGES CXX)
-
-set(CMAKE_AUTOUIC ON)
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
-find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
-find_package(QXlsxQt6 REQUIRED)
-
-set(QT_SOURCE_FILE ../qdarkstyle/dark/darkstyle.qrc)
-
-# 根据 Qt 版本选择正确的资源添加函数
-qt6_add_resources(QT_RESOURCES ${QT_SOURCE_FILE})
-
-set(PROJECT_SOURCES
- main.cpp
- mainwindow.cpp
- mainwindow.h
- mainwindow.ui
- ${QT_RESOURCES}
-)
-
-if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
- qt_add_executable(XNIDLGen
- MANUAL_FINALIZATION
- ${PROJECT_SOURCES}
- )
-# Define target properties for Android with Qt 6 as:
-# set_property(TARGET XNIDLGen APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
-# ${CMAKE_CURRENT_SOURCE_DIR}/android)
-# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
-else()
- if(ANDROID)
- add_library(XNIDLGen SHARED
- ${PROJECT_SOURCES}
- )
-# Define properties for Android with Qt 5 after find_package() calls as:
-# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
- else()
- add_executable(XNIDLGen
- ${PROJECT_SOURCES}
- )
- endif()
-endif()
-
-target_link_libraries(XNIDLGen PRIVATE
- Qt${QT_VERSION_MAJOR}::Widgets
- QXlsx::QXlsx)
-
-# Check if CMAKE_INSTALL_PREFIX is set to its default value
-if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/../Release" CACHE PATH "Install path prefix" FORCE)
-endif()
-
-include(GNUInstallDirs)
-install(TARGETS XNIDLGen
- BUNDLE DESTINATION .
- LIBRARY DESTINATION .
- RUNTIME DESTINATION .
-)
-
-# Add a post-installation command to set the application icon using gio
-install(CODE "
- execute_process(COMMAND gio set -t string ${CMAKE_INSTALL_PREFIX}/XNIDLGen \"metadata::custom-icon\" \"file://${CMAKE_INSTALL_PREFIX}/resource/XNIDLGen.png\")
-")
-
-if(QT_VERSION_MAJOR EQUAL 6)
- qt_finalize_executable(XNIDLGen)
-endif()
\ No newline at end of file
diff --git a/XNIDLGen/CMakeLists.txt.user b/XNIDLGen/CMakeLists.txt.user
deleted file mode 100755
index 36a6e54..0000000
--- a/XNIDLGen/CMakeLists.txt.user
+++ /dev/null
@@ -1,421 +0,0 @@
-
-
-
-
-
- EnvironmentId
- {c0015c8c-17e0-44a4-897e-eb0bda6a867e}
-
-
- ProjectExplorer.Project.ActiveTarget
- 0
-
-
- ProjectExplorer.Project.EditorSettings
-
- true
- false
- true
-
- Cpp
-
- CppGlobal
-
-
-
- QmlJS
-
- QmlJSGlobal
-
-
- 2
- UTF-8
- false
- 4
- false
- 80
- true
- true
- 1
- 0
- false
- true
- false
- 2
- true
- true
- 0
- 8
- true
- false
- 1
- true
- true
- true
- *.md, *.MD, Makefile
- false
- true
- true
-
-
-
- ProjectExplorer.Project.PluginSettings
-
-
- true
- false
- true
- true
- true
- true
-
- false
-
-
- 0
- true
-
- true
- true
- Builtin.DefaultTidyAndClazy
- 10
- true
-
-
-
- true
-
-
-
-
- ProjectExplorer.Project.Target.0
-
- Desktop
- Desktop Qt 6.5.3 MinGW 64-bit
- Desktop Qt 6.5.3 MinGW 64-bit
- qt.qt6.653.win64_mingw_kit
- 0
- 0
- 0
-
- Debug
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_BUILD_TYPE:STRING=Debug
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
- 0
- I:\MyPrj\XNSim\XNIDLGen\build\Desktop_Qt_6_5_3_MinGW_64_bit-Debug
-
-
-
-
- all
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Debug
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- Release
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_BUILD_TYPE:STRING=Release
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
- I:\MyPrj\XNSim\XNIDLGen\build\Desktop_Qt_6_5_3_MinGW_64_bit-Release
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
- I:\MyPrj\XNSim\XNIDLGen\build\Desktop_Qt_6_5_3_MinGW_64_bit-RelWithDebInfo
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release with Debug Information
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
- 0
- I:\MyPrj\XNSim\XNIDLGen\build\Desktop_Qt_6_5_3_MinGW_64_bit-Profile
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Profile
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- MinSizeRel
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_BUILD_TYPE:STRING=MinSizeRel
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
- I:\MyPrj\XNSim\XNIDLGen\build\Desktop_Qt_6_5_3_MinGW_64_bit-MinSizeRel
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Minimum Size Release
- CMakeProjectManager.CMakeBuildConfiguration
-
- 5
-
-
- 0
- 部署
- 部署
- ProjectExplorer.BuildSteps.Deploy
-
- 1
-
- false
- ProjectExplorer.DefaultDeployConfiguration
-
- 1
-
- true
- true
- 0
- true
-
-
- 2
-
- false
- -e cpu-cycles --call-graph "dwarf,4096" -F 250
-
- ProjectExplorer.CustomExecutableRunConfiguration
-
- false
- true
- true
-
- 1
-
-
-
- ProjectExplorer.Project.TargetCount
- 1
-
-
- ProjectExplorer.Project.Updater.FileVersion
- 22
-
-
- Version
- 22
-
-
diff --git a/XNIDLGen/main.cpp b/XNIDLGen/main.cpp
deleted file mode 100755
index 13124e8..0000000
--- a/XNIDLGen/main.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "mainwindow.h"
-
-#include
-#include
-#include
-
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
-
- QFile file(":qdarkstyle/dark/darkstyle.qss");
- if (file.open(QFile::ReadOnly)) {
- QTextStream stream(&file);
- QString styleSheet = stream.readAll();
- a.setStyleSheet(styleSheet);
- }
-
- MainWindow w;
- w.show();
- return a.exec();
-}
diff --git a/XNIDLGen/mainwindow.cpp b/XNIDLGen/mainwindow.cpp
deleted file mode 100755
index 13f5798..0000000
--- a/XNIDLGen/mainwindow.cpp
+++ /dev/null
@@ -1,395 +0,0 @@
-#include "mainwindow.h"
-#include "./ui_mainwindow.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "xlsxcellrange.h"
-#include "xlsxchart.h"
-#include "xlsxchartsheet.h"
-#include "xlsxdocument.h"
-#include "xlsxrichstring.h"
-#include "xlsxworkbook.h"
-
-using namespace QXlsx;
-
-MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
-{
- ui->setupUi(this);
-
- setWindowTitle("XNSim IDL Generator");
- setWindowIcon(QIcon(":/icon/XNIDLGen.png"));
- //菜单栏
- QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
- QAction *openAction = new QAction(tr("&Open"), this);
- QAction *closeAction = new QAction(tr("&Close"), this);
-
- fileMenu->addAction(openAction);
- fileMenu->addAction(closeAction);
-
- QMenu *operationMenu = menuBar()->addMenu(tr("&Operation"));
- QAction *generateAction = new QAction(tr("Generate &IDL"), this);
- QAction *generatePrjAction = new QAction(tr("Generate &DDS Project"), this);
- operationMenu->addAction(generateAction);
- operationMenu->addAction(generatePrjAction);
-
- connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
- connect(closeAction, &QAction::triggered, this, &MainWindow::closeFile);
- connect(generateAction, &QAction::triggered, this, &MainWindow::generate);
- connect(generatePrjAction, &QAction::triggered, this, &MainWindow::generatePrj);
-
- //主界面
- QGroupBox *namespaceGroupBox = new QGroupBox(tr("Namespace"), this);
- QGridLayout *namespaceGroupBoxLayout = new QGridLayout();
- namespaceGroupBox->setLayout(namespaceGroupBoxLayout);
- QLabel *firstNamespaceLabel = new QLabel(tr("First Namespace:"), namespaceGroupBox);
- QLabel *secondNamespaceLabel = new QLabel(tr("Second Namespace:"), namespaceGroupBox);
- QLabel *thirdNamespaceLabel = new QLabel(tr("Third Namespace:"), namespaceGroupBox);
- QLabel *modelNameLabel = new QLabel(tr("Model Name:"), namespaceGroupBox);
-
- QLineEdit *firstNamespaceLineEdit = new QLineEdit(namespaceGroupBox);
- firstNamespaceLineEdit->setText("XNSim");
- firstNamespaceLineEdit->setReadOnly(true);
- firstNamespaceLineEdit->setObjectName("firstNamespaceLineEdit");
- QLineEdit *secondNamespaceLineEdit = new QLineEdit(namespaceGroupBox);
- secondNamespaceLineEdit->setObjectName("secondNamespaceLineEdit");
- QLineEdit *thirdNamespaceLineEdit = new QLineEdit(namespaceGroupBox);
- thirdNamespaceLineEdit->setObjectName("thirdNamespaceLineEdit");
- QLineEdit *modelNameLineEdit = new QLineEdit(namespaceGroupBox);
- modelNameLineEdit->setObjectName("modelNameLineEdit");
-
- namespaceGroupBoxLayout->addWidget(firstNamespaceLabel, 0, 0);
- namespaceGroupBoxLayout->addWidget(firstNamespaceLineEdit, 0, 1);
- namespaceGroupBoxLayout->addWidget(secondNamespaceLabel, 0, 2);
- namespaceGroupBoxLayout->addWidget(secondNamespaceLineEdit, 0, 3);
- namespaceGroupBoxLayout->addWidget(thirdNamespaceLabel, 1, 0);
- namespaceGroupBoxLayout->addWidget(thirdNamespaceLineEdit, 1, 1);
- namespaceGroupBoxLayout->addWidget(modelNameLabel, 1, 2);
- namespaceGroupBoxLayout->addWidget(modelNameLineEdit, 1, 3);
-
- QGroupBox *groupBox = new QGroupBox(tr("File Preview"), this);
- groupBox->setObjectName("groupBox");
- QTabWidget *tabWidget = new QTabWidget(groupBox);
- tabWidget->setObjectName("tabWidget");
-
- QWidget *tab1 = new QWidget();
- QTableWidget *table1 = new QTableWidget(10, 3, tab1); // 10 rows, 5 columns
- table1->setObjectName("table1");
- QStringList headers;
- headers << "name" << "type" << "size";
- table1->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
- table1->setHorizontalHeaderLabels(headers);
- QVBoxLayout *tab1Layout = new QVBoxLayout();
- tab1Layout->addWidget(table1);
- tab1->setLayout(tab1Layout);
-
- QWidget *tab2 = new QWidget();
- QTableWidget *table2 = new QTableWidget(10, 3, tab2); // 10 rows, 5 columns
- table2->setObjectName("table2");
- table2->setHorizontalHeaderLabels(headers);
- table2->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
- QVBoxLayout *tab2Layout = new QVBoxLayout();
- tab2Layout->addWidget(table2);
- tab2->setLayout(tab2Layout);
-
- tabWidget->addTab(tab1, tr("Inputs"));
- tabWidget->addTab(tab2, tr("Outputs"));
-
- QVBoxLayout *groupBoxLayout = new QVBoxLayout();
- groupBoxLayout->addWidget(tabWidget);
- groupBox->setLayout(groupBoxLayout);
-
- QVBoxLayout *mainLayout = new QVBoxLayout();
- mainLayout->setContentsMargins(
- 10, 10, 10, 10); // Add margins to create space between the menu bar and central widget
- mainLayout->addWidget(namespaceGroupBox);
- mainLayout->addWidget(groupBox);
-
- centralWidget()->setLayout(mainLayout);
- centralWidget()->setEnabled(false);
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-void MainWindow::openFile()
-{
- QString fileName =
- QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("ICD file (*.xlsx)"));
- if (fileName.isEmpty())
- return;
-
- QXlsx::Document xlsx(fileName);
- if (xlsx.load()) {
- setWindowTitle("XNSim IDL Generator - " + fileName);
- QStringList sheetNames = xlsx.sheetNames();
- for (const QString &sheetName : sheetNames) {
- if (sheetName == "Inputs") {
- xlsx.selectSheet(sheetName);
- QTableWidget *table1 = findChild("table1");
- table1->setRowCount(xlsx.dimension().rowCount() - 1);
- for (int col = 1; col <= xlsx.dimension().columnCount(); ++col) {
- QString columnName = xlsx.read(1, col).toString();
- if (columnName == "SACSC name" || columnName == "SACSC Name"
- || columnName == "NameSACSC") {
- for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
- QString value = xlsx.read(row, col).toString();
- if (value.isEmpty()) {
- continue;
- }
- value = value.toLower();
- table1->setItem(row - 2, 0, new QTableWidgetItem(value));
- }
- } else if (columnName == "Variable Type") {
- for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
- QString value = xlsx.read(row, col).toString();
- if (value.isEmpty()) {
- continue;
- }
- table1->setItem(row - 2, 1, new QTableWidgetItem(value));
- }
- } else if (columnName == "Variable Dimensions") {
- for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
- QString value = xlsx.read(row, col).toString();
- if (value.isEmpty()) {
- continue;
- }
- if (!value.contains("[") && value.toInt() > 1) {
- value = "[" + value + "]";
- }
- table1->setItem(row - 2, 2, new QTableWidgetItem(value));
- }
- } else {
- continue;
- }
- }
- } else if (sheetName == "Outputs") {
- xlsx.selectSheet(sheetName);
- QTableWidget *table2 = findChild("table2");
- table2->setRowCount(xlsx.dimension().rowCount() - 1);
- for (int col = 1; col <= xlsx.dimension().columnCount(); ++col) {
- QString columnName = xlsx.read(1, col).toString();
- if (columnName == "SACSC name" || columnName == "SACSC Name"
- || columnName == "NameSACSC") {
- for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
- QString value = xlsx.read(row, col).toString();
- if (value.isEmpty()) {
- continue;
- }
- value = value.toLower();
- table2->setItem(row - 2, 0, new QTableWidgetItem(value));
- }
- } else if (columnName == "Variable Type") {
- for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
- QString value = xlsx.read(row, col).toString();
- if (value.isEmpty()) {
- continue;
- }
- table2->setItem(row - 2, 1, new QTableWidgetItem(value));
- }
- } else if (columnName == "Variable Dimensions") {
- for (int row = 2; row <= xlsx.dimension().rowCount(); ++row) {
- QString value = xlsx.read(row, col).toString();
- if (value.isEmpty()) {
- continue;
- }
- if (!value.contains("[") && value.toInt() > 1) {
- value = "[" + value + "]";
- }
- table2->setItem(row - 2, 2, new QTableWidgetItem(value));
- }
- } else {
- continue;
- }
- }
- } else {
- continue;
- }
- }
- }
- centralWidget()->setEnabled(true);
-}
-
-void MainWindow::closeFile()
-{
- QTableWidget *table1 = findChild("table1");
- QTableWidget *table2 = findChild("table2");
- table1->clear();
- table2->clear();
- table1->setRowCount(0);
- table2->setRowCount(0);
- centralWidget()->setEnabled(false);
-}
-
-void MainWindow::generate()
-{
- QLineEdit *modelNameLineEdit = findChild("modelNameLineEdit");
- if (!modelNameLineEdit || modelNameLineEdit->text().isEmpty()) {
- QMessageBox::warning(this, tr("Error"), tr("Model name is empty"));
- return;
- }
- QString modelName = modelNameLineEdit->text();
- QString defaultFileName = modelName + ".idl";
- QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"),
- QDir::currentPath() + "/" + defaultFileName,
- tr("IDL Files (*.idl)"));
- if (filePath.isEmpty()) {
- return;
- }
-
- if (!filePath.endsWith(".idl", Qt::CaseInsensitive)) {
- filePath += ".idl";
- }
-
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
- return;
- }
-
- QTextStream out(&file);
- QLineEdit *firstNamespaceLineEdit = findChild("firstNamespaceLineEdit");
- QLineEdit *secondNamespaceLineEdit = findChild("secondNamespaceLineEdit");
- QLineEdit *thirdNamespaceLineEdit = findChild("thirdNamespaceLineEdit");
-
- if (firstNamespaceLineEdit) {
- out << "module " << firstNamespaceLineEdit->text() << "\n";
- out << "{\n";
- if (secondNamespaceLineEdit && !secondNamespaceLineEdit->text().isEmpty()) {
- out << "\tmodule " << secondNamespaceLineEdit->text() << "\n";
- out << "\t{\n";
- if (thirdNamespaceLineEdit && !thirdNamespaceLineEdit->text().isEmpty()) {
- out << "\t\tmodule " << thirdNamespaceLineEdit->text() << "\n";
- out << "\t\t{\n";
- genInput(modelName, "\t\t\t", out);
- genOutput(modelName, "\t\t\t", out);
- out << "\t\t};\n";
- } else {
- genInput(modelName, "\t\t", out);
- genOutput(modelName, "\t\t", out);
- }
- out << "\t};\n";
- } else {
- genInput(modelName, "\t", out);
- genOutput(modelName, "\t", out);
- }
- out << "};\n";
- }
-
- file.close();
-}
-
-void MainWindow::generatePrj()
-{
- QFileDialog fileDialog(this);
- fileDialog.setNameFilter(tr("IDL Files (*.idl)"));
- fileDialog.setViewMode(QFileDialog::Detail);
- QString idlFilePath;
- if (fileDialog.exec()) {
- idlFilePath = fileDialog.selectedFiles().first();
- }
-
- if (idlFilePath.isEmpty()) {
- return;
- }
-
- QString savePath = QFileDialog::getExistingDirectory(this, tr("Select Save Directory"),
- QString(), QFileDialog::ShowDirsOnly);
- if (savePath.isEmpty()) {
- return;
- }
-
- QDir dir(savePath);
- savePath = dir.absolutePath();
-
- QProcess process;
- QStringList arguments = QStringList()
- << "-flat-output-dir" << "-replace" << "-d" << savePath << idlFilePath;
- process.start("fastddsgen", arguments);
- process.waitForFinished();
- QString output = process.readAllStandardOutput();
-
- QMessageBox::information(this, tr("Generate DDS Project Result"), output);
-
- //TODO 生成Interface头文件和源文件
-}
-
-QString MainWindow::typeChange(QString type)
-{
- if (type == "char" || type == "unsigned char") {
- return "char";
- } else if (type == "short" || type == "unsigned short" || type == "long"
- || type == "unsigned long" || type == "long long" || type == "unsigned long long"
- || type == "float" || type == "double" || type == "long double"
- || type == "string") {
- return type;
- } else if (type == "int") {
- return "long";
- } else if (type == "unsigned int") {
- return "unsigned long";
- } else if (type == "bool") {
- return "boolean";
- } else if (type == "std::string") {
- return "string";
- }
- return "error";
-}
-
-void MainWindow::genInput(QString name, QString prefix, QTextStream &out)
-{
- out << prefix << "struct " << name << "_input" << "\n";
- out << prefix << "{\n";
- QTableWidget *table1 = findChild("table1");
- if (table1) {
- for (int row = 0; row < table1->rowCount(); ++row) {
- QString name = table1->item(row, 0)->text();
- QString type = table1->item(row, 1)->text();
- QString size = table1->item(row, 2)->text();
- if (typeChange(type) == "error") {
- QMessageBox::warning(this, tr("Error"), name + tr("is unknown type!"));
- return;
- }
- if (size.isEmpty() || size == "1") {
- out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << ";\n";
- } else {
- out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << size
- << ";\n";
- }
- }
- }
- out << prefix << "};\n";
-}
-
-void MainWindow::genOutput(QString name, QString prefix, QTextStream &out)
-{
- out << prefix << "struct " << name << "_output" << "\n";
- out << prefix << "{\n";
- QTableWidget *table2 = findChild("table2");
- if (table2) {
- for (int row = 0; row < table2->rowCount(); ++row) {
- QString name = table2->item(row, 0)->text();
- QString type = table2->item(row, 1)->text();
- QString size = table2->item(row, 2)->text();
- if (typeChange(type) == "error") {
- QMessageBox::warning(this, tr("Error"), name + tr("is unknown type!"));
- return;
- }
- if (size.isEmpty() || size == "1") {
- out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << ";\n";
- } else {
- out << prefix << "\t" << "@optional " << typeChange(type) << " " << name << size
- << ";\n";
- }
- }
- }
- out << prefix << "};\n";
-}
diff --git a/XNIDLGen/mainwindow.h b/XNIDLGen/mainwindow.h
deleted file mode 100755
index ce7844a..0000000
--- a/XNIDLGen/mainwindow.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include
-
-QT_BEGIN_NAMESPACE
-namespace Ui
-{
-class MainWindow;
-}
-QT_END_NAMESPACE
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
-
-public slots:
- void openFile();
- void closeFile();
- void generate();
- void generatePrj();
-
-private:
- QString typeChange(QString type);
- void genInput(QString name, QString prefix, QTextStream &out);
- void genOutput(QString name, QString prefix, QTextStream &out);
- Ui::MainWindow *ui;
-};
-#endif // MAINWINDOW_H
diff --git a/XNIDLGen/mainwindow.ui b/XNIDLGen/mainwindow.ui
deleted file mode 100755
index 2b1cb81..0000000
--- a/XNIDLGen/mainwindow.ui
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- MainWindow
-
-
-
- 0
- 0
- 800
- 600
-
-
-
- MainWindow
-
-
-
-
-
-
-
-
diff --git a/XNMonitor/.vscode/c_cpp_properties.json b/XNMonitor/.vscode/c_cpp_properties.json
deleted file mode 100755
index 0b3cbd5..0000000
--- a/XNMonitor/.vscode/c_cpp_properties.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "configurations": [
- {
- "compileCommands": "${workspaceFolder}/build/compile_commands.json",
- "configurationProvider": "ms-vscode.cmake-tools"
- }
- ],
- "version": 4
-}
\ No newline at end of file
diff --git a/XNMonitor/.vscode/settings.json b/XNMonitor/.vscode/settings.json
deleted file mode 100755
index 3ebd24d..0000000
--- a/XNMonitor/.vscode/settings.json
+++ /dev/null
@@ -1,90 +0,0 @@
-{
- "files.associations": {
- "*.cpp": "cpp",
- "qmainwindow": "cpp",
- "new": "cpp",
- "qstring": "cpp",
- "chrono": "cpp",
- "algorithm": "cpp",
- "qvector": "cpp",
- "array": "cpp",
- "atomic": "cpp",
- "bit": "cpp",
- "*.tcc": "cpp",
- "cctype": "cpp",
- "clocale": "cpp",
- "cmath": "cpp",
- "codecvt": "cpp",
- "compare": "cpp",
- "concepts": "cpp",
- "condition_variable": "cpp",
- "cstdarg": "cpp",
- "cstddef": "cpp",
- "cstdint": "cpp",
- "cstdio": "cpp",
- "cstdlib": "cpp",
- "cstring": "cpp",
- "ctime": "cpp",
- "cwchar": "cpp",
- "cwctype": "cpp",
- "deque": "cpp",
- "list": "cpp",
- "map": "cpp",
- "string": "cpp",
- "unordered_map": "cpp",
- "vector": "cpp",
- "exception": "cpp",
- "functional": "cpp",
- "iterator": "cpp",
- "memory": "cpp",
- "memory_resource": "cpp",
- "numeric": "cpp",
- "optional": "cpp",
- "random": "cpp",
- "ratio": "cpp",
- "source_location": "cpp",
- "string_view": "cpp",
- "system_error": "cpp",
- "tuple": "cpp",
- "type_traits": "cpp",
- "utility": "cpp",
- "future": "cpp",
- "initializer_list": "cpp",
- "iomanip": "cpp",
- "iosfwd": "cpp",
- "istream": "cpp",
- "limits": "cpp",
- "mutex": "cpp",
- "numbers": "cpp",
- "ostream": "cpp",
- "semaphore": "cpp",
- "sstream": "cpp",
- "stdexcept": "cpp",
- "stop_token": "cpp",
- "streambuf": "cpp",
- "thread": "cpp",
- "cinttypes": "cpp",
- "typeinfo": "cpp",
- "variant": "cpp",
- "ranges": "cpp",
- "shared_mutex": "cpp",
- "span": "cpp",
- "qregularexpression": "cpp",
- "qtextstream": "cpp",
- "qsplitter": "cpp",
- "qvboxlayout": "cpp",
- "qthread": "cpp",
- "*.ipp": "cpp",
- "bitset": "cpp",
- "complex": "cpp",
- "set": "cpp",
- "regex": "cpp",
- "iostream": "cpp",
- "typeindex": "cpp",
- "qmap": "cpp",
- "qmessagebox": "cpp",
- "qdebug": "cpp",
- "qscopedpointer": "cpp",
- "qmutexlocker": "cpp"
- }
-}
\ No newline at end of file
diff --git a/XNMonitor/CMakeLists.txt b/XNMonitor/CMakeLists.txt
deleted file mode 100755
index a993a22..0000000
--- a/XNMonitor/CMakeLists.txt
+++ /dev/null
@@ -1,157 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-project(XNMonitor VERSION 0.1 LANGUAGES CXX)
-
-set(CMAKE_AUTOUIC ON)
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-if(NOT fastcdr_FOUND)
- find_package(fastcdr 2 REQUIRED)
-endif()
-
-if(NOT fastdds_FOUND)
- find_package(fastdds 3 REQUIRED)
-endif()
-
-# 获取环境变量
-if(DEFINED ENV{XNCore})
- set(XNCore_PATH $ENV{XNCore})
-else()
- message(FATAL_ERROR "Environment variable XNCore is not set.")
-endif()
-
-# 添加 XNCore_PATH 下的 include 目录为包含目录
-include_directories(${XNCore_PATH}/include)
-
-file(GLOB DDS_XNIDL_SOURCES_CXX "../XNCore/XNIDL/*.cxx")
-
-add_definitions(-DQCUSTOMPLOT_USE_OPENGL)
-
-find_package(QT NAMES Qt6 Qt5 REQUIRED
- COMPONENTS Core Widgets PrintSupport
- Xml OpenGLWidgets
-)
-find_package(Qt${QT_VERSION_MAJOR} REQUIRED
- COMPONENTS Widgets PrintSupport Xml
- OpenGLWidgets
-)
-
-find_package(OpenGL REQUIRED) # 添加这一行
-find_package(OpenSSL REQUIRED)
-
-#set(QT_SOURCE_FILE qdarkstyle/light/lightstyle.qrc) # 将资源文件放到工程目录下,该部分会由RCC编译器预编译为cpp文件
-set(QT_SOURCE_FILE ../qdarkstyle/dark/darkstyle.qrc)
-
-# 根据 Qt 版本选择正确的资源添加函数
-qt6_add_resources(QT_RESOURCES ${QT_SOURCE_FILE})
-
-set(PROJECT_SOURCES
- main.cpp
- mainwindow.cpp
- mainwindow.h
- SystemStatusWidget/SystemStatusWidget.h
- SystemStatusWidget/SystemStatusWidget.cpp
- ModelStatusWidget/ModelStatusWidget.h
- ModelStatusWidget/ModelStatusWidget.cpp
- DataMonitorWidget/DataMonitorWidget.h
- DataMonitorWidget/DataMonitorWidget.cpp
- DataCollectionWidget/DataCollectionWidget.h
- DataCollectionWidget/DataCollectionWidget.cpp
- SystemStatusWidget/SystemInfoUpdateThread.h
- SystemStatusWidget/SystemInfoUpdateThread.cpp
- ModelStatusWidget/ModelInfoUpdateThread.h
- ModelStatusWidget/ModelInfoUpdateThread.cpp
- DataMonitorWidget/DataMonitorThread.h
- DataMonitorWidget/DataMonitorThread.cpp
- DataCollectionWidget/DataCollectionThread.h
- DataCollectionWidget/DataCollectionThread.cpp
- TopicManager/DataReaderListenerImpl.h
- TopicManager/TopicManager.h
- TopicManager/TopicManager.cpp
- TopicMonitorFactory/TopicMonitor.h
- TopicMonitorFactory/TopicMonitorFactory.h
- TopicMonitorFactory/TopicMonitorFactory.cpp
- ModelTopicMonitor/AerodynamicsMonitor.h
- ModelTopicMonitor/WeightBalanceMonitor.h
- ModelTopicMonitor/GroundHandlingMonitor.h
- ModelTopicMonitor/AerodynamicsMonitor.cpp
- ModelTopicMonitor/WeightBalanceMonitor.cpp
- ModelTopicMonitor/GroundHandlingMonitor.cpp
- DebugWidget/DebugWidget.h
- DebugWidget/DebugWidget.cpp
- XNCustomPlot.h
- XNCustomPlot.cpp
- qcustomplot.h
- qcustomplot.cpp
- mainwindow.ui
- TypeDefine.h
- ${QT_RESOURCES}
-)
-
-if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
- qt_add_executable(XNMonitor
- MANUAL_FINALIZATION
- ${PROJECT_SOURCES}
- ${DDS_XNIDL_SOURCES_CXX}
- )
-# Define target properties for Android with Qt 6 as:
-# set_property(TARGET XNMonitor APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
-# ${CMAKE_CURRENT_SOURCE_DIR}/android)
-# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
-else()
- if(ANDROID)
- add_library(XNMonitor SHARED
- ${PROJECT_SOURCES}
- )
-# Define properties for Android with Qt 5 after find_package() calls as:
-# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
- else()
- add_executable(XNMonitor
- ${PROJECT_SOURCES}
- ${QT_RESOURCES}
- ${DDS_XNIDL_SOURCES_CXX}
- )
- endif()
-endif()
-
-# Check if CMAKE_INSTALL_PREFIX is set to its default value
-if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/../Release" CACHE PATH "Install path prefix" FORCE)
-endif()
-
-target_link_libraries(XNMonitor PRIVATE
- Qt${QT_VERSION_MAJOR}::Widgets
- Qt${QT_VERSION_MAJOR}::PrintSupport
- Qt${QT_VERSION_MAJOR}::Xml
- Qt${QT_VERSION_MAJOR}::OpenGLWidgets
- OpenGL::GL
- fastcdr
- fastdds
- OpenSSL::SSL
- OpenSSL::Crypto
- ${CMAKE_INSTALL_PREFIX}/Models/libXNAerodynamicsInterface.so
- ${CMAKE_INSTALL_PREFIX}/Models/libXNWeightBalanceInterface.so
- ${CMAKE_INSTALL_PREFIX}/Models/libXNGroundHandlingInterface.so
-)
-
-
-
-include(GNUInstallDirs)
-install(TARGETS XNMonitor
- BUNDLE DESTINATION .
- LIBRARY DESTINATION .
- RUNTIME DESTINATION .
-)
-
-# Add a post-installation command to set the application icon using gio
-install(CODE "
- execute_process(COMMAND gio set -t string ${CMAKE_INSTALL_PREFIX}/XNMonitor \"metadata::custom-icon\" \"file://${CMAKE_INSTALL_PREFIX}/resource/XNMonitor.png\")
-")
-
-if(QT_VERSION_MAJOR EQUAL 6)
- qt_finalize_executable(XNMonitor)
-endif()
\ No newline at end of file
diff --git a/XNMonitor/CMakeLists.txt.user b/XNMonitor/CMakeLists.txt.user
deleted file mode 100755
index f51e8d2..0000000
--- a/XNMonitor/CMakeLists.txt.user
+++ /dev/null
@@ -1,423 +0,0 @@
-
-
-
-
-
- EnvironmentId
- {c0015c8c-17e0-44a4-897e-eb0bda6a867e}
-
-
- ProjectExplorer.Project.ActiveTarget
- 0
-
-
- ProjectExplorer.Project.EditorSettings
-
- true
- false
- true
-
- Cpp
-
- CppGlobal
-
-
-
- QmlJS
-
- QmlJSGlobal
-
-
- 2
- UTF-8
- false
- 4
- false
- 80
- true
- true
- 1
- 0
- false
- true
- false
- 2
- true
- true
- 0
- 8
- true
- false
- 1
- true
- true
- true
- *.md, *.MD, Makefile
- false
- true
- true
-
-
-
- ProjectExplorer.Project.PluginSettings
-
-
- true
- false
- true
- true
- true
- true
-
- false
-
-
- 0
- true
-
- true
- true
- Builtin.DefaultTidyAndClazy
- 10
- true
-
-
-
- true
-
-
-
-
- ProjectExplorer.Project.Target.0
-
- Desktop
- Desktop Qt 6.5.3 MinGW 64-bit
- Desktop Qt 6.5.3 MinGW 64-bit
- qt.qt6.653.win64_mingw_kit
- 0
- 0
- 0
-
- Debug
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_BUILD_TYPE:STRING=Debug
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- 0
- I:\MyPrj\MyQtPrj\XNMonitor\build\Desktop_Qt_6_5_3_MinGW_64_bit-Debug
-
-
-
-
- all
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- 构建
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Debug
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- Release
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_BUILD_TYPE:STRING=Release
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- I:\MyPrj\MyQtPrj\XNMonitor\build\Desktop_Qt_6_5_3_MinGW_64_bit-Release
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- I:\MyPrj\MyQtPrj\XNMonitor\build\Desktop_Qt_6_5_3_MinGW_64_bit-RelWithDebInfo
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Release with Debug Information
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- RelWithDebInfo
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- 0
- I:\MyPrj\MyQtPrj\XNMonitor\build\Desktop_Qt_6_5_3_MinGW_64_bit-Profile
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Profile
- CMakeProjectManager.CMakeBuildConfiguration
-
-
- MinSizeRel
- 2
- false
-
- -DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
--DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
--DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
--DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
--DCMAKE_BUILD_TYPE:STRING=MinSizeRel
--DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
--DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
--DCMAKE_GENERATOR:STRING=Ninja
- I:\MyPrj\MyQtPrj\XNMonitor\build\Desktop_Qt_6_5_3_MinGW_64_bit-MinSizeRel
-
-
-
-
- all
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 构建
- 构建
- ProjectExplorer.BuildSteps.Build
-
-
-
-
-
- clean
-
- false
-
- true
- CMakeProjectManager.MakeStep
-
- 1
- 清除
- 清除
- ProjectExplorer.BuildSteps.Clean
-
- 2
- false
-
- false
-
- Minimum Size Release
- CMakeProjectManager.CMakeBuildConfiguration
-
- 5
-
-
- 0
- 部署
- 部署
- ProjectExplorer.BuildSteps.Deploy
-
- 1
-
- false
- ProjectExplorer.DefaultDeployConfiguration
-
- 1
-
- true
- true
- 0
- true
-
-
- 2
-
- false
- -e cpu-cycles --call-graph "dwarf,4096" -F 250
- XNMonitor
- CMakeProjectManager.CMakeRunConfiguration.XNMonitor
- XNMonitor
- false
- true
- true
- true
- I:/MyPrj/MyQtPrj/XNMonitor/build/Desktop_Qt_6_5_3_MinGW_64_bit-Debug
-
- 1
-
-
-
- ProjectExplorer.Project.TargetCount
- 1
-
-
- ProjectExplorer.Project.Updater.FileVersion
- 22
-
-
- Version
- 22
-
-
diff --git a/XNMonitor/DataCollectionWidget/DataCollectionThread.cpp b/XNMonitor/DataCollectionWidget/DataCollectionThread.cpp
deleted file mode 100755
index c9800bb..0000000
--- a/XNMonitor/DataCollectionWidget/DataCollectionThread.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include
-#include "DataCollectionThread.h"
-
-DataCollectionThread::DataCollectionThread(QVector collectionDataNames,
- double collectionFrequency,
- double collectionTime,
- QString collectionPath) :
- m_CollectionFrequency(collectionFrequency),
- m_CollectionTime(collectionTime),
- m_CollectionPath(collectionPath) {
- for (const QString &dataName : collectionDataNames) {
- m_CollectionDataMap[dataName] = QVector();
- }
-}
-
-void DataCollectionThread::run() {
- double collectionPeriod = 1.0 / m_CollectionFrequency;
- for (double time = m_CollectionTime; time > 0; time -= collectionPeriod) {
- for (const QString &dataName : m_CollectionDataMap.keys()) {
- m_CollectionDataMap[dataName] << generateTestCollectionData();
- }
- //如果time为整数,则更新时间
- if (time - static_cast(time) < collectionPeriod) {
- emit UpdateDataCollectionTime(static_cast(time));
- }
- msleep(collectionPeriod * 1000);
- }
-
- QString timeStamp = QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
- QString fileName = m_CollectionPath + "/data" + timeStamp + ".csv";
-
- //保存数据
- QFile file(fileName);
- file.open(QIODevice::WriteOnly | QIODevice::Text);
- QTextStream out(&file);
- out << "Time";
- for (const QString &dataName : m_CollectionDataMap.keys()) {
- out << "," << dataName;
- }
- out << "\n";
- for (int i = 0; i < m_CollectionDataMap[m_CollectionDataMap.keys().first()].size(); i++) {
- out << i * collectionPeriod;
- for (const QString &dataName : m_CollectionDataMap.keys()) {
- out << "," << m_CollectionDataMap[dataName][i];
- }
- out << "\n";
- }
- file.close();
- emit DataCollectionStatus(true, fileName);
-}
-
-void DataCollectionThread::onStopDataCollection() {
- quit();
- emit DataCollectionStatus(false, QString(""));
-}
-
-template
-T DataCollectionThread::generateTestCollectionData() {
- std::random_device rd; // 用于获取随机数种子
- std::mt19937 gen(rd()); // Mersenne Twister随机数生成器
- std::uniform_real_distribution<> dis(-1.0, 1.0); // [-1.0, 1.0)范围内的均匀分布
- return (T)(dis(gen) + 100);
-}
-
diff --git a/XNMonitor/DataCollectionWidget/DataCollectionThread.h b/XNMonitor/DataCollectionWidget/DataCollectionThread.h
deleted file mode 100755
index 95a07fe..0000000
--- a/XNMonitor/DataCollectionWidget/DataCollectionThread.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-class DataCollectionThread : public QThread
-{
- Q_OBJECT
-public:
- DataCollectionThread(QVector collectionDataNames, double collectionFrequency,
- double collectionTime, QString collectionPath);
-
-protected:
- void run() override;
-signals:
- void DataCollectionStatus(const bool &status, const QString &filePath);
- void UpdateDataCollectionTime(const unsigned int &time);
-
-public slots:
- void onStopDataCollection();
-
-private:
- template
- T generateTestCollectionData();
- QMap> m_CollectionDataMap;
- double m_CollectionFrequency;
- double m_CollectionTime;
- QString m_CollectionPath;
-};
diff --git a/XNMonitor/DataCollectionWidget/DataCollectionWidget.cpp b/XNMonitor/DataCollectionWidget/DataCollectionWidget.cpp
deleted file mode 100755
index 6727262..0000000
--- a/XNMonitor/DataCollectionWidget/DataCollectionWidget.cpp
+++ /dev/null
@@ -1,790 +0,0 @@
-#include "DataCollectionWidget.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-DataCollectionWidget::DataCollectionWidget(QWidget *parent) : QWidget(parent)
-{
- setupTabDataCollection();
-}
-
-DataCollectionWidget::~DataCollectionWidget()
-{
-}
-
-void DataCollectionWidget::onSetCurrentTabIndex(int index)
-{
- this->currentTabIndex = index;
- if (currentTabIndex == 3) {
- this->show();
- } else {
- this->hide();
- }
-}
-
-// 设置数据采集标签页
-void DataCollectionWidget::setupTabDataCollection()
-{
- // 修改这里:从 dataMonitoringContent 改为 dataCollectionContent
- QHBoxLayout *mainLayout = new QHBoxLayout(this); // 创建水平布局
-
- // 使用QSplitter进行左右栏的动态分割
- QSplitter *horizontalSplitter = new QSplitter(Qt::Horizontal); // 创建一个水平方向的QSplitter
-
- // 左栏布局
- setupTabDataCollectionLeftPanel(horizontalSplitter);
-
- // 右栏布局
- setupTabDataCollectionRightPanel(horizontalSplitter);
-
- // 设置QSplitter的初始分割比例为1:4,即左栏占五分之一,右栏占五分之四
- horizontalSplitter->setStretchFactor(0, 1); // 左侧面板的拉伸因子为1
- horizontalSplitter->setStretchFactor(1, 4); // 右侧面板的拉伸因子为4
-
- // 将QSplitter添加到主布局中
- mainLayout->addWidget(horizontalSplitter);
-}
-
-void DataCollectionWidget::setupTabDataCollectionLeftPanel(QSplitter *horizontalSplitter)
-{
- // 创建垂直布局
- QVBoxLayout *leftLayout = new QVBoxLayout();
-
- // 创建树形控件
- QTreeWidget *treeWidget = new QTreeWidget();
- treeWidget->setHeaderLabels({"数据采集项", "操作"});
- treeWidget->setColumnCount(2);
-
- // 设置列宽模式和固定宽度
- treeWidget->header()->setSectionResizeMode(0, QHeaderView::Stretch); // 第一列自动伸展
- treeWidget->header()->setSectionResizeMode(1, QHeaderView::Fixed); // 第二列固定宽度
- treeWidget->setColumnWidth(1, 100); // 设置第二列宽度为100像素
- treeWidget->header()->setStretchLastSection(false); // 禁止最后一列自动伸展
-
- // 添加树形控件到布局
- leftLayout->addWidget(treeWidget);
-
- // 创建水平布局来放置按钮
- QHBoxLayout *buttonLayout1 = new QHBoxLayout();
-
- // 创建添加数据和清空数据按钮
- QPushButton *addDataButton = new QPushButton("添加数据");
- QPushButton *addDataProfileButton = new QPushButton("添加采集模板");
- QPushButton *clearDataButton = new QPushButton("清空数据");
-
- // 连接添加数据按钮的点击信号
- connect(addDataButton, &QPushButton::clicked, this, [=]() {
- // 创建输入对话框
- bool ok;
- QString dataName = QInputDialog::getText(this, "添加数据接口",
- "请输入数据接口名称:", QLineEdit::Normal, "", &ok);
-
- // 如果用户点击确定且输入不为空
- if (ok && !dataName.isEmpty()) {
- // 创建新的树节点
- QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
- item->setText(0, dataName); // 设置第一列为数据名称
-
- // 创建删除按钮
- QPushButton *deleteButton = new QPushButton("删除");
- treeWidget->setItemWidget(item, 1, deleteButton); // 设置第二列为删除按钮
-
- // 连接删除按钮的点击信号
- connect(deleteButton, &QPushButton::clicked, this, [=]() {
- // 获取按钮所在的item的索引
- int index = treeWidget->indexOfTopLevelItem(item);
- if (index != -1) {
- // 删除该项
- delete treeWidget->takeTopLevelItem(index);
- }
- });
- }
- });
-
- // 连接清空数据按钮的点击信号
- connect(clearDataButton, &QPushButton::clicked, this, [=]() {
- // 弹出确认对话框
- QMessageBox::StandardButton reply;
- reply = QMessageBox::question(this, "确认清空", "确定要清空所有数据吗?",
- QMessageBox::Yes | QMessageBox::No);
-
- if (reply == QMessageBox::Yes) {
- treeWidget->clear(); // 清空树形控件
- }
- });
-
- // 将按钮添加到水平布局中
- buttonLayout1->addWidget(addDataButton);
- buttonLayout1->addWidget(addDataProfileButton);
- buttonLayout1->addWidget(clearDataButton);
-
- // 将水平按钮布局添加到左侧主布局中
- leftLayout->addLayout(buttonLayout1);
-
- // 创建按钮布局
- QVBoxLayout *buttonLayout = new QVBoxLayout();
-
- // 创建上部分网格布局
- QGridLayout *gridLayout = new QGridLayout();
-
- // 第一列 - Labels
- QLabel *freqLabel = new QLabel("采集频率");
- QLabel *durationLabel = new QLabel("采集时长");
- QLabel *pathLabel = new QLabel("保存路径");
- gridLayout->addWidget(freqLabel, 0, 0);
- gridLayout->addWidget(durationLabel, 1, 0);
- gridLayout->addWidget(pathLabel, 2, 0);
-
- // 第二列 - LineEdits
- QLineEdit *freqEdit = new QLineEdit();
- freqEdit->setPlaceholderText("请输入采集频率");
- QLineEdit *durationEdit = new QLineEdit();
- durationEdit->setPlaceholderText("请输入采集时长");
- QLineEdit *pathEdit = new QLineEdit();
- pathEdit->setPlaceholderText("请输入保存路径");
- gridLayout->addWidget(freqEdit, 0, 1);
- gridLayout->addWidget(durationEdit, 1, 1);
- gridLayout->addWidget(pathEdit, 2, 1);
-
- // 设置输入验证器,只允许输入数字和小数点
- QDoubleValidator *doubleValidator = new QDoubleValidator(0, 999999, 6, this);
- doubleValidator->setNotation(QDoubleValidator::StandardNotation);
- freqEdit->setValidator(doubleValidator);
- durationEdit->setValidator(doubleValidator);
-
- // 第三列 - 单位标签和选择按钮
- QLabel *hzLabel = new QLabel("Hz");
- QLabel *sLabel = new QLabel("s");
- QPushButton *selectPathButton = new QPushButton("...");
- gridLayout->addWidget(hzLabel, 0, 2);
- gridLayout->addWidget(sLabel, 1, 2);
- gridLayout->addWidget(selectPathButton, 2, 2);
-
- // 连接选择路径按钮的点击信号
- connect(selectPathButton, &QPushButton::clicked, this, [=]() {
- QString dir = QFileDialog::getExistingDirectory(this, "选择保存路径", QDir::currentPath(),
- QFileDialog::ShowDirsOnly
- | QFileDialog::DontResolveSymlinks);
- if (!dir.isEmpty()) {
- pathEdit->setText(dir);
- }
- });
-
- connect(addDataProfileButton, &QPushButton::clicked, this, [=]() {
- // 弹出文件选择对话框
- QString fileName = QFileDialog::getOpenFileName(this, "选择采集模板", QDir::currentPath(),
- "采集模板文件 (*.xml)");
- if (!fileName.isEmpty()) {
-
- QFile file(fileName);
- file.open(QIODevice::ReadOnly | QIODevice::Text);
- QDomDocument doc;
- if (!doc.setContent(&file)) {
- QMessageBox::warning(this, "错误", "无法解析XML文件");
- return;
- }
-
- QDomElement root = doc.documentElement();
- if (root.tagName() != "DataCollection") {
- QMessageBox::warning(this, "错误", "无效的XML格式");
- return;
- }
-
- // 读取采集数据名称
- QDomElement collectionData = root.firstChildElement("CollectionData");
- if (!collectionData.isNull()) {
- QDomElement dataName = collectionData.firstChildElement("DataName");
- while (!dataName.isNull()) {
- QString name = dataName.text();
-
- // 创建新的树节点
- QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget);
- item->setText(0, name);
-
- // 创建删除按钮
- QPushButton *deleteButton = new QPushButton("删除");
- treeWidget->setItemWidget(item, 1, deleteButton);
-
- // 连接删除按钮的点击信号
- connect(deleteButton, &QPushButton::clicked, this, [=]() {
- int index = treeWidget->indexOfTopLevelItem(item);
- if (index != -1) {
- delete treeWidget->takeTopLevelItem(index);
- }
- });
-
- dataName = dataName.nextSiblingElement("DataName");
- }
- }
-
- // 读取并设置采集频率
- QDomElement freqElement = root.firstChildElement("DataFrequency");
- if (!freqElement.isNull()) {
- freqEdit->setText(freqElement.text());
- }
-
- // 读取并设置采集时长
- QDomElement timeElement = root.firstChildElement("DataTime");
- if (!timeElement.isNull()) {
- durationEdit->setText(timeElement.text());
- }
-
- // 读取并设置保存路径
- QDomElement pathElement = root.firstChildElement("DataPath");
- if (!pathElement.isNull()) {
- pathEdit->setText(pathElement.text());
- }
-
- file.close();
- }
- });
-
- // 添加网格布局到按钮布局
- buttonLayout->addLayout(gridLayout);
-
- // 创建水平布局用于底部按钮
- QHBoxLayout *bottomButtonLayout = new QHBoxLayout();
-
- // 创建开始和终止按钮
- QPushButton *startButton = new QPushButton("开始采集");
- startButton->setObjectName("startDataCollectionButton");
- QPushButton *stopButton = new QPushButton("终止采集");
- bottomButtonLayout->addWidget(startButton);
- bottomButtonLayout->addWidget(stopButton);
-
- connect(startButton, &QPushButton::clicked, this, [=]() {
- if (treeWidget->topLevelItemCount() == 0) {
- QMessageBox::warning(this, "提示", "请先添加数据接口");
- return;
- }
- QStringList collectionDataNames;
- for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) {
- collectionDataNames << treeWidget->topLevelItem(i)->text(0);
- }
- if (freqEdit->text().isEmpty() || durationEdit->text().isEmpty()
- || pathEdit->text().isEmpty()) {
- QMessageBox::warning(this, "提示", "请填写采集频率、采集时长和保存路径");
- return;
- }
- double collectionFrequency = freqEdit->text().toDouble();
- double collectionTime = durationEdit->text().toDouble();
- QString collectionPath = pathEdit->text();
- DataCollectionThread *dataCollectionThread = new DataCollectionThread(
- collectionDataNames, collectionFrequency, collectionTime, collectionPath);
- connect(dataCollectionThread, &DataCollectionThread::DataCollectionStatus, this,
- &DataCollectionWidget::onDataCollectionStatus);
- connect(dataCollectionThread, &DataCollectionThread::UpdateDataCollectionTime, this,
- &DataCollectionWidget::onUpdateDataCollectionTime);
- connect(this, &DataCollectionWidget::stopDataCollection, dataCollectionThread,
- &DataCollectionThread::onStopDataCollection);
- dataCollectionThread->start();
- startButton->setEnabled(false);
- });
-
- connect(stopButton, &QPushButton::clicked, this, [=]() { emit stopDataCollection(); });
-
- // 添加底部按钮布局到主按钮布局
- buttonLayout->addLayout(bottomButtonLayout);
-
- // 将按钮布局添加到主布局
- leftLayout->addLayout(buttonLayout);
-
- // 创建一个QWidget作为左栏的容器,并设置其布局为leftLayout
- QWidget *leftPanel = new QWidget();
- leftPanel->setLayout(leftLayout);
-
- horizontalSplitter->addWidget(leftPanel);
-}
-
-void DataCollectionWidget::onUpdateDataCollectionTime(const unsigned int newTime)
-{
- QPushButton *startButton = findChild("startDataCollectionButton");
- if (startButton) {
- startButton->setText(QString::number(newTime));
- }
-}
-
-void DataCollectionWidget::onDataCollectionStatus(const bool &status, const QString &filePath)
-{
- QPushButton *startButton = findChild("startDataCollectionButton");
- if (startButton) {
- if (status) {
- QMessageBox::StandardButton reply = QMessageBox::question(
- this, "提示",
- QString("数据采集完成,文件已保存至:%1\n是否立即打开文件?").arg(filePath),
- QMessageBox::Yes | QMessageBox::No);
-
- if (reply == QMessageBox::Yes) {
- openDataCollectionFile(filePath);
- }
- } else {
- QMessageBox::information(this, "提示", "数据采集异常终止");
- }
- startButton->setText("开始采集");
- startButton->setEnabled(true);
- }
-}
-
-void DataCollectionWidget::setupTabDataCollectionRightPanel(QSplitter *horizontalSplitter)
-{
- QWidget *rightPanel = new QWidget();
- horizontalSplitter->addWidget(rightPanel);
-
- // 创建右侧面板的主布局
- QHBoxLayout *rightLayout = new QHBoxLayout(rightPanel);
-
- // 创建左侧的TabWidget
- QTabWidget *leftTabWidget = new QTabWidget();
- leftTabWidget->setTabPosition(QTabWidget::North);
- leftTabWidget->setMovable(true);
- leftTabWidget->setTabsClosable(true); // 设置所有标签页可关闭
- dataPlotIndex = 0;
-
- // 创建默认的第一个标签页
- QWidget *firstTab = new QWidget();
- QVBoxLayout *firstTabLayout = new QVBoxLayout(firstTab);
- XNCustomPlot *plot = new XNCustomPlot();
- plot->setObjectName(QString("dataPlot%1").arg(dataPlotIndex));
- setupPlotWidget(plot);
- firstTabLayout->addWidget(plot);
- plot->addGraph();
- plot->graph(0)->setPen(QPen(Qt::green, 2));
- plot->addGraph();
- plot->graph(1)->setPen(QPen(Qt::red, 2));
- firstTabLayout->addWidget(plot);
- int firstTabIndex = leftTabWidget->addTab(firstTab, QString("绘图%1").arg(dataPlotIndex));
- dataPlotIndex++;
-
- // 添加"+"标签页
- QWidget *addTab = new QWidget();
- int addTabIndex = leftTabWidget->addTab(addTab, "+");
-
- // 移除"+"标签页的关闭按钮
- leftTabWidget->tabBar()->setTabButton(addTabIndex, QTabBar::RightSide, nullptr);
-
- // 连接标签切换信号
- connect(leftTabWidget, &QTabWidget::currentChanged, [=](int index) {
- if (index == leftTabWidget->count() - 1) {
- if (leftTabWidget->property("ignoreChange").toBool()) {
- leftTabWidget->setCurrentIndex(0);
- return;
- }
-
- // 如果点击了"+"标签(且不是因为删除标签页导致的切换)
- int newIndex = leftTabWidget->count() - 1;
-
- // 创建新的标签页
- QWidget *newTab = new QWidget();
- QVBoxLayout *newTabLayout = new QVBoxLayout(newTab);
- XNCustomPlot *newPlot = new XNCustomPlot();
- newPlot->setObjectName(QString("dataPlot%1").arg(dataPlotIndex));
- setupPlotWidget(newPlot);
- newPlot->addGraph();
- newPlot->graph(0)->setPen(QPen(Qt::green, 2));
- newPlot->addGraph();
- newPlot->graph(1)->setPen(QPen(Qt::red, 2));
- newTabLayout->addWidget(newPlot);
-
- // 在"+"标签之前插入新标签
- leftTabWidget->insertTab(newIndex, newTab, QString("绘图%1").arg(dataPlotIndex));
- dataPlotIndex++;
-
- // 选中新创建的标签
- leftTabWidget->setCurrentIndex(newIndex);
- }
- XNCustomPlot *currentPlot = findChild(QString("dataPlot%1").arg(index));
- if (currentPlot) {
- currentPlot->setOpenGl(false);
- currentPlot->replot();
- currentPlot->setOpenGl(true);
- currentPlot->replot();
- }
- });
-
- // 连接标签关闭信号
- connect(leftTabWidget, &QTabWidget::tabCloseRequested, [=](int index) {
- // 设置标记,表示即将因为删除标签页而改变当前标签
- leftTabWidget->setProperty("ignoreChange", true);
-
- // 删除指定的标签页
- leftTabWidget->removeTab(index);
-
- // 如果删除后只剩下"+"标签页,则创建一个新的标签页
- if (leftTabWidget->count() == 1) {
- QWidget *newTab = new QWidget();
- QVBoxLayout *newTabLayout = new QVBoxLayout(newTab);
- XNCustomPlot *newPlot = new XNCustomPlot();
- newPlot->setObjectName("dataPlot1");
- setupPlotWidget(newPlot);
- newPlot->addGraph();
- newPlot->graph(0)->setPen(QPen(Qt::green, 2));
- newPlot->addGraph();
- newPlot->graph(1)->setPen(QPen(Qt::red, 2));
- newTabLayout->addWidget(newPlot);
-
- // 在"+"标签之前插入新标签
- leftTabWidget->insertTab(0, newTab, QString("绘图%1").arg(dataPlotIndex));
- leftTabWidget->setCurrentIndex(0);
- dataPlotIndex++;
- }
-
- // 清除标记
- leftTabWidget->setProperty("ignoreChange", false);
- });
-
- // 创建右侧的垂直布局,用于放置两个TreeWidget
- QVBoxLayout *rightTreeLayout = new QVBoxLayout();
-
- // 创建上部TreeWidget
- QTreeWidget *collectionDataTreeWidget = new QTreeWidget();
- collectionDataTreeWidget->setHeaderLabel("采集数据");
- collectionDataTreeWidget->setObjectName("collectionDataTreeWidget");
-
- connect(collectionDataTreeWidget, &QTreeWidget::itemClicked, this,
- [=](QTreeWidgetItem *item, int column) {
- QString varName = item->text(0);
- if (collectionData.contains(varName)) {
- int currentIndex = leftTabWidget->currentIndex();
- QCustomPlot *currentPlot =
- findChild(QString("dataPlot%1").arg(currentIndex));
- if (currentPlot) {
- currentPlot->graph(0)->setData(collectionData["Time"],
- collectionData[varName]);
- currentPlot->graph(0)->setPen(QPen(Qt::green, 2));
- currentPlot->graph(0)->setName(varName);
- // 自动调整坐标轴范围以适应数据
- currentPlot->xAxis->rescale();
- currentPlot->yAxis->rescale();
- // 设置图例
- currentPlot->legend->setVisible(true);
- currentPlot->legend->setFont(QFont("Helvetica", 10));
-
- currentPlot->replot();
- }
- }
- });
-
- // 创建水平布局用于放置按钮
- QHBoxLayout *collectionDataButtonLayout = new QHBoxLayout();
-
- // 创建打开和关闭按钮
- QPushButton *openCollectionDataButton = new QPushButton("打开");
- QPushButton *closeCollectionDataButton = new QPushButton("关闭");
-
- connect(openCollectionDataButton, &QPushButton::clicked, this, [=]() {
- QString fileName = QFileDialog::getOpenFileName(
- this, "选择采集数据文件", QDir::currentPath(), "采集数据文件 (*.csv)");
- openDataCollectionFile(fileName);
- });
-
- connect(closeCollectionDataButton, &QPushButton::clicked, this, [=]() {
- collectionData.clear();
- collectionDataTreeWidget->clear();
- });
-
- // 将按钮添加到水平布局
- collectionDataButtonLayout->addWidget(openCollectionDataButton);
- collectionDataButtonLayout->addWidget(closeCollectionDataButton);
-
- // 创建一个容器widget来容纳按钮布局
- QWidget *collectionDataButtonContainer = new QWidget();
- collectionDataButtonContainer->setLayout(collectionDataButtonLayout);
-
- // 创建下部TreeWidget
- QTreeWidget *referenceDataTreeWidget = new QTreeWidget();
- referenceDataTreeWidget->setHeaderLabel("参考数据");
-
- connect(referenceDataTreeWidget, &QTreeWidget::itemClicked, this,
- [=](QTreeWidgetItem *item, int column) {
- QString varName = item->text(0);
- if (referenceData.contains(varName)) {
- int currentIndex = leftTabWidget->currentIndex();
- QCustomPlot *currentPlot =
- findChild(QString("dataPlot%1").arg(currentIndex));
- if (currentPlot) {
- currentPlot->graph(1)->setData(referenceData["Time"],
- referenceData[varName]);
- currentPlot->graph(1)->setPen(QPen(Qt::red, 2));
- currentPlot->graph(1)->setName(varName);
- // 自动调整坐标轴范围以适应数据
- currentPlot->xAxis->rescale();
- currentPlot->yAxis->rescale();
- // 设置图例
- currentPlot->legend->setVisible(true);
- currentPlot->legend->setFont(QFont("Helvetica", 10));
- currentPlot->replot();
- }
- }
- });
-
- QHBoxLayout *referenceDataButtonLayout = new QHBoxLayout();
-
- QPushButton *openReferenceDataButton = new QPushButton("打开");
- QPushButton *closeReferenceDataButton = new QPushButton("关闭");
-
- connect(openReferenceDataButton, &QPushButton::clicked, this, [=]() {
- QString fileName = QFileDialog::getOpenFileName(
- this, "选择参考数据文件", QDir::currentPath(), "参考数据文件 (*.csv)");
- if (!fileName.isEmpty()) {
- QFile file(fileName);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QTextStream in(&file);
-
- // 读取第一行作为标题
- QString headerLine = in.readLine();
- QStringList headers = headerLine.split(",");
-
- referenceData["Time"] = QVector();
- // 第一次读取时,从headers中获取变量名并初始化vectors
- if (referenceData.isEmpty()) {
- for (int i = 1; i < headers.size(); i++) {
- referenceData[headers[i]] = QVector();
- }
- }
-
- // 清空现有数据
- referenceData.clear();
-
- while (!in.atEnd()) {
- QString line = in.readLine();
- QStringList fields = line.split(",");
-
- referenceData["Time"].append(fields[0].toDouble());
- for (int i = 1; i < fields.size() && i < headers.size(); i++) {
- bool ok;
- double value = fields[i].toDouble(&ok);
- if (ok) {
- referenceData[headers[i]].append(value);
- }
- }
- }
-
- file.close();
-
- // 清空现有树形结构
- referenceDataTreeWidget->clear();
-
- // 将第一列数据名称添加到树形结构中
- for (auto it = referenceData.begin(); it != referenceData.end(); ++it) {
- if (it.key() != "" && it.key() != "Time") {
- QTreeWidgetItem *item = new QTreeWidgetItem(referenceDataTreeWidget);
- item->setText(0, it.key());
- }
- }
- } else {
- QMessageBox::warning(this, "错误", "无法打开文件!");
- }
- }
- });
-
- connect(closeReferenceDataButton, &QPushButton::clicked, this, [=]() {
- referenceData.clear();
- referenceDataTreeWidget->clear();
- });
-
- referenceDataButtonLayout->addWidget(openReferenceDataButton);
- referenceDataButtonLayout->addWidget(closeReferenceDataButton);
-
- QWidget *referenceDataButtonContainer = new QWidget();
- referenceDataButtonContainer->setLayout(referenceDataButtonLayout);
-
- // 将两个TreeWidget添加到右侧垂直布局
- rightTreeLayout->addWidget(collectionDataTreeWidget);
- // 将按钮容器添加到右侧垂直布局
- rightTreeLayout->addWidget(collectionDataButtonContainer);
- // 将参考数据TreeWidget添加到右侧垂直布局
- rightTreeLayout->addWidget(referenceDataTreeWidget);
- // 将按钮容器添加到右侧垂直布局
- rightTreeLayout->addWidget(referenceDataButtonContainer);
-
- // 创建一个容器widget来容纳右侧的树形视图
- QWidget *rightTreeContainer = new QWidget();
- rightTreeContainer->setLayout(rightTreeLayout);
-
- // 创建一个水平分割器来分隔TabWidget和右侧树形视图
- QSplitter *rightSplitter = new QSplitter(Qt::Horizontal);
- rightSplitter->addWidget(leftTabWidget);
- rightSplitter->addWidget(rightTreeContainer);
- rightSplitter->setStretchFactor(0, 4); // TabWidget占据更多空间
- rightSplitter->setStretchFactor(1, 1);
-
- // 将分割器添加到右侧面板的主布局
- rightLayout->addWidget(rightSplitter);
- rightLayout->setContentsMargins(0, 0, 0, 0);
-}
-
-void DataCollectionWidget::openDataCollectionFile(const QString &filePath)
-{
- if (!filePath.isEmpty()) {
- QFile file(filePath);
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QTextStream in(&file);
-
- // 读取第一行作为标题
- QString headerLine = in.readLine();
- QStringList headers = headerLine.split(",");
-
- collectionData["Time"] = QVector();
- // 第一次读取时,从headers中获取变量名并初始化vectors
- if (collectionData.isEmpty()) {
- for (int i = 1; i < headers.size(); i++) {
- collectionData[headers[i]] = QVector();
- }
- }
-
- // 清空现有数据
- collectionData.clear();
-
- while (!in.atEnd()) {
- QString line = in.readLine();
- QStringList fields = line.split(",");
-
- collectionData["Time"].append(fields[0].toDouble());
- // 将每一列的数据添加到对应变量名的vector中
- for (int i = 1; i < fields.size() && i < headers.size(); i++) {
- bool ok;
- double value = fields[i].toDouble(&ok);
- if (ok) {
- collectionData[headers[i]].append(value);
- }
- }
- }
-
- file.close();
-
- QTreeWidget *collectionDataTreeWidget =
- findChild("collectionDataTreeWidget");
- if (collectionDataTreeWidget) {
- // 清空现有树形结构
- collectionDataTreeWidget->clear();
-
- // 将第一列数据名称添加到树形结构中
- for (auto it = collectionData.begin(); it != collectionData.end(); ++it) {
- if (it.key() != "" && it.key() != "Time") {
- QTreeWidgetItem *item = new QTreeWidgetItem(collectionDataTreeWidget);
- item->setText(0, it.key());
- }
- }
- }
- } else {
- QMessageBox::warning(this, "错误", "无法打开文件!");
- }
- }
-}
-
-void DataCollectionWidget::setupPlotWidget(XNCustomPlot *customPlot)
-{
- customPlot->setBackground(QBrush(QColor("#19232D")));
- customPlot->xAxis->setLabelColor(Qt::white);
- customPlot->yAxis->setLabelColor(Qt::white);
- customPlot->xAxis->setLabel("时间(s)");
- customPlot->yAxis->setLabel("值");
- customPlot->xAxis->setTickLabelRotation(60);
- customPlot->xAxis->setTickLabelColor(Qt::white);
- customPlot->yAxis->setTickLabelColor(Qt::white);
- customPlot->xAxis->grid()->setVisible(true);
- customPlot->yAxis->grid()->setVisible(true);
-
- customPlot->setNotAntialiasedElements(QCP::aeAll); // 关闭抗锯齿
- customPlot->setPlottingHints(QCP::phFastPolylines); // 使用快速绘制
- customPlot->setNoAntialiasingOnDrag(true); // 拖动时关闭抗锯齿
-
- // 优化图表性能
- customPlot->setBufferDevicePixelRatio(1.0); // 设置缓冲区像素比
- customPlot->setOpenGl(true); // 启用OpenGL加速(如果支持)
-
- // 确保图表可以接收鼠标事件
- customPlot->setMouseTracking(true);
- customPlot->setAttribute(Qt::WA_Hover);
- customPlot->setFocusPolicy(Qt::StrongFocus);
-
- // 启用所有交互选项
- customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems
- | QCP::iSelectAxes | QCP::iSelectLegend);
-
- // 创建新的顶层层级
- customPlot->addLayer("topmost", customPlot->layer("main"), QCustomPlot::limAbove);
- QCPLayer *topmostLayer = customPlot->layer("topmost");
- topmostLayer->setMode(QCPLayer::lmBuffered);
-
- // 将所有现有图层移到新层级下方
- for (int i = 0; i < customPlot->layerCount(); ++i) {
- QCPLayer *layer = customPlot->layer(i);
- if (layer != topmostLayer) {
- layer->setMode(QCPLayer::lmBuffered);
- customPlot->moveLayer(layer, topmostLayer, QCustomPlot::limBelow);
- }
- }
-
- // 创建坐标标签
- m_coordLabel = new QCPItemText(customPlot);
- m_coordLabel->setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
- m_coordLabel->setTextAlignment(Qt::AlignLeft);
- m_coordLabel->setVisible(false);
- m_coordLabel->setPadding(QMargins(8, 8, 8, 8)); // 增加内边距
- m_coordLabel->setBrush(QBrush(QColor(40, 40, 40, 255)));
- m_coordLabel->setPen(QPen(QColor(80, 80, 80, 255)));
- m_coordLabel->setColor(Qt::white);
- QFont labelFont = QFont("Arial", 16);
- labelFont.setBold(true);
- m_coordLabel->setFont(labelFont);
- m_coordLabel->setLayer("topmost"); // 使用最顶层
-
- // 创建点追踪器
- m_tracer = new QCPItemTracer(customPlot);
- m_tracer->setStyle(QCPItemTracer::tsCircle);
- m_tracer->setPen(QPen(Qt::red));
- m_tracer->setBrush(Qt::red);
- m_tracer->setSize(8);
- m_tracer->setVisible(false);
- m_tracer->setLayer("topmost"); // 使用最顶层
-
- // 连接鼠标事件
- connect(customPlot, &XNCustomPlot::mousePressed, this, [=](QMouseEvent *event) {
- if (event->button() == Qt::LeftButton && customPlot->graph(0)) {
- double x = customPlot->xAxis->pixelToCoord(event->pos().x());
- double y = customPlot->yAxis->pixelToCoord(event->pos().y());
-
- if (!customPlot->graph(0)->data()->isEmpty()) {
- double minDistance = std::numeric_limits::max();
- QCPGraphDataContainer::const_iterator closestPoint;
- bool foundPoint = false;
-
- for (auto it = customPlot->graph(0)->data()->begin();
- it != customPlot->graph(0)->data()->end(); ++it) {
- double distance = qSqrt(qPow(it->key - x, 2) + qPow(it->value - y, 2));
- if (distance < minDistance) {
- minDistance = distance;
- closestPoint = it;
- foundPoint = true;
- }
- }
-
- if (foundPoint) {
- m_tracer->setGraph(customPlot->graph(0));
- m_tracer->setGraphKey(closestPoint->key);
- m_tracer->setVisible(true);
-
- m_coordLabel->position->setCoords(closestPoint->key, closestPoint->value);
- m_coordLabel->setText(QString("时间: %1\n数值: %2")
- .arg(closestPoint->key)
- .arg(closestPoint->value));
- m_coordLabel->setVisible(true);
-
- customPlot->replot();
- }
- }
- }
- });
-
- // 确保在初始化时重新绘制一次
- customPlot->replot();
-}
\ No newline at end of file
diff --git a/XNMonitor/DataCollectionWidget/DataCollectionWidget.h b/XNMonitor/DataCollectionWidget/DataCollectionWidget.h
deleted file mode 100755
index 5c65705..0000000
--- a/XNMonitor/DataCollectionWidget/DataCollectionWidget.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-#include
-#include
-#include "DataCollectionThread.h"
-#include "../TypeDefine.h"
-#include "../XNCustomPlot.h"
-
-class DataCollectionWidget : public QWidget
-{
- Q_OBJECT
-public:
- explicit DataCollectionWidget(QWidget *parent = nullptr);
- ~DataCollectionWidget();
-
-signals:
- void stopDataCollection();
-
-public slots:
- void onSetCurrentTabIndex(int index);
- void onUpdateDataCollectionTime(const unsigned int newTime);
- void onDataCollectionStatus(const bool &status, const QString &filePath);
-
-private:
- void setupTabDataCollection(); // 设置数据采集标签页的函数声明
- void
- setupTabDataCollectionLeftPanel(QSplitter *horizontalSplitter); // 设置数据采集左面板的函数声明
- void
- setupTabDataCollectionRightPanel(QSplitter *horizontalSplitter); // 设置数据采集右面板的函数声明
- void openDataCollectionFile(const QString &filePath);
- void setupPlotWidget(XNCustomPlot *customPlot);
-
-private:
- unsigned int dataPlotIndex; // 数据采集索引
- QMap> collectionData;
- QMap> referenceData;
- int currentTabIndex = 0; // 当前选中的标签页索引
- QCPItemTracer *m_tracer;
- QCPItemText *m_coordLabel;
-};
\ No newline at end of file
diff --git a/XNMonitor/DataMonitorWidget/DataMonitorThread.cpp b/XNMonitor/DataMonitorWidget/DataMonitorThread.cpp
deleted file mode 100755
index e766a8c..0000000
--- a/XNMonitor/DataMonitorWidget/DataMonitorThread.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/**
- * @file DataMonitorThread.cpp
- * @author jinchao
- * @brief 数据监控线程类实现
- * @version 1.0
- * @date 2025-03-10
- *
- * @copyright Copyright (c) 2025 COMAC
- *
- */
-#include "DataMonitorThread.h"
-#include
-#include
-#include
-#include "../TopicManager/TopicManager.h"
-#include "../TopicMonitorFactory/TopicMonitorFactory.h"
-
-DataMonitorThread::DataMonitorThread(QObject *parent) : QThread(parent)
-{
-}
-
-DataMonitorThread::~DataMonitorThread()
-{
- // 停止所有主题监控
- if (m_TopicMonitorMap.size() > 0) {
- for (auto &topicName : m_TopicMonitorMap.keys()) {
- m_TopicMonitorMap[topicName]->stopMonitoring(topicName);
- m_TopicMonitorMap.remove(topicName);
- }
- }
-}
-
-void DataMonitorThread::run()
-{
- while (!m_Quit) {
- if (m_Active) {
- QMutexLocker locker(&m_Mutex);
- for (auto &topicName : m_VarNameMap.keys()) {
- // 遍历主题名下的所有变量
- for (auto &varName : m_VarNameMap[topicName].keys()) {
- if (m_VarNameMap[topicName][varName] == 0) {
- // 如果变量名对应的监控状态为0,则获取数据
- QString value = m_TopicMonitorMap[topicName]->getData(topicName, varName);
- emit updateMonitoringData(varName, value);
- } else if (m_VarNameMap[topicName][varName] == 2) {
- // 如果变量名对应的监控状态为2,则注入一次数据
- m_TopicMonitorMap[topicName]->injectData(
- varName, m_InjectValueMap[topicName][varName]);
- emit updateMonitoringData(
- varName, QString::number(m_InjectValueMap[topicName][varName]));
- m_VarNameMap[topicName][varName] = 0;
- m_InjectValueMap[topicName].remove(varName);
- } else if (m_VarNameMap[topicName][varName] == 3) {
- // 如果变量名对应的监控状态为3,则注入连续数据
- m_TopicMonitorMap[topicName]->injectData(
- varName, m_InjectValueMap[topicName][varName]);
- emit updateMonitoringData(
- varName, QString::number(m_InjectValueMap[topicName][varName]));
- }
- }
- }
- }
- QThread::msleep(m_SleepTime);
- }
-}
-
-void DataMonitorThread::onSaveModelDefinition(
- const QSharedPointer &modelDefinition)
-{
- QMutexLocker locker(&m_Mutex);
-
- // 首先检查输入参数是否为空
- if (!modelDefinition) {
- emit sendDebugMessage(1, "保存模型接口定义失败,ModelDefinition指针为空");
- return;
- }
-
- // 设置最大递归深度
- const int MAX_RECURSION_DEPTH = 5;
-
- // 查找所有主题定义的结构体lambda表达式
- std::function> &, int)>
- findAllStruct = [this, &findAllStruct, MAX_RECURSION_DEPTH](
- const QString &topic,
- const QVector> &nsVector,
- int depth) {
- // 检查递归深度
- if (depth > MAX_RECURSION_DEPTH) {
- return;
- }
-
- for (auto &ns : nsVector) {
- // 检查是否为空指针
- if (!ns) {
- continue;
- }
- // 计算新的主题名
- QString newTopic =
- topic.size() > 0 ? topic + "::" + ns->namespaceName : ns->namespaceName;
- // 递归查找所有结构体
- findAllStruct(newTopic, ns->childNamespaces, depth + 1);
-
- for (auto &structDef : ns->structDefinitions) {
- // 检查是否为空指针
- if (!structDef) {
- continue;
- }
- // 保存主题名和结构体定义
- m_StructDefinitionList[newTopic + "::" + structDef->structName] = structDef;
- // 发送调试信息
- emit sendDebugMessage(0,
- "保存主题名" + newTopic + "::" + structDef->structName);
- }
- }
- };
- // 调用lambda表达式,查找所有主题定义的结构体
- findAllStruct("", modelDefinition->namespaceDefinitions, 0);
-}
-
-void DataMonitorThread::onStartMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName)
-{
- QMutexLocker locker(&m_Mutex);
- // 检查主题名是否在结构体列表中
- if (m_StructDefinitionList.contains(topicName)) {
- // 如果主题名在结构体列表中,则开始监控
- if (StartTopicMonitor(modelName, topicName)) {
- // 保存监控状态
- m_VarNameMap[topicName][varName] = 0;
- // 发送调试信息
- emit sendDebugMessage(0, "开始监控主题名" + topicName);
- }
- } else {
- // 如果主题名不在结构体列表中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要监控的主题名" + topicName);
- }
-}
-
-bool DataMonitorThread::StartTopicMonitor(const QString &modelName, const QString &topicName)
-{
- // 创建主题监控器
- m_TopicMonitorMap[topicName] = TopicMonitorFactory::getInstance().createMonitor(modelName);
- // 检查主题监控器是否创建成功
- if (m_TopicMonitorMap[topicName]) {
- // 开始监控
- bool bRet = m_TopicMonitorMap[topicName]->startMonitoring(topicName);
- // 返回监控结果
- return bRet;
- }
- // 如果主题监控器创建失败,则返回false
- return false;
-}
-
-void DataMonitorThread::onStopMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName)
-{
- QMutexLocker locker(&m_Mutex);
- if (m_StructDefinitionList.contains(topicName)) {
- // 如果变量名在监控状态中,则删除变量名对应的监控状态
- if (m_VarNameMap[topicName].contains(varName))
- m_VarNameMap[topicName].remove(varName);
- // 如果主题名对应的监控状态表为空,则停止监控主题
- if (m_VarNameMap[topicName].size() == 0) {
- // 如果主题监控器不存在,则获取主题监控器
- if (!m_TopicMonitorMap[topicName]) {
- m_TopicMonitorMap[topicName] =
- TopicMonitorFactory::getInstance().createMonitor(modelName);
- }
- // 停止监控主题
- m_TopicMonitorMap[topicName]->stopMonitoring(topicName);
- // 删除主题监控器
- m_TopicMonitorMap.remove(topicName);
- // 发送调试信息
- emit sendDebugMessage(0, "停止监控主题名" + topicName);
- }
- } else {
- // 如果主题名不在结构体列表中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要停止监控的主题名" + topicName);
- }
-}
-
-void DataMonitorThread::onPauseMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName)
-{
- QMutexLocker locker(&m_Mutex);
- if (m_VarNameMap.contains(topicName)) {
- // 如果变量名在监控状态中,则暂停监控
- if (m_VarNameMap[topicName].contains(varName)) {
- m_VarNameMap[topicName][varName] = 1;
- // 发送调试信息
- emit sendDebugMessage(0, "暂停监控主题名" + topicName + "的变量" + varName);
- } else {
- // 如果变量名不在监控状态中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要暂停监控的主题名" + topicName + "的变量" + varName);
- }
- } else {
- // 如果主题名不在监控状态中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要暂停监控的主题名" + topicName);
- }
-}
-
-void DataMonitorThread::onResumeMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName)
-{
- QMutexLocker locker(&m_Mutex);
- if (m_VarNameMap.contains(topicName)) {
- // 如果变量名在监控状态中,则恢复监控
- if (m_VarNameMap[topicName].contains(varName)) {
- m_VarNameMap[topicName][varName] = 0;
- // 发送调试信息
- emit sendDebugMessage(0, "恢复监控主题名" + topicName + "的变量" + varName);
- } else {
- // 如果变量名不在监控状态中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要恢复监控的主题名" + topicName + "的变量" + varName);
- }
- } else {
- // 如果主题名不在监控状态中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要恢复监控的主题名" + topicName);
- }
-}
-
-void DataMonitorThread::onInjectOnceData(const QString &modelName, const QString &topicName,
- const QString &varName, const double &value)
-{
- QMutexLocker locker(&m_Mutex);
- // 检查主题名是否在结构体列表中
- if (m_StructDefinitionList.contains(topicName)) {
- // 保存监控状态
- m_VarNameMap[topicName][varName] = 2;
- // 保存注入值
- m_InjectValueMap[topicName][varName] = value;
- // 发送调试信息
- emit sendDebugMessage(0, "注入一次数据主题名" + topicName + "的变量" + varName);
- } else {
- // 如果主题名不在结构体列表中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要注入一次数据的主题名" + topicName);
- }
-}
-
-void DataMonitorThread::onInjectContinuousData(const QString &modelName, const QString &topicName,
- const QString &varName, const double &value)
-{
- QMutexLocker locker(&m_Mutex);
- if (m_StructDefinitionList.contains(topicName)) {
- // 保存监控状态
- m_VarNameMap[topicName][varName] = 3;
- // 保存注入值
- m_InjectValueMap[topicName][varName] = value;
- // 发送调试信息
- emit sendDebugMessage(0, "注入连续数据主题名" + topicName + "的变量" + varName);
- } else {
- // 如果主题名不在结构体列表中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要注入连续数据的主题名" + topicName);
- }
-}
-
-void DataMonitorThread::onStopInjectContinuousData(const QString &modelName,
- const QString &topicName, const QString &varName)
-{
- QMutexLocker locker(&m_Mutex);
- if (m_VarNameMap.contains(topicName)) {
- // 如果变量名在监控状态中,则停止注入连续数据
- if (m_VarNameMap[topicName].contains(varName)) {
- m_VarNameMap[topicName][varName] = 0;
- // 删除注入值
- m_InjectValueMap[topicName].remove(varName);
- // 发送调试信息
- emit sendDebugMessage(0, "停止注入连续数据主题名" + topicName + "的变量" + varName);
- } else {
- // 如果变量名不在监控状态中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要停止注入连续数据的主题名" + topicName + "的变量"
- + varName);
- }
- } else {
- // 如果主题名不在监控状态中,则发送调试信息
- emit sendDebugMessage(2, "未找到需要停止注入连续数据的主题名" + topicName);
- }
-}
-
-void DataMonitorThread::onChangeSleepTime(const unsigned int newSleepTime)
-{
- m_SleepTime = newSleepTime;
-}
-
-void DataMonitorThread::onThreadController(const bool &isActive)
-{
- m_Active = isActive;
-}
diff --git a/XNMonitor/DataMonitorWidget/DataMonitorThread.h b/XNMonitor/DataMonitorWidget/DataMonitorThread.h
deleted file mode 100755
index 523a4bb..0000000
--- a/XNMonitor/DataMonitorWidget/DataMonitorThread.h
+++ /dev/null
@@ -1,144 +0,0 @@
-#pragma once
-#include
-#include
-#include
-#include
-#include "../TopicMonitorFactory/TopicMonitor.h"
-#include "../TopicManager/TopicManager.h"
-#include "../TypeDefine.h"
-
-class DataMonitorThread : public QThread
-{
- Q_OBJECT
-
-public:
- explicit DataMonitorThread(QObject *parent = nullptr);
- ~DataMonitorThread();
-
-signals:
- void updateMonitoringData(const QString &varName, const QString &value);
- void sendDebugMessage(int type, const QString &message); // 发送调试信息的信号声明
-public slots:
- /**
- * @brief 设置线程休眠时间
- * @param newSleepTime 新的休眠时间(毫秒)
- */
- void onChangeSleepTime(const unsigned int newSleepTime);
-
- /**
- * @brief 控制线程运行状态
- * @param isRunning true:运行 false:停止
- */
- void onThreadController(const bool &isRunning);
-
- /**
- * @brief 保存模型定义
- * @param modelDefinition 模型定义
- */
- void onSaveModelDefinition(const QSharedPointer &modelDefinition);
-
- /**
- * @brief 开始监控指定变量
- * @param varName 变量名
- */
- void onStartMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName);
-
- /**
- * @brief 停止监控指定变量
- * @param varName 变量名
- */
- void onStopMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName);
-
- /**
- * @brief 暂停监控指定变量
- * @param varName 变量名
- */
- void onPauseMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName);
-
- /**
- * @brief 恢复监控指定变量
- * @param varName 变量名
- */
- void onResumeMonitoring(const QString &modelName, const QString &topicName,
- const QString &varName);
-
- /**
- * @brief 注入一次性数据
- * @param varName 变量名
- * @param value 注入的值
- */
- void onInjectOnceData(const QString &modelName, const QString &topicName,
- const QString &varName, const double &value);
-
- /**
- * @brief 持续注入数据
- * @param varName 变量名
- * @param value 注入的值
- */
- void onInjectContinuousData(const QString &modelName, const QString &topicName,
- const QString &varName, const double &value);
-
- /**
- * @brief 停止持续注入数据
- * @param varName 变量名
- */
- void onStopInjectContinuousData(const QString &modelName, const QString &topicName,
- const QString &varName);
-
- /**
- * @brief 退出线程
- */
- void onThreadQuit() { m_Quit = true; }
-
-protected:
- /**
- * @brief 线程运行函数
- */
- void run() override;
-
-private:
- /**
- * @brief 启动主题监控
- * @param modelName 模型名
- * @param topicName 主题名
- * @return 是否启动成功
- */
- bool StartTopicMonitor(const QString &modelName, const QString &topicName);
-
-private:
- /**
- * @brief 模型名到模型定义的映射
- */
- QMap> m_StructDefinitionList;
- /**
- * @brief 变量名到监控状态的映射
- */
- QMap> m_VarNameMap;
- /**
- * @brief 变量名到注入值的映射
- */
- QMap> m_InjectValueMap;
- /**
- * @brief 线程休眠时间(毫秒)
- */
- unsigned int m_SleepTime = 1000;
- /**
- * @brief 线程活动状态
- */
- bool m_Active = false;
- /**
- * @brief 线程退出标志
- */
- bool m_Quit = false;
- /**
- * @brief 互斥锁
- */
- QMutex m_Mutex;
- /**
- * @brief 模型名到主题监控器的映射
- */
- QMap> m_TopicMonitorMap;
-};
diff --git a/XNMonitor/DataMonitorWidget/DataMonitorWidget.cpp b/XNMonitor/DataMonitorWidget/DataMonitorWidget.cpp
deleted file mode 100755
index 107cd63..0000000
--- a/XNMonitor/DataMonitorWidget/DataMonitorWidget.cpp
+++ /dev/null
@@ -1,1346 +0,0 @@
-/**
- * @file DataMonitorWidget.cpp
- * @author jinchao
- * @brief 数据监控窗口类实现
- * @version 1.0
- * @date 2025-03-10
- *
- * @copyright Copyright (c) 2025 COMAC
- *
- */
-#include "DataMonitorWidget.h"
-#include
-
-DataMonitorWidget::DataMonitorWidget(QWidget *parent) : QWidget(parent)
-{
- setupTabDataMonitoring(); // 设置数据监控标签页
- InitialDataMonitorThread(); // 初始化数据监控线程
-}
-
-DataMonitorWidget::~DataMonitorWidget()
-{
- // 释放数据监控线程
- if (dataMonitorThread != nullptr) {
- dataMonitorThread->onThreadQuit();
- dataMonitorThread->quit();
- dataMonitorThread->wait();
- delete dataMonitorThread;
- dataMonitorThread = nullptr;
- }
-}
-
-void DataMonitorWidget::onSetCurrentTabIndex(int index)
-{
- this->currentTabIndex = index;
- if (currentTabIndex == 2) {
- //如果当前标签索引为2,则显示数据监控窗口
- this->show();
- emit controlDataMonitorThread(true);
- } else {
- //如果当前标签索引不为2,则隐藏数据监控窗口
- this->hide();
- emit controlDataMonitorThread(false);
- }
-}
-
-void DataMonitorWidget::InitialDataMonitorThread()
-{
- // 初始化数据监控线程
- dataMonitorThread = new DataMonitorThread(this);
- // 连接数据监控线程的更新监控数据信号到更新监控数据槽函数
- connect(dataMonitorThread, &DataMonitorThread::updateMonitoringData, this,
- &DataMonitorWidget::updateMonitoringData);
- // 连接控制数据监控线程信号到数据监控线程控制函数
- connect(this, &DataMonitorWidget::controlDataMonitorThread, dataMonitorThread,
- &DataMonitorThread::onThreadController);
- // 连接监控开始信号到数据监控线程开始监控函数
- connect(this, &DataMonitorWidget::monitoringStarted, dataMonitorThread,
- &DataMonitorThread::onStartMonitoring);
- // 连接监控停止信号到数据监控线程停止监控函数
- connect(this, &DataMonitorWidget::monitoringStopped, dataMonitorThread,
- &DataMonitorThread::onStopMonitoring);
- // 连接监控暂停信号到数据监控线程暂停监控函数
- connect(this, &DataMonitorWidget::monitoringPaused, dataMonitorThread,
- &DataMonitorThread::onPauseMonitoring);
- // 连接监控恢复信号到数据监控线程恢复监控函数
- connect(this, &DataMonitorWidget::monitoringResumed, dataMonitorThread,
- &DataMonitorThread::onResumeMonitoring);
- // 连接注入一次数据信号到数据监控线程注入一次数据函数
- connect(this, &DataMonitorWidget::injectOnceData, dataMonitorThread,
- &DataMonitorThread::onInjectOnceData);
- // 连接注入持续数据信号到数据监控线程注入持续数据函数
- connect(this, &DataMonitorWidget::injectContinuousData, dataMonitorThread,
- &DataMonitorThread::onInjectContinuousData);
- // 连接停止注入持续数据信号到数据监控线程停止注入持续数据函数
- connect(this, &DataMonitorWidget::stopInjectContinuousData, dataMonitorThread,
- &DataMonitorThread::onStopInjectContinuousData);
- // 连接保存模型定义信号到数据监控线程保存模型定义函数
- connect(this, &DataMonitorWidget::saveModelDefinition, dataMonitorThread,
- &DataMonitorThread::onSaveModelDefinition);
- // 连接数据监控线程的发送调试消息信号到发送调试消息槽函数
- connect(dataMonitorThread, &DataMonitorThread::sendDebugMessage, this,
- &DataMonitorWidget::onSendDebugMessage);
- // 启动数据监控线程
- dataMonitorThread->start();
- // 发送控制数据监控线程信号
- emit controlDataMonitorThread(true);
-}
-
-// 设置数据监控标签页
-void DataMonitorWidget::setupTabDataMonitoring()
-{
- QHBoxLayout *mainLayout = new QHBoxLayout(this); // 创建水平布局
- // 使用QSplitter进行左右栏的动态分割
- QSplitter *horizontalSplitter = new QSplitter(Qt::Horizontal); // 创建一个水平方向的QSplitter
-
- // 左栏布局
- setupTabDataMonitoringLeftPanel(horizontalSplitter);
-
- // 右栏布局
- setupTabDataMonitoringRightPanel(horizontalSplitter);
-
- // 设置QSplitter的初始分割比例为1:4,即左栏占五分之一,右栏占五分之四
- QList sizes;
- sizes << 1 << 4;
- horizontalSplitter->setSizes(sizes);
-
- // 将QSplitter添加到主布局中
- mainLayout->addWidget(horizontalSplitter);
-}
-
-// 设置数据监控左栏
-void DataMonitorWidget::setupTabDataMonitoringLeftPanel(QSplitter *splitter)
-{
- // 左栏布局
- QVBoxLayout *leftLayout = new QVBoxLayout();
- leftLayout->setObjectName("ModelInterfaceLeftLayout");
-
- // 添加搜索框
- QLineEdit *searchLineEdit = new QLineEdit();
- searchLineEdit->setObjectName("ModelInterfaceSearchBox");
- searchLineEdit->setPlaceholderText("Search (use * as wildcard)");
- searchLineEdit->setClearButtonEnabled(true);
-
- // 设置搜索框字体
- QFont searchFont = searchLineEdit->font();
- searchFont.setPointSize(14);
- searchLineEdit->setFont(searchFont);
-
- leftLayout->addWidget(searchLineEdit);
-
- QTreeWidget *tree = new QTreeWidget();
- tree->setColumnCount(2); // 设置为两列
- tree->setObjectName("ModelInterfaceTree");
- tree->setHeaderLabels(QStringList() << "模型接口列表" << "操作"); // 设置两列的表头
- tree->setIndentation(10); // 设置缩进大小
-
- // 设置树控件的字体
- QFont treeFont = tree->font();
- treeFont.setPointSize(16); // 设置字体大小为16
- tree->setFont(treeFont);
-
- // 同时设置表头字体
- QFont headerFont = treeFont;
- headerFont.setBold(true); // 表头字体加粗
- tree->header()->setFont(headerFont);
-
- // 设置列宽模式和固定宽度
- tree->header()->setSectionResizeMode(0, QHeaderView::Stretch); // 第一列自动伸展
- tree->header()->setSectionResizeMode(1, QHeaderView::Fixed); // 第二列固定宽度
- tree->setColumnWidth(1, 100); // 设置第二列宽度为80像素
- tree->header()->setStretchLastSection(false); // 禁止最后一列自动伸展
-
- // 设置树控件的样式表
- tree->setStyleSheet("QTreeWidget {"
- "show-decoration-selected: 1;"
- "}"
- "QTreeWidget::branch:has-children:!has-siblings:closed,"
- "QTreeWidget::branch:closed:has-children:has-siblings"
- "{"
- "border-image: none;"
- "image: url(:/qss_icons/dark/rc/chevron-right.png);"
- "}"
- "QTreeWidget::branch:open:has-children:!has-siblings,"
- "QTreeWidget::branch:open:has-children:has-siblings"
- "{"
- "border-image: none;"
- "image: url(:/qss_icons/dark/rc/chevron-down.png);"
- "}");
-
- leftLayout->addWidget(tree);
-
- QPushButton *openModelInterfaceFileButton = new QPushButton("打开模型接口文件");
- leftLayout->addWidget(openModelInterfaceFileButton); // 将按钮添加到左栏布局中
- connect(openModelInterfaceFileButton, &QPushButton::clicked, this,
- &DataMonitorWidget::openModelInterfaceFile);
-
- // 连接搜索框的文本改变信号到搜索函数
- connect(searchLineEdit, &QLineEdit::textChanged, this,
- &DataMonitorWidget::searchModelInterface);
-
- // 创建一个QWidget作为左栏的容器,并设置其布局为leftLayout
- QWidget *leftPanel = new QWidget();
- leftPanel->setLayout(leftLayout);
-
- // 创建一个QScrollArea来包含左栏的布局
- QScrollArea *leftScrollArea = new QScrollArea(this);
- leftScrollArea->setWidget(leftPanel);
- leftScrollArea->setWidgetResizable(true);
- leftScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
- leftScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
-
- // 将QScrollArea添加到QSplitter中
- splitter->addWidget(leftScrollArea);
-}
-
-// 打开模型接口文件
-void DataMonitorWidget::openModelInterfaceFile()
-{
- // 打开文件对话框
- QString fileName =
- QFileDialog::getOpenFileName(this, "选择模型接口文件", "", "模型接口文件(*.idl)");
- // 如果文件名不为空
- if (fileName.isEmpty())
- return;
- // 创建文件
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QMessageBox::warning(this, "错误", "无法打开文件:" + file.errorString());
- return;
- }
- // 创建模型定义
- QSharedPointer modelDefinition = QSharedPointer::create();
- // 设置模型名称
- modelDefinition->modelName = fileName.split("/").last().split(".").first();
-
- // 读取文件
- QTextStream in(&file);
- // 命名空间栈
- QStack> namespaceStack;
- // 当前结构体
- QSharedPointer currentStruct;
- // 当前行
- QString line;
- // 是否在结构体中
- bool inStruct = false;
- // 花括号计数
- int braceCount = 0;
-
- // 逐行读取IDL文件
- while (!in.atEnd()) {
- // 读取一行
- line = in.readLine().trimmed();
-
- // 跳过空行和注释
- if (line.isEmpty() || line.startsWith("//"))
- continue;
-
- // 处理命名空间开始
- if (line.startsWith("module")) {
- // 花括号计数加1
- braceCount++;
- // 创建新的命名空间
- QSharedPointer newNS =
- QSharedPointer::create();
-
- // 获取命名空间名称
- QString nsNames = line.mid(7).trimmed();
- newNS->namespaceName = nsNames.split(" ").first(); // 直接使用完整名称
- // 将新的命名空间压入命名空间栈
- namespaceStack.push(newNS);
- // 继续处理下一行
- continue;
- }
-
- // 处理结构体开始
- if (line.startsWith("struct")) {
- // 如果已经在结构体中,并且当前结构体不为空,则将当前结构体添加到命名空间栈中
- if (inStruct && currentStruct && !currentStruct->structName.isEmpty()) {
- // 将当前结构体添加到命名空间栈中
- namespaceStack.top()->structDefinitions.append(currentStruct);
- // 创建新的结构体
- currentStruct = QSharedPointer::create();
- }
- // 设置在结构体中
- inStruct = true;
- // 花括号计数加1
- braceCount++;
- // 如果当前结构体为空,则创建新的结构体
- if (!currentStruct) {
- // 创建新的结构体
- currentStruct = QSharedPointer::create();
- }
- // 设置结构体名称
- currentStruct->structName = line.split(" ").at(1);
- // 继续处理下一行
- continue;
- }
-
- // 处理成员变量
- if (inStruct && currentStruct) {
- // 如果当前行不是花括号,则处理成员变量
- if (!line.startsWith("{") && !line.startsWith("}")) {
- // 描述
- QString description;
- // 注释位置
- int commentPos = line.indexOf("//");
- // 如果注释位置不为-1,则获取注释
- if (commentPos != -1) {
- // 获取注释
- description = line.mid(commentPos + 2).trimmed();
- // 获取成员变量声明
- line = line.left(commentPos).trimmed();
- }
- // 分割成员变量声明
- QStringList parts = line.split(";").first().split(" ", Qt::SkipEmptyParts);
- // 如果该行以@开头,移除第一个参数
- if (parts[0].startsWith("@"))
- parts.pop_front();
- // 如果成员变量声明大小大于等于2,则处理成员变量
- if (parts.size() >= 2) {
- // 创建成员变量
- QSharedPointer var = QSharedPointer::create();
- // 设置数据类型
- var->dataType = parts[0];
- // 设置变量声明
- QString varDecl = parts[1];
- // 如果变量声明包含[,则设置为数组
- if (varDecl.contains("[")) {
- // 设置为数组
- var->isArray = true;
- // 设置变量名称
- var->variableName = varDecl.split("[").first();
- // 正则表达式
- QRegularExpression re("\\[(\\d+)\\]");
- // 匹配
- QRegularExpressionMatchIterator i = re.globalMatch(varDecl);
- // 遍历匹配
- while (i.hasNext()) {
- // 获取匹配
- QRegularExpressionMatch match = i.next();
- // 添加到数组大小
- var->arraySizes.append(match.captured(1).toInt());
- }
- } else {
- // 设置为非数组
- var->isArray = false;
- // 设置变量名称
- var->variableName = varDecl;
- }
- // 设置描述
- var->description = description;
- // 添加到结构体成员变量列表
- currentStruct->memberVariables.append(var);
- }
- }
- }
-
- // 处理花括号闭合
- if (line.contains("}")) {
- // 花括号计数减1
- braceCount--;
- // 如果当前在结构体中
- if (inStruct) {
- // 设置不在结构体中
- inStruct = false;
- // 如果当前结构体不为空,则将当前结构体添加到命名空间栈中
- if (currentStruct && !currentStruct->structName.isEmpty()) {
- // 将当前结构体添加到命名空间栈中
- namespaceStack.top()->structDefinitions.append(currentStruct);
- // 创建新的结构体
- currentStruct = QSharedPointer::create();
- }
- } else {
- // 如果命名空间栈不为空
- if (!namespaceStack.isEmpty()) {
- // 获取命名空间
- QSharedPointer completedNS = namespaceStack.pop();
- // 只有当栈为空时,才添加到namespaceDefinitions
- if (namespaceStack.isEmpty()) {
- // 添加到namespaceDefinitions
- modelDefinition->namespaceDefinitions.append(completedNS);
- } else {
- // 添加到子命名空间
- namespaceStack.top()->childNamespaces.append(completedNS);
- }
- }
- }
- }
- }
-
- // 关闭文件
- file.close();
- // 更新界面
- updateInterfaceInfoPage(modelDefinition);
- // 保存模型定义
- emit saveModelDefinition(modelDefinition);
-}
-
-// 更新模型接口信息页面
-void DataMonitorWidget::updateInterfaceInfoPage(QSharedPointer modelDefinition)
-{
- // 如果当前标签索引不为2,则返回
- if (currentTabIndex != 2)
- return;
- // 获取模型接口树
- QTreeWidget *tree = findChild("ModelInterfaceTree");
- if (!tree)
- return;
- // 创建模型项
- QTreeWidgetItem *modelItem = new QTreeWidgetItem(tree);
- // 设置模型名称
- modelItem->setText(0, modelDefinition->modelName);
-
- // 为模型项添加按钮
- QPushButton *modelButton = new QPushButton("关闭");
- // 设置按钮对象名称
- modelButton->setObjectName(QString("btn_model_%1").arg(modelDefinition->modelName));
- // 将按钮添加到树中
- tree->setItemWidget(modelItem, 1, modelButton);
-
- // 连接按钮的点击信号到槽函数
- connect(modelButton, &QPushButton::clicked, this, [=]() {
- // 显示确认对话框
- QMessageBox::StandardButton reply;
- reply = QMessageBox::question(
- this, "确认关闭",
- QString("确定要关闭模型 %1 的接口描述吗?").arg(modelDefinition->modelName),
- QMessageBox::Yes | QMessageBox::No);
-
- if (reply == QMessageBox::Yes) {
- // 从树中删除该模型项及其所有子项
- delete tree->takeTopLevelItem(tree->indexOfTopLevelItem(modelItem));
- }
- });
-
- // 遍历namespaces,为每个命名空间创建一个根节点
- for (const auto &ns : modelDefinition->namespaceDefinitions) {
- addNameSpaceToTree(modelDefinition->modelName, QStringList(), ns, modelItem, tree);
- }
-
- modelItem->setExpanded(true);
-}
-
-// 添加命名空间到树
-void DataMonitorWidget::addNameSpaceToTree(const QString &modelName,
- const QStringList &topicNameList,
- const QSharedPointer &ns,
- QTreeWidgetItem *parentItem, QTreeWidget *tree)
-{
- // 创建命名空间项
- QTreeWidgetItem *namespaceItem = new QTreeWidgetItem(parentItem);
- // 新的主题名称列表
- QStringList newTopicNameList = topicNameList;
- // 添加命名空间名称
- newTopicNameList.append(ns->namespaceName);
- // 设置命名空间名称
- namespaceItem->setText(0, ns->namespaceName);
- // 设置模块类型
- namespaceItem->setText(1, "Module");
- // 遍历子命名空间
- for (const auto &childNS : ns->childNamespaces) {
- // 添加到树中
- addNameSpaceToTree(modelName, newTopicNameList, childNS, namespaceItem, tree);
- }
-
- // 遍历命名空间中的结构体定义
- for (const auto &structDef : ns->structDefinitions) {
- // 创建结构体项
- QTreeWidgetItem *structItem = new QTreeWidgetItem(namespaceItem);
- // 设置结构体名称
- structItem->setText(0, structDef->structName);
- // 设置模块类型
- structItem->setText(1, "Struct");
- // 新的主题名称列表
- QString topicName = newTopicNameList.join("::") + "::" + structDef->structName;
- // 遍历结构体的成员变量
- for (const auto &memberVar : structDef->memberVariables) {
- // 创建成员变量项
- QTreeWidgetItem *memberItem = new QTreeWidgetItem(structItem);
- // 设置成员变量名称
- memberItem->setText(0, memberVar->variableName);
- // 如果成员变量是数组
- if (memberVar->isArray) {
- // 为成员变量项添加按钮
- QPushButton *memberButton = new QPushButton("监控全部");
- // 按钮对象名称
- QString btnName = "btn_member_" + newTopicNameList.join("_");
- // 设置按钮对象名称
- memberButton->setObjectName(btnName);
- // 将按钮添加到树中
- tree->setItemWidget(memberItem, 1, memberButton);
- // 连接监控全部按钮的点击信号
- connect(memberButton, &QPushButton::clicked, this, [=]() {
- for (int i = 0; i < memberVar->arraySizes[0]; ++i) {
- // 如果成员变量是二维数组
- if (memberVar->arraySizes.size() == 2) {
- // 遍历二维数组
- for (int j = 0; j < memberVar->arraySizes[1]; ++j) {
- // 添加监控数据
- addMonitoringData(modelName, topicName,
- QString("%1[%2][%3]")
- .arg(memberVar->variableName)
- .arg(i)
- .arg(j),
- memberVar->dataType);
- }
- } else {
- // 添加监控数据
- addMonitoringData(modelName, topicName,
- QString("%1[%2]").arg(memberVar->variableName).arg(i),
- memberVar->dataType);
- }
- }
- });
- // 遍历一维数组
- for (int i = 0; i < memberVar->arraySizes[0]; ++i) {
- // 创建成员变量项
- QTreeWidgetItem *memberItem1 = new QTreeWidgetItem(memberItem);
- // 设置成员变量名称
- memberItem1->setText(
- 0, QStringLiteral("%1[%2]").arg(memberVar->variableName).arg(i));
- // 如果成员变量是二维数组
- if (memberVar->arraySizes.size() == 2) {
- // 为数组元素项添加按钮
- QPushButton *arrayButton = new QPushButton("监控全部");
- // 按钮对象名称
- QString btnName = "btn_array_" + newTopicNameList.join("_");
- // 设置按钮对象名称
- arrayButton->setObjectName(btnName);
- // 将按钮添加到树中
- tree->setItemWidget(memberItem1, 1, arrayButton);
-
- // 连接二维数组监控全部按钮的点击信号
- connect(arrayButton, &QPushButton::clicked, this, [=]() {
- for (int j = 0; j < memberVar->arraySizes[1]; ++j) {
- addMonitoringData(modelName, topicName,
- QString("%1[%2][%3]")
- .arg(memberVar->variableName)
- .arg(i)
- .arg(j),
- memberVar->dataType);
- }
- });
- // 遍历二维数组
- for (int j = 0; j < memberVar->arraySizes[1]; ++j) {
- // 创建二维数组元素项
- QTreeWidgetItem *arrayElementItem = new QTreeWidgetItem(memberItem1);
- // 设置二维数组元素名称
- arrayElementItem->setText(0, QStringLiteral("%1[%2][%3]")
- .arg(memberVar->variableName)
- .arg(i)
- .arg(j));
-
- // 为二维数组元素项添加按钮
- QPushButton *arrayElement2Button = new QPushButton("监控");
- QString btnName = "btn_array2_" + newTopicNameList.join("_");
- arrayElement2Button->setObjectName(btnName);
- tree->setItemWidget(arrayElementItem, 1, arrayElement2Button);
-
- // 连接二维数组元素监控按钮的点击信号
- connect(arrayElement2Button, &QPushButton::clicked, this, [=]() {
- addMonitoringData(modelName, topicName,
- QString("%1[%2][%3]")
- .arg(memberVar->variableName)
- .arg(i)
- .arg(j),
- memberVar->dataType);
- });
- }
- } else {
- // 为数组元素项添加按钮
- QPushButton *arrayButton = new QPushButton("监控");
- QString btnName = "btn_array_" + newTopicNameList.join("_");
- arrayButton->setObjectName(btnName);
- tree->setItemWidget(memberItem1, 1, arrayButton);
-
- // 连接一维数组元素监控按钮的点击信号
- connect(arrayButton, &QPushButton::clicked, this, [=]() {
- addMonitoringData(modelName, topicName,
- QString("%1[%2]").arg(memberVar->variableName).arg(i),
- memberVar->dataType);
- });
- }
- }
- } else {
- // 为成员变量项添加按钮
- QPushButton *memberButton = new QPushButton("监控");
- QString btnName = "btn_member_" + newTopicNameList.join("_");
- memberButton->setObjectName(btnName);
- tree->setItemWidget(memberItem, 1, memberButton);
-
- // 连接普通变量监控按钮的点击信号
- connect(memberButton, &QPushButton::clicked, this, [=]() {
- addMonitoringData(modelName, topicName, memberVar->variableName,
- memberVar->dataType);
- });
- }
- }
- }
-}
-
-// 添加监控数据
-void DataMonitorWidget::addMonitoringData(const QString &modelName, const QString &topicName,
- const QString &varName, const QString &dataType)
-{
- QTableWidget *table = findChild("dataMonitoringTableWidget");
- if (!table)
- return;
-
- // 查找是否已经监控该变量
- for (int i = 0; i < table->rowCount(); ++i) {
- QTableWidgetItem *item = table->item(i, 0);
- if (item && item->text() == varName) {
- QMessageBox::information(this, "提示", "该变量已经监控了");
- return;
- }
- }
-
- // 如果没有找到该变量,则添加新行
- int row = table->rowCount();
- table->setRowCount(row + 1);
- // 初始化新行的所有列
- for (int col = 0; col < table->columnCount(); ++col) {
- QTableWidgetItem *item = new QTableWidgetItem();
- if (col != 7) {
- item->setFlags(item->flags() & ~Qt::ItemIsEditable);
- }
- table->setItem(row, col, item);
- }
-
- // 设置接口名称
- table->item(row, 0)->setText(varName);
-
- // 设置主题名称
- table->item(row, 1)->setText(topicName);
-
- // 设置模型名称
- table->item(row, 2)->setText(modelName);
-
- // 设置数据类型
- table->item(row, 3)->setText(dataType);
-
- // 设置初始值
- table->item(row, 4)->setText("--");
-
- // 设置监控状态(灰色)
- table->item(row, 5)->setText("未开始");
- table->item(row, 5)->setForeground(QColor(128, 128, 128));
-
- // 设置更改值单元格(可编辑)
- QTableWidgetItem *changeValueItem = new QTableWidgetItem();
- table->setItem(row, 7, changeValueItem);
-
- // 创建监控控制按钮组
- QWidget *buttonWidget = new QWidget();
- QHBoxLayout *buttonLayout = new QHBoxLayout(buttonWidget);
- buttonLayout->setContentsMargins(2, 2, 2, 2);
- buttonLayout->setSpacing(2);
- // 创建开始按钮
- QPushButton *startStopButton = new QPushButton("开始");
- // 创建暂停按钮
- QPushButton *pauseResumeButton = new QPushButton("暂停");
- // 创建绘图按钮
- QPushButton *plotButton = new QPushButton("绘图");
- // 创建删除按钮
- QPushButton *deleteButton = new QPushButton("删除");
-
- // 设置暂停按钮不可用
- pauseResumeButton->setEnabled(false);
- // 设置绘图按钮不可用
- plotButton->setEnabled(false);
- // 设置绘图按钮可选中
- plotButton->setCheckable(true);
- // 设置绘图按钮对象名称
- plotButton->setObjectName(QString("btn_plot_%1").arg(varName));
- // 将按钮添加到布局中
- buttonLayout->addWidget(startStopButton);
- buttonLayout->addWidget(pauseResumeButton);
- buttonLayout->addWidget(plotButton);
- buttonLayout->addWidget(deleteButton);
- // 将按钮组添加到表格中
- table->setCellWidget(row, 6, buttonWidget);
-
- // 创建注入按钮组
- QWidget *injectButtonWidget = new QWidget();
- QHBoxLayout *injectLayout = new QHBoxLayout(injectButtonWidget);
- injectLayout->setContentsMargins(2, 2, 2, 2);
- injectLayout->setSpacing(2);
- // 创建注入一次按钮
- QPushButton *injectOnceButton = new QPushButton("注入一次");
- QPushButton *injectContinuousButton = new QPushButton("持续注入");
- injectOnceButton->setFixedWidth(100);
- injectContinuousButton->setFixedWidth(100);
- injectOnceButton->setEnabled(false);
- injectContinuousButton->setEnabled(false);
- // 将按钮添加到布局中
- injectLayout->addWidget(injectOnceButton);
- injectLayout->addWidget(injectContinuousButton);
- // 将按钮组添加到表格中
- table->setCellWidget(row, 8, injectButtonWidget);
-
- // 连接开始/停止按钮的点击信号
- connect(startStopButton, &QPushButton::clicked, this, [=]() {
- if (startStopButton->text() == "开始") {
- // 设置开始按钮文本为停止
- startStopButton->setText("停止");
- // 设置暂停按钮可用
- pauseResumeButton->setEnabled(true);
- // 设置绘图按钮可用
- plotButton->setEnabled(true);
- // 设置注入一次按钮可用
- injectOnceButton->setEnabled(true);
- // 设置持续注入按钮可用
- injectContinuousButton->setEnabled(true);
- // 设置删除按钮不可用
- deleteButton->setEnabled(false);
-
- // 设置状态为"监控中"(绿色)
- QTableWidgetItem *statusItem = table->item(row, 5);
- statusItem->setText("监控中");
- statusItem->setForeground(QColor(0, 255, 0)); // 绿色
-
- // 设置注入一次按钮可用
- injectOnceButton->setEnabled(true);
- // 设置持续注入按钮可用
- injectContinuousButton->setEnabled(true);
- // 添加变量数据映射
- varDataMap[varName] = QVector();
-
- // 发送开始监控信号
- emit monitoringStarted(modelName, topicName, varName);
- } else {
- // 设置开始按钮文本为开始
- startStopButton->setText("开始");
- // 设置暂停按钮文本为暂停
- pauseResumeButton->setText("暂停");
- // 设置暂停按钮不可用
- pauseResumeButton->setEnabled(false);
- // 设置绘图按钮不可用
- plotButton->setEnabled(false);
- // 设置注入一次按钮不可用
- injectOnceButton->setEnabled(false);
- // 设置持续注入按钮不可用
- injectContinuousButton->setEnabled(false);
- // 设置删除按钮可用
- deleteButton->setEnabled(true);
-
- // 设置状态为"未开始"(灰色)
- QTableWidgetItem *statusItem = table->item(row, 5);
- statusItem->setText("未开始");
- statusItem->setForeground(QColor(128, 128, 128)); // 灰色
-
- // 设置注入一次按钮不可用
- injectOnceButton->setEnabled(false);
- // 设置持续注入按钮不可用
- injectContinuousButton->setEnabled(false);
- // 移除变量数据映射
- varDataMap.remove(varName);
-
- // 发送停止监控信号
- emit monitoringStopped(modelName, topicName, varName);
- }
- });
-
- // 连接暂停/继续按钮的点击信号
- connect(pauseResumeButton, &QPushButton::clicked, this, [=]() {
- if (pauseResumeButton->text() == "暂停") {
- // 设置暂停按钮文本为继续
- pauseResumeButton->setText("继续");
-
- // 设置状态为"已暂停"(橙色)
- QTableWidgetItem *statusItem = table->item(row, 5);
- statusItem->setText("已暂停");
- statusItem->setForeground(QColor(255, 165, 0)); // 橙色
-
- // 设置注入一次按钮可用
- injectOnceButton->setEnabled(true);
- // 设置持续注入按钮可用
- injectContinuousButton->setEnabled(true);
-
- // 发送暂停监控信号
- emit monitoringPaused(modelName, topicName, varName);
-
- } else {
- // 设置暂停按钮文本为暂停
- pauseResumeButton->setText("暂停");
-
- // 设置状态为"监控中"(绿色)
- QTableWidgetItem *statusItem = table->item(row, 5);
- statusItem->setText("监控中");
- statusItem->setForeground(QColor(0, 255, 0)); // 绿色
-
- // 设置注入一次按钮不可用
- injectOnceButton->setEnabled(false);
- // 设置持续注入按钮不可用
- injectContinuousButton->setEnabled(false);
-
- // 发送继续监控信号
- emit monitoringResumed(modelName, topicName, varName);
- }
- });
-
- // 连接绘图按钮的点击信号
- connect(plotButton, &QPushButton::clicked, this, [=]() {
- // 遍历表格中所有行,将其他行的plotButton设置为未选中状态
- for (int i = 0; i < table->rowCount(); ++i) {
- if (i != row) { // 跳过当前行
- // 获取变量名称
- QString varName = table->item(i, 0)->text();
- // 获取绘图按钮对象名称
- QString objectName = QString("btn_plot_%1").arg(varName);
- // 获取绘图按钮
- QPushButton *otherPlotButton = findChild(objectName);
- // 如果绘图按钮存在
- if (otherPlotButton) {
- // 设置绘图按钮为未选中状态
- otherPlotButton->setChecked(false);
- }
- }
- }
-
- // 获取当前数据
- if (!varDataMap.contains(varName)) {
- // 添加变量数据映射
- varDataMap[varName] = QVector();
- }
-
- // 如果按钮被选中,则显示图表
- if (plotButton->isChecked()) {
- // 获取变量数据
- const QVector &data = varDataMap[varName];
- // 如果变量数据不为空
- if (data.size() > 0) {
- // 创建x轴数据
- QVector xData;
- // 遍历变量数据
- for (int i = 0; i < data.size(); ++i) {
- xData.push_back(i);
- }
-
- // 获取图表对象
- XNCustomPlot *customPlot = findChild("dataMonitoringCustomPlot");
- if (customPlot) {
- if (customPlot->graphCount() == 0) {
- // 添加新的图表并设置绿色
- customPlot->addGraph();
- QPen greenPen(Qt::green);
- greenPen.setWidth(2);
- customPlot->graph(0)->setPen(greenPen);
- }
- // 设置图表数据
- customPlot->graph(0)->setData(xData, data);
-
- // 自动调整坐标轴范围
- customPlot->xAxis->setRange(0, data.size());
- customPlot->yAxis->rescale();
-
- // 重绘图表
- customPlot->replot();
- }
- }
- } else {
- // 如果取消选中,则清除图表
- XNCustomPlot *customPlot = findChild("dataMonitoringCustomPlot");
- if (customPlot) {
- customPlot->clearGraphs();
- customPlot->replot();
- }
- }
- });
-
- // 连接删除按钮的点击信号
- connect(deleteButton, &QPushButton::clicked, this, [=]() {
- QMessageBox::StandardButton reply;
- reply = QMessageBox::question(this, "确认删除", "确定要删除该监控项吗?",
- QMessageBox::Yes | QMessageBox::No);
-
- if (reply == QMessageBox::Yes) {
- // 如果该行正在绘图,则清空绘图
- QPushButton *plotButton = qobject_cast(table->cellWidget(row, 4));
- if (plotButton && plotButton->isChecked()) {
- XNCustomPlot *customPlot = findChild("dataMonitoringCustomPlot");
- if (customPlot) {
- customPlot->clearGraphs();
- customPlot->replot();
- }
- }
- // 清空该行的所有内容
- for (int col = 0; col < table->columnCount(); ++col) {
- if (table->item(row, col)) {
- table->item(row, col)->setText("");
- }
- }
- // 移除按钮组件
- table->removeCellWidget(row, 6);
- // 移除注入按钮
- table->removeCellWidget(row, 8);
- // 移除该行
- table->removeRow(row);
- }
- });
-
- connect(injectOnceButton, &QPushButton::clicked, this, [=]() {
- // 读取更改值单元格的内容
- QTableWidgetItem *changeValueItem = table->item(row, 7);
- if (!changeValueItem || changeValueItem->text().isEmpty()) {
- QMessageBox::warning(this, "警告", "请先输入注入值");
- return;
- }
- emit injectOnceData(modelName, topicName, varName, changeValueItem->text().toDouble());
- });
- connect(injectContinuousButton, &QPushButton::clicked, this, [=]() {
- if (injectContinuousButton->text() == "持续注入") {
- // 读取更改值单元格的内容
- QTableWidgetItem *changeValueItem = table->item(row, 7);
- if (!changeValueItem || changeValueItem->text().isEmpty()) {
- QMessageBox::warning(this, "警告", "请先输入注入值");
- return;
- }
- injectContinuousButton->setText("停止注入");
- emit injectContinuousData(modelName, topicName, varName,
- changeValueItem->text().toDouble());
- } else {
- injectContinuousButton->setText("持续注入");
- emit stopInjectContinuousData(modelName, topicName, varName);
- }
- });
-}
-
-// 设置数据监控右面板
-void DataMonitorWidget::setupTabDataMonitoringRightPanel(QSplitter *splitter)
-{
- // 右栏布局
- QVBoxLayout *rightLayout = new QVBoxLayout();
-
- // 创建一个新的QSplitter用于垂直分割右栏的上下两部分
- QSplitter *verticalSplitter = new QSplitter(Qt::Vertical); // 垂直方向的QSplitter
-
- // 表格布局
- QTableWidget *dataMonitoringTableWidget = new QTableWidget();
- setupDataMonitoringTableWidget(dataMonitoringTableWidget);
-
- // 图表绘制区域
- QWidget *dataMonitoringChartWidget =
- new QWidget(); // 图表区域,可以使用XNCustomPlot等库进行绘制
- setupDataMonitoringChartWidget(dataMonitoringChartWidget); // 配置图表区域
-
- // 将表格和图表添加到垂直分割器中
- verticalSplitter->addWidget(dataMonitoringTableWidget);
- verticalSplitter->addWidget(dataMonitoringChartWidget);
-
- QList sizes;
- sizes << 3 << 2;
- verticalSplitter->setSizes(sizes);
-
- // 将垂直分割器添加到右栏布局中
- rightLayout->addWidget(verticalSplitter);
-
- // 创建一个QWidget作为右栏的容器,并设置其布局为rightLayout
- QWidget *rightPanel = new QWidget();
- rightPanel->setLayout(rightLayout);
-
- // 将右栏容器添加到QSplitter中
- splitter->addWidget(rightPanel);
-}
-
-// 设置数据监控表格
-void DataMonitorWidget::setupDataMonitoringTableWidget(QTableWidget *dataMonitoringTableWidget)
-{
- dataMonitoringTableWidget->setRowCount(0); // 设置初始行数为1(空行)
- dataMonitoringTableWidget->setColumnCount(9); // 设置表格的列数
-
- QFont headerFont("Arial", 16, QFont::Bold);
- dataMonitoringTableWidget->horizontalHeader()->setFont(headerFont);
-
- // 设置表格的列标题
- dataMonitoringTableWidget->setHorizontalHeaderLabels({"接口名称", "主题名称", "模型名称",
- "数据类型", "值", "监控状态", "监控控制",
- "注入值", "数据注入"});
-
- // 设置表格的选择模式为单选
- dataMonitoringTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
-
- // 设置表格仅第8列可编辑
- for (int col = 0; col < dataMonitoringTableWidget->columnCount(); col++) {
- for (int row = 0; row < dataMonitoringTableWidget->rowCount(); row++) {
- QTableWidgetItem *item = dataMonitoringTableWidget->item(row, col);
- if (item) {
- if (col == 7) { // 第8列(索引7)可编辑
- item->setFlags(item->flags() | Qt::ItemIsEditable);
- } else { // 其他列不可编辑
- item->setFlags(item->flags() & ~Qt::ItemIsEditable);
- }
- }
- }
- }
-
- // 设置表格的objectName,以便后续可以通过findChild找到并更新它
- dataMonitoringTableWidget->setObjectName("dataMonitoringTableWidget");
-
- // 设置列宽
- dataMonitoringTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
-
- // 设置各列的固定宽度
- dataMonitoringTableWidget->setColumnWidth(0, 300); // 接口名称列
- dataMonitoringTableWidget->setColumnWidth(1, 100); // 主题名称列
- dataMonitoringTableWidget->setColumnWidth(2, 100); // 模型名称列
- dataMonitoringTableWidget->setColumnWidth(3, 100); // 数据类型列
- dataMonitoringTableWidget->setColumnWidth(4, 100); // 值列
- dataMonitoringTableWidget->setColumnWidth(5, 100); // 监控状态列
- dataMonitoringTableWidget->setColumnWidth(6, 400); // 监控控制列 - 设置更宽以容纳按钮
- dataMonitoringTableWidget->setColumnWidth(7, 100); // 更改值列
- dataMonitoringTableWidget->setColumnWidth(8, 200); // 数据注入列
- dataMonitoringTableWidget->horizontalHeader()->setStretchLastSection(
- true); // 最后一列(数据注入)自适应
-
- // // 初始化第一行的所有列
- // for (int col = 0; col < dataMonitoringTableWidget->columnCount(); ++col) {
- // QTableWidgetItem *item = new QTableWidgetItem();
- // if (col != 0 && col != 5) {
- // item->setFlags(item->flags() & ~Qt::ItemIsEditable);
- // }
- // dataMonitoringTableWidget->setItem(0, col, item);
- // }
-}
-
-// 更新监控数据
-void DataMonitorWidget::updateMonitoringData(const QString &varName, const QString &value)
-{
- if (currentTabIndex != 2)
- return;
-
- QTableWidget *table = findChild("dataMonitoringTableWidget");
- if (!table)
- return;
-
- int row = -1;
- for (int i = 0; i < table->rowCount(); ++i) {
- if (table->item(i, 0) && table->item(i, 0)->text() == varName) {
- row = i;
- break;
- }
- }
-
- if (row != -1) {
- // 更新表格值
- table->item(row, 4)->setText(value);
-
- // 更新数据
- bool ok;
- double dValue = value.toDouble(&ok);
- if (ok) {
- varDataMap[varName].append(dValue);
- if (varDataMap[varName].size() > 100) {
- varDataMap[varName].removeFirst();
- }
-
- // 如果该变量正在绘图,则更新图表
- QString objectName = QString("btn_plot_%1").arg(varName);
- QPushButton *plotButton = findChild(objectName);
- if (plotButton && plotButton->isChecked()) {
- XNCustomPlot *customPlot = findChild("dataMonitoringCustomPlot");
- if (customPlot && customPlot->graph(0)) {
- // 确保使用绿色
- QPen greenPen(Qt::green);
- greenPen.setWidth(2);
- customPlot->graph(0)->setPen(greenPen);
-
- // 保存当前的Y轴范围
- QCPRange yRange = customPlot->yAxis->range();
-
- // 准备数据
- const QVector