From ef7ed1c30011cd37033da98aa2965b09ef13136c Mon Sep 17 00:00:00 2001 From: brige Date: Mon, 17 Nov 2025 00:07:24 +0800 Subject: [PATCH 1/2] fix minsize 10 --- src/main.cpp | 9 ++------- src/ui/FramelessDelegateWin.cpp | 10 ++++++++++ src/ui/FramelessWindow.cpp | 6 ++---- src/ui/MainFrame.cpp | 14 ++------------ src/ui/MainWindow.cpp | 28 ++++++++++------------------ src/ui/MainWindow.h | 1 + src/ui/ModelBrowser.cpp | 4 ++-- src/viewer/OsgWidget.cpp | 26 +++++++++++++++++++------- src/viewer/OsgWidget.h | 11 +++-------- 9 files changed, 51 insertions(+), 58 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index fd8417fb..33b6291b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,15 +59,10 @@ int main(int argc, char* argv[]) { MainFrame mainWindow; splash.showMessage(("正在创建主窗口..."), Qt::AlignHCenter | Qt::AlignBottom, Qt:: white); - // 先显示窗口,再在事件循环启动后最大化,避免首次显示时原生窗口放置未就绪导致尺寸异常 - mainWindow.showMaximized(); - // QTimer::singleShot(0, &mainWindow, &MainFrame::showMaximized); + mainWindow.show(); + QTimer::singleShot(20, &mainWindow, &MainFrame::showMaximized); splash.finish(&mainWindow); - int ret = app.exec(); - // app.Uninit(); - Sleep(200); return ret; - } diff --git a/src/ui/FramelessDelegateWin.cpp b/src/ui/FramelessDelegateWin.cpp index e52b93d1..e994ca7d 100644 --- a/src/ui/FramelessDelegateWin.cpp +++ b/src/ui/FramelessDelegateWin.cpp @@ -172,6 +172,16 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa mmi->ptMaxTrackSize.x = (rcMon.right - rcMon.left) + frameX * 2; mmi->ptMaxTrackSize.y = (rcMon.bottom - rcMon.top) + frameY * 2; + + const QSize minSize = mainWidget_->minimumSize(); + const double dpr = mainWidget_->devicePixelRatioF(); + const int minWpx = static_cast(std::round(minSize.width() * dpr)); + const int minHpx = static_cast(std::round(minSize.height() * dpr)); + // Guard against zero/negative values + const int clampedMinW = std::max(1, minWpx) + frameX * 2; + const int clampedMinH = std::max(1, minHpx) + frameY * 2; + mmi->ptMinTrackSize.x = clampedMinW; + mmi->ptMinTrackSize.y = clampedMinH; } if (::IsZoomed(msg->hwnd)) { diff --git a/src/ui/FramelessWindow.cpp b/src/ui/FramelessWindow.cpp index a941e097..af5dbdb4 100644 --- a/src/ui/FramelessWindow.cpp +++ b/src/ui/FramelessWindow.cpp @@ -11,10 +11,10 @@ FramelessWindow::FramelessWindow(QWidget* parent) | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMaximizeButtonHint - | Qt::WindowMinimizeButtonHint); + | Qt::WindowMinimizeButtonHint + ); delegate_ = FramelessDelegate::Create(this); - } FramelessWindow::~FramelessWindow() { @@ -23,7 +23,6 @@ FramelessWindow::~FramelessWindow() { void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) { titleBar->SetMainWidget(this); if (delegate_) { - // 通知委托当前标题栏,以便把它作为可拖动区域处理。 delegate_->SetTitleBar(titleBar); } } @@ -33,7 +32,6 @@ bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qi #else bool FramelessWindow::nativeEvent(const QByteArray & eventType, void* message, long* result) { #endif - // 先让无边框委托处理原生事件(如 WM_NCHITTEST 以支持边缘拖动缩放)。 if (delegate_ && delegate_->nativeEvent(eventType, message, result)) { return true; } diff --git a/src/ui/MainFrame.cpp b/src/ui/MainFrame.cpp index e2dc092a..bc0ae579 100644 --- a/src/ui/MainFrame.cpp +++ b/src/ui/MainFrame.cpp @@ -36,6 +36,8 @@ MainFrame::MainFrame(QWidget *parent) : ui(new Ui::MainFrame) { ui->setupUi(this); + + setMinimumSize(800, 600); assert(nullptr == s_instance); s_instance = this; @@ -102,13 +104,6 @@ void MainFrame::InitUI() { FileManagerMenu* fileMenu = new FileManagerMenu(this); AddMenuWidget("file_manager", tr("file manager"), fileMenu); - //AddMenuWidget("view_manager", tr("view manager"), new ViewManagerMenu(this)); - //AddMenuWidget("plan_manager", tr("plan manager"), new PlanManagerMenu(this)); - //AddMenuWidget("dynamic_display", tr("dynamic display"), new DynamicDisplayMenu(this)); - // ChartPlotMenu* chartMenu = new ChartPlotMenu(this); - // AddMenuWidget("simu_manager", tr("simu manager"), chartMenu); - - // Command buttons menu based on parsed commands SimuRunMenu* simuRunMenu = new SimuRunMenu(this); AddMenuWidget("simu_manager", tr("simu manager"), simuRunMenu); @@ -123,11 +118,6 @@ void MainFrame::InitUI() { simuRunMenu->SetMainWindow(mainWindow); - /*OsgWidget* viewWidget = mainWindow->GetViewWidget(); - connect(fileMenu, &FileManagerMenu::LoadDyt, viewWidget, &OsgWidget::OnLoadDyt);*/ - - //connect(system_, &SystemManagerMenu::signalShowUISetting, mainWindow, &MainWindow::slotShowUISetting); - if (ui->menuWidget->count() > 0) { ui->menuWidget->setCurrentIndex(0); menuWidget_.isEmpty() ? assert(false) : menuWidget_.key(0)->setChecked(true); diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index d4ec800a..9c570e4f 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -38,11 +38,12 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); + setMinimumSize(800, 600); LOG_INFO("MainWindow::MainWindow - Constructor called, about to call InitUI"); InitUI(); LOG_INFO("MainWindow::MainWindow - Constructor completed"); -} +} MainWindow::~MainWindow() { UninitUI(); @@ -70,7 +71,6 @@ void MainWindow::InitUI() { mapDockWidget_.insert("ModelBrowser", model); addDockWidget(Qt::LeftDockWidgetArea, model); - // 创建预制模型面板 DockWidget* presetModel = new DockWidget(tr("preset models"), 0); presetModel->SetDockWidgetTitleBar(new DockTitleBar(presetModel)); presetModel->setObjectName("Dock.PresetModelPanel"); @@ -82,11 +82,8 @@ void MainWindow::InitUI() { DockWidget* attribte = new DockWidget(tr("attribte"), 0); attribte->SetDockWidgetTitleBar(new DockTitleBar(attribte)); attribte->setObjectName("Dock.PropertyBrowser"); - //addDockWidget(pSettingUI->GetArea("PropertyBrowser"), attribte); propertyBrowser_ = new PropertyBrowser(0); propertyBrowser_->AttachDock(attribte); - // Ensure property panel has a reasonable minimum width; no maximum limit - attribte->setMinimumWidth(240); mapDockWidget_.insert("PropertyBrowser", attribte); addDockWidget(Qt::RightDockWidgetArea, attribte); @@ -106,23 +103,18 @@ void MainWindow::InitUI() { connect(modelBrowser_, &ModelBrowser::FileEntryChange, propertyBrowser_, &PropertyBrowser::OnFileEntryChange); connect(modelBrowser_, &ModelBrowser::GroupChange, propertyBrowser_, &PropertyBrowser::OnGroupChange); - qtOsgViewWidget_ = new OsgWidget; + qtOsgViewWidget_ = new OsgWidget(0); qtOsgViewWidget_->Initialize(); - DockWidget* viewDock = new DockWidget(tr("Main View"), 0); - viewDock->SetDockWidgetTitleBar(new DockTitleBar(viewDock)); - viewDock->setObjectName("Dock.MainView"); - viewDock->setWidget(qtOsgViewWidget_); - // Ensure main view has a reasonable minimum size to avoid being squeezed - // Use smaller minimum size to support smaller displays - qtOsgViewWidget_->setMinimumSize(640, 480); - viewDock->setMinimumSize(640, 480); - addDockWidget(Qt::LeftDockWidgetArea, viewDock); - mapDockWidget_.insert("MainView", viewDock); + DockWidget* mainView = new DockWidget(tr("Main View"), 0); + mainView->SetDockWidgetTitleBar(new DockTitleBar(mainView)); + mainView->setObjectName("Dock.MainView"); + qtOsgViewWidget_->AttachDock(mainView); + mapDockWidget_.insert("MainView", mainView); + addDockWidget(Qt::RightDockWidgetArea, mainView); - splitDockWidget(model, viewDock, Qt::Horizontal); + splitDockWidget(model, mainView, Qt::Horizontal); - // 将预制模型面板与模型浏览器标签化 tabifyDockWidget(model, presetModel); dataPanelManager_ = new DataPanelManager(this, this); diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index c8cbd9db..583db78a 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -48,6 +48,7 @@ private: class PropertyBrowser* propertyBrowser_{ nullptr }; class QWebEngineView* webEngineView_{ nullptr }; class OsgWidget* qtOsgViewWidget_{ nullptr }; + //QWidget* qtOsgViewWidget_{ nullptr }; class SignalIndicatorLampUI* signalIndicatorLampUI_{ nullptr }; class CodeEdtUI* matlabFileDlg_{ nullptr }; diff --git a/src/ui/ModelBrowser.cpp b/src/ui/ModelBrowser.cpp index 3ed28ba8..56bd748c 100644 --- a/src/ui/ModelBrowser.cpp +++ b/src/ui/ModelBrowser.cpp @@ -3,8 +3,8 @@ #include #include -#include "DockTitleBar.h" -#include "DockWidget.h" +#include "ui/DockTitleBar.h" +#include "ui/DockWidget.h" #include "ModelBrowser/ModelTreeWidget.h" #include "workspace/WorkSpaceManager.h" diff --git a/src/viewer/OsgWidget.cpp b/src/viewer/OsgWidget.cpp index 76c4f7ca..45983ea3 100644 --- a/src/viewer/OsgWidget.cpp +++ b/src/viewer/OsgWidget.cpp @@ -21,7 +21,6 @@ #include "OsgViewer.h" #include "common/SpdLogger.h" #include "scene/OEScene.h" -#include "ui/MainFrame.h" #include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpace.h" #include "scutcheon/osgScutcheon.h" @@ -33,6 +32,10 @@ #include "entities/Entity.h" #include "entities/Component.h" +#include "ui/DockTitleBar.h" +#include "ui/DockWidget.h" +#include "ui/MainFrame.h" + static void ConfigureView( osgViewer::View* view ) { view->addEventHandler(new osgViewer::StatsHandler()); view->addEventHandler(new osgViewer::WindowSizeHandler()); @@ -55,14 +58,13 @@ OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags f) setThreadingModel(osgViewer::ViewerBase::SingleThreaded); setMouseTracking(true); setKeyEventSetsDone(0); - - // 启用拖拽接收 + setAcceptDrops(true); connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) ); timer_.start( 10 ); - setMinimumSize(100, 100); + //setMinimumSize(800, 100); LOG_INFO("OsgWidget::OsgWidget"); } @@ -131,6 +133,19 @@ void OsgWidget::LoadDefaultScene() { } } +void OsgWidget::AttachDock(DockWidget* dockWidget) { + if (nullptr == dockWidget) { + qDebug() << __FUNCTION__ << "dockwidget is nullptr"; + return; + } + + dockWidget->SetDockWidgetTitleBar(nullptr); + dockWidget->setWidget(this); + + DockTitleBar* dockTitleBar = new DockTitleBar; + dockWidget->SetDockWidgetTitleBar(dockTitleBar); +} + osgQt::GraphicsWindowQt* OsgWidget::createGraphicsWindow(int x, int y, int w, int h, const std::string& name, bool windowDecoration) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); @@ -199,7 +214,6 @@ void OsgWidget::dragEnterEvent(QDragEnterEvent* event) { } void OsgWidget::dragMoveEvent(QDragMoveEvent* event) { - // 检查是否是预制模型拖拽 if (event->mimeData()->hasFormat("application/x-preset-model")) { event->acceptProposedAction(); } else { @@ -249,11 +263,9 @@ void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& mo } osg::Viewport* vp = view_->getCamera()->getViewport(); - // 将屏幕坐标转换为世界坐标 double longitude, latitude, height; if (!ScreenToWorldCoordinate(static_cast(position.x()), static_cast(vp->height() - position.y()), longitude, latitude, height)) { LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates"); - // 使用默认位置 longitude = 0.0; latitude = 0.0; height = 0.0; diff --git a/src/viewer/OsgWidget.h b/src/viewer/OsgWidget.h index a11cf9a8..d906da2e 100644 --- a/src/viewer/OsgWidget.h +++ b/src/viewer/OsgWidget.h @@ -11,12 +11,14 @@ class OsgWidget : public QWidget, public osgViewer::CompositeViewer { public: OsgWidget(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); ~OsgWidget() override; - QPaintEngine* paintEngine() const override { return nullptr; } + QPaintEngine* paintEngine() const override { return nullptr; } void Initialize(void); void Uninitialize(void); void LoadDefaultScene(void); + void AttachDock(class DockWidget* dockWidget); + signals: void signalScaleInfo(const QString&); @@ -28,18 +30,11 @@ protected: void resizeEvent(QResizeEvent* event) override; void paintEvent( QPaintEvent* /*event*/ ) override; - // 拖拽事件处理 void dragEnterEvent(QDragEnterEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override; void dropEvent(QDropEvent* event) override; public slots: - /** - * @brief 处理预制模型拖拽 - * @param modelType 模型类型 - * @param modelName 模型名称 - * @param position 屏幕位置(可选) - */ void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF()); bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude); From d9c64eb1b3d620bc78109c3205f3725b6ad23947 Mon Sep 17 00:00:00 2001 From: brige Date: Mon, 17 Nov 2025 01:58:50 +0800 Subject: [PATCH 2/2] add version and fix min size --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 25 +++++++++---- src/entities/PathComponent.cpp | 4 --- src/res/dyt.rc | 1 - src/res/dyt.rc.in | 36 +++++++++++++++++++ src/ui/FrameTitleBar.cpp | 1 - src/ui/FramelessDelegate.cpp | 1 - src/ui/Menu/PlayManagerMenu.cpp | 3 -- src/ui/PropertyBrowser.cpp | 19 ---------- .../PropertyBrowser/qtworkspaceattribute.cpp | 3 -- src/ui/PropertyBrowser/qtworkspaceattribute.h | 2 -- src/utils/TransformPath.cpp | 5 --- src/workspace/Timestep.cpp | 3 -- src/workspace/WorkSpace.cpp | 4 --- src/workspace/WorkSpaceXMLParse.cpp | 27 ++------------ src/workspace/WorkSpaceXMLWrite.cpp | 7 ---- 16 files changed, 58 insertions(+), 85 deletions(-) delete mode 100644 src/res/dyt.rc create mode 100644 src/res/dyt.rc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b9fc80d..1b44c57a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.21) -PROJECT(Dyt) +project(Dyt VERSION 1.0.0) option(USE_HOST_EVENT_LOOP "Enable the integration of CEF message loop thread into host event loop" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dcfef2ad..bb0626e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,3 @@ -PROJECT(Dyt) - set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -19,7 +17,22 @@ FILE(GLOB_RECURSE CPP_FILES ./*.cpp common/*.cpp model/*.cpp app/*.cpp utils/*.c FILE(GLOB_RECURSE CC_FILES ./*.cc) FILE(GLOB_RECURSE UI_FILES ./*.ui) FILE(GLOB_RECURSE QRC_FILES ./*.qrc) -FILE(GLOB_RECURSE RC_FILES ./res/*.rc) +## Configure Windows resource file with version info (exposed to cmake-gui) +set(DYT_COMPANY_NAME "DYT" CACHE STRING "Company name for version resource") +set(DYT_PRODUCT_NAME "DYT" CACHE STRING "Product name for version resource") +set(DYT_FILE_DESCRIPTION "Dyt Application" CACHE STRING "File description for version resource") +set(DYT_COPYRIGHT "(C) 2025 DYT" CACHE STRING "Legal copyright for version resource") + +# Read version from top-level project definition and expose as editable cache entries +set(DYT_VERSION_MAJOR "${Dyt_VERSION_MAJOR}" CACHE STRING "Major version for version resource") +set(DYT_VERSION_MINOR "${Dyt_VERSION_MINOR}" CACHE STRING "Minor version for version resource") +set(DYT_VERSION_PATCH "${Dyt_VERSION_PATCH}" CACHE STRING "Patch version for version resource") +set(DYT_VERSION "${Dyt_VERSION}" CACHE STRING "Product version string for version resource") + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/res/dyt.rc.in + ${PROJECT_BINARY_DIR}/dyt.rc +) SET( TS_FILES @@ -77,7 +90,7 @@ SET( ) configure_file( - ${PROJECT_SOURCE_DIR}/config.cpp.in + ${CMAKE_CURRENT_SOURCE_DIR}/config.cpp.in ${PROJECT_BINARY_DIR}/config.cpp ) @@ -88,10 +101,10 @@ SET( ${CC_FILES} ${UI_FILES} ${QRC_FILES} - ${RC_FILES} + ${PROJECT_BINARY_DIR}/dyt.rc ${QM_FILES} ${PROJECT_BINARY_DIR}/config.cpp - ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.manifest + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.manifest ) INCLUDE_DIRECTORIES( diff --git a/src/entities/PathComponent.cpp b/src/entities/PathComponent.cpp index 40b2b5a6..014b1be7 100644 --- a/src/entities/PathComponent.cpp +++ b/src/entities/PathComponent.cpp @@ -62,7 +62,6 @@ void PathComponent::Begin() { animationPath_->clear(); - // 优先使用路径文件的时间列;若不存在则按当前时间范围等间距生成时间点 std::vector mappedSteps; const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty(); double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0; @@ -70,7 +69,6 @@ void PathComponent::Begin() { if (hasPathTimes) { const auto& times = transformPath_->GetTimes(); if (timeStep_->HasManualRange()) { - // 使用文件时间为主:仅截取手动范围内的原始时间点 double dstMin = timeStep_->GetManualStart(); double dstMax = timeStep_->GetManualEnd(); mappedSteps.reserve(times.size()); @@ -79,7 +77,6 @@ void PathComponent::Begin() { mappedSteps.push_back(t); } } - // 若截取后为空,回退为原始时间列,避免动画路径为空 if (mappedSteps.empty()) { mappedSteps = times; } @@ -94,7 +91,6 @@ void PathComponent::Begin() { double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin; double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax; double step = rangeStep; - // 若步长无效,则回退为均匀分布 if (step <= 0.0) { step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0; } diff --git a/src/res/dyt.rc b/src/res/dyt.rc deleted file mode 100644 index 94305d7c..00000000 --- a/src/res/dyt.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON ICON DISCARDABLE ".\\res\\sys_icon.ico" diff --git a/src/res/dyt.rc.in b/src/res/dyt.rc.in new file mode 100644 index 00000000..b8762b0a --- /dev/null +++ b/src/res/dyt.rc.in @@ -0,0 +1,36 @@ +IDI_ICON ICON DISCARDABLE "@CMAKE_CURRENT_SOURCE_DIR@/res/sys_icon.ico" + +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @DYT_VERSION_MAJOR@,@DYT_VERSION_MINOR@,@DYT_VERSION_PATCH@,0 + PRODUCTVERSION @DYT_VERSION_MAJOR@,@DYT_VERSION_MINOR@,@DYT_VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "@DYT_COMPANY_NAME@\0" + VALUE "FileDescription", "@DYT_FILE_DESCRIPTION@\0" + VALUE "FileVersion", "@DYT_VERSION@\0" + VALUE "InternalName", "@PROJECT_NAME@\0" + VALUE "OriginalFilename", "@PROJECT_NAME@.exe\0" + VALUE "ProductName", "@DYT_PRODUCT_NAME@\0" + VALUE "ProductVersion", "@DYT_VERSION@\0" + VALUE "LegalCopyright", "@DYT_COPYRIGHT@\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1200 + END +END \ No newline at end of file diff --git a/src/ui/FrameTitleBar.cpp b/src/ui/FrameTitleBar.cpp index dd99f9d1..e1487169 100644 --- a/src/ui/FrameTitleBar.cpp +++ b/src/ui/FrameTitleBar.cpp @@ -54,7 +54,6 @@ void FrameTitleBar::SetMainWidget(QWidget* widget) { } } void FrameTitleBar::OnMaximized(bool maximized) { - // 根据配置位决定是否显示最大/还原按钮,并切换图标 const bool hasMaxButton = (ftbButton_ & FTB_MAX) != 0; ui->sys_max->setVisible(hasMaxButton); if (!hasMaxButton) { diff --git a/src/ui/FramelessDelegate.cpp b/src/ui/FramelessDelegate.cpp index b1f86ed2..ff11ab14 100644 --- a/src/ui/FramelessDelegate.cpp +++ b/src/ui/FramelessDelegate.cpp @@ -41,7 +41,6 @@ void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) { titleBar_ = titleBar; if (nullptr != titleBar_) { - // 跟踪标题栏显示/隐藏,以便在显示时注册为可移动区域 titleBar_->installEventFilter(this); } } diff --git a/src/ui/Menu/PlayManagerMenu.cpp b/src/ui/Menu/PlayManagerMenu.cpp index db21c462..e7b95326 100644 --- a/src/ui/Menu/PlayManagerMenu.cpp +++ b/src/ui/Menu/PlayManagerMenu.cpp @@ -118,7 +118,6 @@ void PlayManagerMenu::OnWorkspaceChange(WorkSpace* workSpace) { } workSpace_ = workSpace; connect(workSpace, &WorkSpace::TimestepChanged, this, &PlayManagerMenu::OnTimestepChanged); - // 若当前 workspace 已有 timestep,则立即刷新一次 UI if (auto* timestep = workSpace->GetTimestep()) { OnTimestepChanged(timestep); } @@ -140,12 +139,10 @@ void PlayManagerMenu::OnTimestepChanged(Timestep* timestep) { ui->horizontalSlider->setValue(int(dt)); } ); - // 监听倍速改变(SpeedChanged):更新显示为 x倍速 connect(timestep, &Timestep::StepChanged, [this](double speed) { ui->lbUp->setText(QString("x%1").arg(speed)); } ); - // 当时间范围更新(例如用户在属性面板设置了起止时间)时,刷新显示与滑条范围 connect(timestep, &Timestep::RangeChanged, [this](double minTime, double maxTime, double step, double speed) { minTime_ = minTime; maxTime_ = maxTime; diff --git a/src/ui/PropertyBrowser.cpp b/src/ui/PropertyBrowser.cpp index 30f2caff..b3c94e67 100644 --- a/src/ui/PropertyBrowser.cpp +++ b/src/ui/PropertyBrowser.cpp @@ -48,7 +48,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) { WorkSpace* workspace = value.value(); if (nullptr == workspace) { LOG_WARN("workspace is nullptr"); - // 如果没有属性对象,清空属性面板 browser_->clear(); propertyToId_.clear(); idToProperty_.clear(); @@ -57,7 +56,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) { return; } - // 点击根项目需要清空属性面板,不展示工作区属性 browser_->clear(); propertyToId_.clear(); idToProperty_.clear(); @@ -71,7 +69,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) { workSpaceManager_->setValue(property, worksapceAttribute); addProperty(property, tr("WorkSpace")); - // 保持对运行时工作区变更的监听(树刷新所需),但属性面板保持清空 if (currentWorkspace_) { QObject::disconnect(currentWorkspace_, nullptr, this, nullptr); } @@ -79,7 +76,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) { QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged, this, &PropertyBrowser::OnWorkspaceFilesChanged); - // 属性面板清空,文件项属性由 FileEntry 点击时单独处理 } void PropertyBrowser::OnEntityChange(const QVariant& value) { @@ -87,7 +83,6 @@ void PropertyBrowser::OnEntityChange(const QVariant& value) { Entity* entity = value.value(); if (nullptr == entity) { LOG_WARN("engity is nullptr"); - // 如果没有属性对象,清空属性面板 browser_->clear(); propertyToId_.clear(); idToProperty_.clear(); @@ -141,7 +136,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { FileEntry* entry = value.value(); if (!entry) { LOG_WARN("file entry is nullptr"); - // 如果没有属性对象,清空属性面板 inFileEntryView_ = false; browser_->clear(); propertyToId_.clear(); @@ -173,7 +167,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { //if (!curve) { LOG_WARN("file entry not a curve: %s", entry->GetFileName().toStdString().c_str()); - // 基础信息组 const QString idBasic = QString("FileEntry:%1").arg(entry->GetFileName()); const QString titleBasic = QString("File Entry - %1").arg(entry->GetName()); QtProperty* groupBasic = groupManager_->addProperty(tr("Basic")); @@ -205,7 +198,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { addProperty(groupBasic, idBasic); - // 类型专属属性显示 switch (entry->GetType()) { case FileEntryType::Curve: @@ -453,7 +445,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { const QString titleChart = QString("Surface Chart - %1").arg(entry->GetName()); const QString titleItems = QString("Surfaces - %1").arg(entry->GetName()); - // Chart 属性 QtProperty* chartGroup = groupManager_->addProperty(tr("Chart")); const auto& chart = surf->GetChartProperties(); QtProperty* xCountProp = intManager_->addProperty(tr("xCount")); @@ -600,7 +591,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { addProperty(chartGroup, idChart); - // Surface 列表 QtProperty* itemsGroup = groupManager_->addProperty(tr("SurfacesProp")); const auto& items = surf->GetSurfaceProperties(); for (int i = 0; i < items.size(); ++i) @@ -626,7 +616,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { QtProperty* col = colorManager_->addProperty(tr("color")); colorManager_->setValue(col, s.color); itemGroup->addSubProperty(col); - // 写回 Surface 条目颜色 colorSetters_[col] = [surf, entry, i](const QColor& c) { auto props = surf->GetSurfaceProperties(); @@ -768,7 +757,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { // QtProperty* col = colorManager_->addProperty(tr("color")); // colorManager_->setValue(col, t.color); // itemGroup->addSubProperty(col); - // // 写回 Table 条目颜色 // colorSetters_[col] = [tbl, entry, i](const QColor& c){ // auto props = tbl->GetTableProperties(); // if (i >= 0 && i < props.size()) { @@ -778,7 +766,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { // if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType()); // } // }; - // // datas 展示为拼接字符串 // QStringList values; // for (const auto& v : t.datas) values << QString::number(v); // QtProperty* ds = stringManager_->addProperty(tr("datas")); @@ -800,7 +787,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { const QString titleColor = QString("Light Colors - %1").arg(entry->GetName()); const QString titleRows = QString("Light Rows - %1").arg(entry->GetName()); - // 颜色与时间 QtProperty* colorGroup = groupManager_->addProperty(tr("Chart")); const auto& colorProps = lt->GetColorProperties(); QtProperty* oc = colorManager_->addProperty(tr("openColor")); @@ -822,7 +808,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { }; addProperty(colorGroup, idColor); - // 写回处理:颜色变化更新到 FileEntryLight 并通知 Workspace colorSetters_[oc] = [lt, entry](const QColor& c) { auto props = lt->GetColorProperties(); @@ -838,7 +823,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType()); }; - // 行数据 QtProperty* rowsGroup = groupManager_->addProperty(tr("Light Rows")); const auto& rows = lt->GetLightProperties(); for (int i = 0; i < rows.size(); ++i) @@ -987,7 +971,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { QtProperty* col = colorManager_->addProperty(tr("color")); colorManager_->setValue(col, ln.color); line->addSubProperty(col); - // 写回 Polar 线颜色 colorSetters_[col] = [pl, entry, i](const QColor& c) { auto props = pl->GetLineProperties(); @@ -1165,7 +1148,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) { break; } - // 聚焦基础信息组 if (groupBasic) { QtBrowserItem* item = browser_->topLevelItem(groupBasic); if (item) { @@ -1270,7 +1252,6 @@ void PropertyBrowser::InitPropertyManager() { browser_->setFactoryForManager(curveEntryManager_->subDoubleProperyManager(), doubleSpinBoxFactory); browser_->setFactoryForManager(curveEntryManager_->subColorProperyManager(), colorFactory); - // 颜色属性变更信号:触发对应写回处理器 connect(colorManager_, &QtColorPropertyManager::valueChanged, this, [this](QtProperty* prop, const QColor& color){ if (colorSetters_.contains(prop)) { diff --git a/src/ui/PropertyBrowser/qtworkspaceattribute.cpp b/src/ui/PropertyBrowser/qtworkspaceattribute.cpp index 7be4d3b4..d174758b 100644 --- a/src/ui/PropertyBrowser/qtworkspaceattribute.cpp +++ b/src/ui/PropertyBrowser/qtworkspaceattribute.cpp @@ -61,9 +61,6 @@ const QString QWorkspaceAttribute::GetDescription() const { return workspace_->GetDescribe(); } - -// 已移除:时间步长文件路径设置/获取(不再从文件读取) - void QWorkspaceAttribute::SetSimulationStart(double start) { if (!workspace_) return; Timestep* t = workspace_->GetTimestep(); diff --git a/src/ui/PropertyBrowser/qtworkspaceattribute.h b/src/ui/PropertyBrowser/qtworkspaceattribute.h index a97996e0..09269158 100644 --- a/src/ui/PropertyBrowser/qtworkspaceattribute.h +++ b/src/ui/PropertyBrowser/qtworkspaceattribute.h @@ -62,8 +62,6 @@ public: void SetDescription(const QString& desc); const QString GetDescription() const; - // 已移除:时间步长文件路径(不再从文件读取) - // Simulation time (manual range) for playback void SetSimulationStart(double start); double GetSimulationStart() const; diff --git a/src/utils/TransformPath.cpp b/src/utils/TransformPath.cpp index 336cad0d..71ec1b2a 100644 --- a/src/utils/TransformPath.cpp +++ b/src/utils/TransformPath.cpp @@ -53,7 +53,6 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent) } bool ok = false; - // 解析各字段 const double time = parts[0].toDouble(&ok); if (!ok) { LOG_WARN("invalid time: {}", parts[0].toStdString()); return {}; } const double longitude= parts[1].toDouble(&ok); if (!ok) { LOG_WARN("invalid longitude: {}", parts[1].toStdString()); return {}; } const double latitude = parts[2].toDouble(&ok); if (!ok) { LOG_WARN("invalid latitude: {}", parts[2].toStdString()); return {}; } @@ -63,13 +62,9 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent) const double roll = parts[6].toDouble(&ok); if (!ok) { LOG_WARN("invalid roll: {}", parts[6].toStdString()); return {}; } Transform transform; - // 位置映射:经度->x,纬度->y,高度->z transform.GetLocation().set(longitude, latitude, altitude); - // 旋转向量采用代码库约定顺序(Pitch, Roll, Heading),与 OsgUtils::HPRToQuat/QuatToHPR 保持一致 transform.GetRotation().set(pitch, roll, heading); - // 当前 PathComponent 使用 WorkSpace 的 Timestep 作为时间轴,这里暂不保存 time 字段 - // 现在记录时间以支持按路径文件驱动回放 times.push_back(time); transforms.push_back(transform); diff --git a/src/workspace/Timestep.cpp b/src/workspace/Timestep.cpp index fa6d75d1..27cf2656 100644 --- a/src/workspace/Timestep.cpp +++ b/src/workspace/Timestep.cpp @@ -25,7 +25,6 @@ void Timestep::SetManualRange(double start, double end) { manualStart_ = start; manualEnd_ = end; maxTime_ = end; - // 通知 UI 更新范围与步进 double minTime = 0.0, maxTime = 0.0, step = 1.0; GetRange(minTime, maxTime, step); emit RangeChanged(minTime, maxTime, step, currentSpeed_); @@ -126,7 +125,6 @@ void Timestep::Stop() { } void Timestep::Up() { - // 提升到下一个倍率(封顶) if (speedIndex_ < int(speedLevels_.size()) - 1) { ++speedIndex_; } @@ -168,7 +166,6 @@ void Timestep::SetSpeed(double speed) { } void Timestep::SetStep(double step) { - // 更新时间轴步进间隔,并通知 UI 范围与步进发生变化 stepInterval_ = step; double minTime = 0.0, maxTime = 0.0, s = 0.0; GetRange(minTime, maxTime, s); diff --git a/src/workspace/WorkSpace.cpp b/src/workspace/WorkSpace.cpp index b3088522..c0c9c98d 100644 --- a/src/workspace/WorkSpace.cpp +++ b/src/workspace/WorkSpace.cpp @@ -367,13 +367,11 @@ void WorkSpace::ExecuteCommands(CommandWhen when) { cmdMgr_->Execute(this, when); } -// 统一属性更新通知:不改变数量,仅提升序号并广播 FilesChanged void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr fileEntry) { ++filesSeq_; emit FilesChanged(type, fileEntry); } -// 删除指定指针的文件条目(不删除物理文件,仅移出工作空间管理) bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) { if (!entry) { LOG_WARN("RemoveFileEntry: entry is nullptr"); @@ -397,7 +395,6 @@ bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) { return true; } -// 按索引删除文件条目 bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) { auto it = files_.find(type); if (it == files_.end()) { @@ -416,7 +413,6 @@ bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) { return true; } -// 按文件名删除文件条目(匹配工作空间内记录的文件名) bool WorkSpace::RemoveFileEntryByName(FileEntryType type, const QString& fileName) { auto it = files_.find(type); if (it == files_.end()) { diff --git a/src/workspace/WorkSpaceXMLParse.cpp b/src/workspace/WorkSpaceXMLParse.cpp index ad402217..edb489ab 100644 --- a/src/workspace/WorkSpaceXMLParse.cpp +++ b/src/workspace/WorkSpaceXMLParse.cpp @@ -60,14 +60,13 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) { LOG_WARN("element is nullptr"); return false; } - // 确保存在 Timestep 实例 + workSpace_->EnsureTimestep(); Timestep* t = workSpace_->GetTimestep(); if (!t) { return false; } - // 解析属性:manual(0/1)、start、end、step int manualFlag = 0; element->QueryIntAttribute("manual", &manualFlag); double start = 0.0; @@ -85,7 +84,6 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) { t->SetStep(step); } - // 若标记为手动或具有完整的 start/end,则设置手动范围;否则按数据最大时间设置边界 if (manualFlag != 0 || (hasStart && hasEnd)) { t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0); } else if (hasEnd) { @@ -122,7 +120,6 @@ bool WorkSpaceXMLParse::ParseCommond(const tinyxml2::XMLElement* element) { return false; } - // Set the command file path using the filename stored in XML workSpace_->commondPath_ = path; return true; } @@ -133,19 +130,15 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) { return false; } - // 首先处理新的Chart元素结构 const tinyxml2::XMLElement* chartElement = element->FirstChildElement("Chart"); while (nullptr != chartElement) { - // 创建FileEntryCurve对象来解析Chart数据 auto curveEntry = CreateEmptyFileEntryCurve(); if (curveEntry && curveEntry->ParseFiles(chartElement)) { - // 添加解析后的FileEntry到workspace workSpace_->SetFileEntry(curveEntry, false); } chartElement = chartElement->NextSiblingElement("Chart"); } - // 保持向后兼容:处理旧的type元素结构 const tinyxml2::XMLElement* typeElement = element->FirstChildElement("type"); while (nullptr != typeElement) { const char* name = typeElement->Attribute("name"); @@ -155,17 +148,14 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) { if (nullptr != name && count > 0) { QString typeName = QString::fromLocal8Bit(name); - // Create FileEntry objects and call their ParseFiles method FileEntryType enumType; if (FileEntryTypeFromString(name, enumType)) { const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart"); while (nullptr != chartElement) { - auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing + auto fileEntry = CreateEmptyFileEntry(enumType); if (fileEntry) { - // Call the FileEntry's ParseFiles method to parse detailed data if (fileEntry->ParseFiles(chartElement)) { - // Add the parsed FileEntry to workspace workSpace_->SetFileEntry(fileEntry, false); } } @@ -173,19 +163,6 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) { chartElement = chartElement->NextSiblingElement(); } - // Create FileEntry objects for this type - //for (int i = 0; i < count; ++i) { - // auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing - // if (fileEntry) { - // // Call the FileEntry's ParseFiles method to parse detailed data - // if (fileEntry->ParseFiles(typeElement)) { - // // Add the parsed FileEntry to workspace - // workSpace_->SetFileEntry(fileEntry, false); - // } - // } - //} - - // Also set file entry count for backward compatibility workSpace_->SetFileEntryCount(enumType, count); } } diff --git a/src/workspace/WorkSpaceXMLWrite.cpp b/src/workspace/WorkSpaceXMLWrite.cpp index d6a28748..1cdf2f69 100644 --- a/src/workspace/WorkSpaceXMLWrite.cpp +++ b/src/workspace/WorkSpaceXMLWrite.cpp @@ -66,15 +66,12 @@ bool WorkSpaceXMLWrite::SaveScene(tinyxml2::XMLElement* scene) { return true; } -// Removed: SaveTimeStep — timestep is no longer file-based -// 新增:保存 Timestep 的手动范围与步长倍率 bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) { if (nullptr == workSpace_) { return false; } auto* t = workSpace_->GetTimestep(); if (!t) { - // 若尚未创建,确保存在一个默认实例,以保证文件的一致性 workSpace_->EnsureTimestep(); t = workSpace_->GetTimestep(); } @@ -114,7 +111,6 @@ bool WorkSpaceXMLWrite::SaveCommond(tinyxml2::XMLElement* scene) { const QString commondPath = workSpace_->GetCommondFilePath(); if (!commondPath.isEmpty()) { tinyxml2::XMLElement* commond = scene->InsertNewChildElement("commond"); - // Extract just the filename from the full path for storage QFileInfo fileInfo(commondPath); commond->SetAttribute("path", fileInfo.fileName().toStdString().c_str()); } @@ -129,7 +125,6 @@ bool WorkSpaceXMLWrite::SaveEntities(tinyxml2::XMLElement* scene, tinyxml2::XMLD bool WorkSpaceXMLWrite::SaveChart(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) { - // charts section retained for compatibility, but deprecated entries (Wave, Report, RD, SimMatlab) are no longer saved tinyxml2::XMLElement* charts = doc->NewElement("charts"); scene->LinkEndChild(charts); @@ -137,7 +132,6 @@ bool WorkSpaceXMLWrite::SaveChart(tinyxml2::XMLElement* scene, tinyxml2::XMLDocu } bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) { - // Persist multi-file entries per type as counts tinyxml2::XMLElement* files = doc->NewElement("files"); scene->LinkEndChild(files); @@ -149,7 +143,6 @@ bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocu typeElem->SetAttribute("count", static_cast(vec.size())); files->LinkEndChild(typeElem); - // Call SaveFiles method for each FileEntry to save detailed data for (const auto& fileEntry : vec) { if (fileEntry) { fileEntry->SaveFiles(typeElem, doc);