Merge branch 'new_osg' of http://brigecode.icu:16623/PM/DYTSrouce into new_osg

This commit is contained in:
pimin 2025-11-17 09:22:16 +08:00
commit c580fed0b4
25 changed files with 109 additions and 143 deletions

View File

@ -1,6 +1,6 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.21) CMAKE_MINIMUM_REQUIRED(VERSION 3.21)
PROJECT(Dyt) project(Dyt VERSION 1.0.0)
option(USE_HOST_EVENT_LOOP option(USE_HOST_EVENT_LOOP
"Enable the integration of CEF message loop thread into host event loop" "Enable the integration of CEF message loop thread into host event loop"

View File

@ -1,5 +1,3 @@
PROJECT(Dyt)
set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC 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 CC_FILES ./*.cc)
FILE(GLOB_RECURSE UI_FILES ./*.ui) FILE(GLOB_RECURSE UI_FILES ./*.ui)
FILE(GLOB_RECURSE QRC_FILES ./*.qrc) 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( SET(
TS_FILES TS_FILES
@ -77,7 +90,7 @@ SET(
) )
configure_file( configure_file(
${PROJECT_SOURCE_DIR}/config.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/config.cpp.in
${PROJECT_BINARY_DIR}/config.cpp ${PROJECT_BINARY_DIR}/config.cpp
) )
@ -88,10 +101,10 @@ SET(
${CC_FILES} ${CC_FILES}
${UI_FILES} ${UI_FILES}
${QRC_FILES} ${QRC_FILES}
${RC_FILES} ${PROJECT_BINARY_DIR}/dyt.rc
${QM_FILES} ${QM_FILES}
${PROJECT_BINARY_DIR}/config.cpp ${PROJECT_BINARY_DIR}/config.cpp
${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.manifest ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.manifest
) )
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(

View File

@ -62,7 +62,6 @@ void PathComponent::Begin() {
animationPath_->clear(); animationPath_->clear();
// 优先使用路径文件的时间列;若不存在则按当前时间范围等间距生成时间点
std::vector<double> mappedSteps; std::vector<double> mappedSteps;
const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty(); const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty();
double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0; double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0;
@ -70,7 +69,6 @@ void PathComponent::Begin() {
if (hasPathTimes) { if (hasPathTimes) {
const auto& times = transformPath_->GetTimes(); const auto& times = transformPath_->GetTimes();
if (timeStep_->HasManualRange()) { if (timeStep_->HasManualRange()) {
// 使用文件时间为主:仅截取手动范围内的原始时间点
double dstMin = timeStep_->GetManualStart(); double dstMin = timeStep_->GetManualStart();
double dstMax = timeStep_->GetManualEnd(); double dstMax = timeStep_->GetManualEnd();
mappedSteps.reserve(times.size()); mappedSteps.reserve(times.size());
@ -79,7 +77,6 @@ void PathComponent::Begin() {
mappedSteps.push_back(t); mappedSteps.push_back(t);
} }
} }
// 若截取后为空,回退为原始时间列,避免动画路径为空
if (mappedSteps.empty()) { if (mappedSteps.empty()) {
mappedSteps = times; mappedSteps = times;
} }
@ -94,7 +91,6 @@ void PathComponent::Begin() {
double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin; double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin;
double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax; double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax;
double step = rangeStep; double step = rangeStep;
// 若步长无效,则回退为均匀分布
if (step <= 0.0) { if (step <= 0.0) {
step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0; step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0;
} }

View File

@ -70,15 +70,10 @@ int main(int argc, char* argv[]) {
MainFrame mainWindow; MainFrame mainWindow;
splash.showMessage(("正在创建主窗口..."), Qt::AlignHCenter | Qt::AlignBottom, Qt:: white); splash.showMessage(("正在创建主窗口..."), Qt::AlignHCenter | Qt::AlignBottom, Qt:: white);
// 先显示窗口,再在事件循环启动后最大化,避免首次显示时原生窗口放置未就绪导致尺寸异常 mainWindow.show();
mainWindow.showMaximized(); QTimer::singleShot(20, &mainWindow, &MainFrame::showMaximized);
// QTimer::singleShot(0, &mainWindow, &MainFrame::showMaximized);
splash.finish(&mainWindow); splash.finish(&mainWindow);
int ret = app.exec(); int ret = app.exec();
// app.Uninit();
Sleep(200);
return ret; return ret;
} }

View File

@ -1 +0,0 @@
IDI_ICON ICON DISCARDABLE ".\\res\\sys_icon.ico"

36
src/res/dyt.rc.in Normal file
View File

@ -0,0 +1,36 @@
IDI_ICON ICON DISCARDABLE "@CMAKE_CURRENT_SOURCE_DIR@/res/sys_icon.ico"
#include <winver.h>
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

View File

@ -54,7 +54,6 @@ void FrameTitleBar::SetMainWidget(QWidget* widget) {
} }
} }
void FrameTitleBar::OnMaximized(bool maximized) { void FrameTitleBar::OnMaximized(bool maximized) {
// 根据配置位决定是否显示最大/还原按钮,并切换图标
const bool hasMaxButton = (ftbButton_ & FTB_MAX) != 0; const bool hasMaxButton = (ftbButton_ & FTB_MAX) != 0;
ui->sys_max->setVisible(hasMaxButton); ui->sys_max->setVisible(hasMaxButton);
if (!hasMaxButton) { if (!hasMaxButton) {

View File

@ -41,7 +41,6 @@ void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) {
titleBar_ = titleBar; titleBar_ = titleBar;
if (nullptr != titleBar_) { if (nullptr != titleBar_) {
// 跟踪标题栏显示/隐藏,以便在显示时注册为可移动区域
titleBar_->installEventFilter(this); titleBar_->installEventFilter(this);
} }
} }

View File

@ -172,6 +172,16 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
mmi->ptMaxTrackSize.x = (rcMon.right - rcMon.left) + frameX * 2; mmi->ptMaxTrackSize.x = (rcMon.right - rcMon.left) + frameX * 2;
mmi->ptMaxTrackSize.y = (rcMon.bottom - rcMon.top) + frameY * 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<int>(std::round(minSize.width() * dpr));
const int minHpx = static_cast<int>(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)) { if (::IsZoomed(msg->hwnd)) {

View File

@ -11,10 +11,10 @@ FramelessWindow::FramelessWindow(QWidget* parent)
| Qt::FramelessWindowHint | Qt::FramelessWindowHint
| Qt::WindowSystemMenuHint | Qt::WindowSystemMenuHint
| Qt::WindowMaximizeButtonHint | Qt::WindowMaximizeButtonHint
| Qt::WindowMinimizeButtonHint); | Qt::WindowMinimizeButtonHint
);
delegate_ = FramelessDelegate::Create(this); delegate_ = FramelessDelegate::Create(this);
} }
FramelessWindow::~FramelessWindow() { FramelessWindow::~FramelessWindow() {
@ -23,7 +23,6 @@ FramelessWindow::~FramelessWindow() {
void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) { void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) {
titleBar->SetMainWidget(this); titleBar->SetMainWidget(this);
if (delegate_) { if (delegate_) {
// 通知委托当前标题栏,以便把它作为可拖动区域处理。
delegate_->SetTitleBar(titleBar); delegate_->SetTitleBar(titleBar);
} }
} }
@ -33,7 +32,6 @@ bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qi
#else #else
bool FramelessWindow::nativeEvent(const QByteArray & eventType, void* message, long* result) { bool FramelessWindow::nativeEvent(const QByteArray & eventType, void* message, long* result) {
#endif #endif
// 先让无边框委托处理原生事件(如 WM_NCHITTEST 以支持边缘拖动缩放)。
if (delegate_ && delegate_->nativeEvent(eventType, message, result)) { if (delegate_ && delegate_->nativeEvent(eventType, message, result)) {
return true; return true;
} }

View File

@ -36,6 +36,8 @@ MainFrame::MainFrame(QWidget *parent) :
ui(new Ui::MainFrame) ui(new Ui::MainFrame)
{ {
ui->setupUi(this); ui->setupUi(this);
setMinimumSize(800, 600);
assert(nullptr == s_instance); assert(nullptr == s_instance);
s_instance = this; s_instance = this;
@ -102,13 +104,6 @@ void MainFrame::InitUI() {
FileManagerMenu* fileMenu = new FileManagerMenu(this); FileManagerMenu* fileMenu = new FileManagerMenu(this);
AddMenuWidget("file_manager", tr("file manager"), fileMenu); 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); SimuRunMenu* simuRunMenu = new SimuRunMenu(this);
AddMenuWidget("simu_manager", tr("simu manager"), simuRunMenu); AddMenuWidget("simu_manager", tr("simu manager"), simuRunMenu);
@ -123,11 +118,6 @@ void MainFrame::InitUI() {
simuRunMenu->SetMainWindow(mainWindow); 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) { if (ui->menuWidget->count() > 0) {
ui->menuWidget->setCurrentIndex(0); ui->menuWidget->setCurrentIndex(0);
menuWidget_.isEmpty() ? assert(false) : menuWidget_.key(0)->setChecked(true); menuWidget_.isEmpty() ? assert(false) : menuWidget_.key(0)->setChecked(true);

View File

@ -38,11 +38,12 @@ MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent) : QMainWindow(parent)
, ui(new Ui::MainWindow) { , ui(new Ui::MainWindow) {
ui->setupUi(this); ui->setupUi(this);
setMinimumSize(800, 600);
LOG_INFO("MainWindow::MainWindow - Constructor called, about to call InitUI"); LOG_INFO("MainWindow::MainWindow - Constructor called, about to call InitUI");
InitUI(); InitUI();
LOG_INFO("MainWindow::MainWindow - Constructor completed"); LOG_INFO("MainWindow::MainWindow - Constructor completed");
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
UninitUI(); UninitUI();
@ -70,7 +71,6 @@ void MainWindow::InitUI() {
mapDockWidget_.insert("ModelBrowser", model); mapDockWidget_.insert("ModelBrowser", model);
addDockWidget(Qt::LeftDockWidgetArea, model); addDockWidget(Qt::LeftDockWidgetArea, model);
// 创建预制模型面板
DockWidget* presetModel = new DockWidget(tr("preset models"), 0); DockWidget* presetModel = new DockWidget(tr("preset models"), 0);
presetModel->SetDockWidgetTitleBar(new DockTitleBar(presetModel)); presetModel->SetDockWidgetTitleBar(new DockTitleBar(presetModel));
presetModel->setObjectName("Dock.PresetModelPanel"); presetModel->setObjectName("Dock.PresetModelPanel");
@ -82,11 +82,8 @@ void MainWindow::InitUI() {
DockWidget* attribte = new DockWidget(tr("attribte"), 0); DockWidget* attribte = new DockWidget(tr("attribte"), 0);
attribte->SetDockWidgetTitleBar(new DockTitleBar(attribte)); attribte->SetDockWidgetTitleBar(new DockTitleBar(attribte));
attribte->setObjectName("Dock.PropertyBrowser"); attribte->setObjectName("Dock.PropertyBrowser");
//addDockWidget(pSettingUI->GetArea("PropertyBrowser"), attribte);
propertyBrowser_ = new PropertyBrowser(0); propertyBrowser_ = new PropertyBrowser(0);
propertyBrowser_->AttachDock(attribte); propertyBrowser_->AttachDock(attribte);
// Ensure property panel has a reasonable minimum width; no maximum limit
attribte->setMinimumWidth(240);
mapDockWidget_.insert("PropertyBrowser", attribte); mapDockWidget_.insert("PropertyBrowser", attribte);
addDockWidget(Qt::RightDockWidgetArea, attribte); addDockWidget(Qt::RightDockWidgetArea, attribte);
@ -106,23 +103,18 @@ void MainWindow::InitUI() {
connect(modelBrowser_, &ModelBrowser::FileEntryChange, propertyBrowser_, &PropertyBrowser::OnFileEntryChange); connect(modelBrowser_, &ModelBrowser::FileEntryChange, propertyBrowser_, &PropertyBrowser::OnFileEntryChange);
connect(modelBrowser_, &ModelBrowser::GroupChange, propertyBrowser_, &PropertyBrowser::OnGroupChange); connect(modelBrowser_, &ModelBrowser::GroupChange, propertyBrowser_, &PropertyBrowser::OnGroupChange);
qtOsgViewWidget_ = new OsgWidget; qtOsgViewWidget_ = new OsgWidget(0);
qtOsgViewWidget_->Initialize(); qtOsgViewWidget_->Initialize();
DockWidget* viewDock = new DockWidget(tr("Main View"), 0); DockWidget* mainView = new DockWidget(tr("Main View"), 0);
viewDock->SetDockWidgetTitleBar(new DockTitleBar(viewDock)); mainView->SetDockWidgetTitleBar(new DockTitleBar(mainView));
viewDock->setObjectName("Dock.MainView"); mainView->setObjectName("Dock.MainView");
viewDock->setWidget(qtOsgViewWidget_); qtOsgViewWidget_->AttachDock(mainView);
// Ensure main view has a reasonable minimum size to avoid being squeezed mapDockWidget_.insert("MainView", mainView);
// Use smaller minimum size to support smaller displays addDockWidget(Qt::RightDockWidgetArea, mainView);
qtOsgViewWidget_->setMinimumSize(640, 480);
viewDock->setMinimumSize(640, 480);
addDockWidget(Qt::LeftDockWidgetArea, viewDock);
mapDockWidget_.insert("MainView", viewDock);
splitDockWidget(model, viewDock, Qt::Horizontal); splitDockWidget(model, mainView, Qt::Horizontal);
// 将预制模型面板与模型浏览器标签化
tabifyDockWidget(model, presetModel); tabifyDockWidget(model, presetModel);
dataPanelManager_ = new DataPanelManager(this, this); dataPanelManager_ = new DataPanelManager(this, this);

View File

@ -48,6 +48,7 @@ private:
class PropertyBrowser* propertyBrowser_{ nullptr }; class PropertyBrowser* propertyBrowser_{ nullptr };
class QWebEngineView* webEngineView_{ nullptr }; class QWebEngineView* webEngineView_{ nullptr };
class OsgWidget* qtOsgViewWidget_{ nullptr }; class OsgWidget* qtOsgViewWidget_{ nullptr };
//QWidget* qtOsgViewWidget_{ nullptr };
class SignalIndicatorLampUI* signalIndicatorLampUI_{ nullptr }; class SignalIndicatorLampUI* signalIndicatorLampUI_{ nullptr };
class CodeEdtUI* matlabFileDlg_{ nullptr }; class CodeEdtUI* matlabFileDlg_{ nullptr };

View File

@ -118,7 +118,6 @@ void PlayManagerMenu::OnWorkspaceChange(WorkSpace* workSpace) {
} }
workSpace_ = workSpace; workSpace_ = workSpace;
connect(workSpace, &WorkSpace::TimestepChanged, this, &PlayManagerMenu::OnTimestepChanged); connect(workSpace, &WorkSpace::TimestepChanged, this, &PlayManagerMenu::OnTimestepChanged);
// 若当前 workspace 已有 timestep则立即刷新一次 UI
if (auto* timestep = workSpace->GetTimestep()) { if (auto* timestep = workSpace->GetTimestep()) {
OnTimestepChanged(timestep); OnTimestepChanged(timestep);
} }
@ -140,12 +139,10 @@ void PlayManagerMenu::OnTimestepChanged(Timestep* timestep) {
ui->horizontalSlider->setValue(int(dt)); ui->horizontalSlider->setValue(int(dt));
} }
); );
// 监听倍速改变SpeedChanged更新显示为 x倍速
connect(timestep, &Timestep::StepChanged, [this](double speed) { connect(timestep, &Timestep::StepChanged, [this](double speed) {
ui->lbUp->setText(QString("x%1").arg(speed)); ui->lbUp->setText(QString("x%1").arg(speed));
} }
); );
// 当时间范围更新(例如用户在属性面板设置了起止时间)时,刷新显示与滑条范围
connect(timestep, &Timestep::RangeChanged, [this](double minTime, double maxTime, double step, double speed) { connect(timestep, &Timestep::RangeChanged, [this](double minTime, double maxTime, double step, double speed) {
minTime_ = minTime; minTime_ = minTime;
maxTime_ = maxTime; maxTime_ = maxTime;

View File

@ -3,8 +3,8 @@
#include <QBoxLayout> #include <QBoxLayout>
#include <QDebug> #include <QDebug>
#include "DockTitleBar.h" #include "ui/DockTitleBar.h"
#include "DockWidget.h" #include "ui/DockWidget.h"
#include "ModelBrowser/ModelTreeWidget.h" #include "ModelBrowser/ModelTreeWidget.h"
#include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpaceManager.h"

View File

@ -48,7 +48,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
WorkSpace* workspace = value.value<WorkSpace*>(); WorkSpace* workspace = value.value<WorkSpace*>();
if (nullptr == workspace) { if (nullptr == workspace) {
LOG_WARN("workspace is nullptr"); LOG_WARN("workspace is nullptr");
// 如果没有属性对象,清空属性面板
browser_->clear(); browser_->clear();
propertyToId_.clear(); propertyToId_.clear();
idToProperty_.clear(); idToProperty_.clear();
@ -57,7 +56,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
return; return;
} }
// 点击根项目需要清空属性面板,不展示工作区属性
browser_->clear(); browser_->clear();
propertyToId_.clear(); propertyToId_.clear();
idToProperty_.clear(); idToProperty_.clear();
@ -71,7 +69,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
workSpaceManager_->setValue(property, worksapceAttribute); workSpaceManager_->setValue(property, worksapceAttribute);
addProperty(property, tr("WorkSpace")); addProperty(property, tr("WorkSpace"));
// 保持对运行时工作区变更的监听(树刷新所需),但属性面板保持清空
if (currentWorkspace_) { if (currentWorkspace_) {
QObject::disconnect(currentWorkspace_, nullptr, this, nullptr); QObject::disconnect(currentWorkspace_, nullptr, this, nullptr);
} }
@ -79,7 +76,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged, QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged,
this, &PropertyBrowser::OnWorkspaceFilesChanged); this, &PropertyBrowser::OnWorkspaceFilesChanged);
// 属性面板清空,文件项属性由 FileEntry 点击时单独处理
} }
void PropertyBrowser::OnEntityChange(const QVariant& value) { void PropertyBrowser::OnEntityChange(const QVariant& value) {
@ -87,7 +83,6 @@ void PropertyBrowser::OnEntityChange(const QVariant& value) {
Entity* entity = value.value<Entity*>(); Entity* entity = value.value<Entity*>();
if (nullptr == entity) { if (nullptr == entity) {
LOG_WARN("engity is nullptr"); LOG_WARN("engity is nullptr");
// 如果没有属性对象,清空属性面板
browser_->clear(); browser_->clear();
propertyToId_.clear(); propertyToId_.clear();
idToProperty_.clear(); idToProperty_.clear();
@ -141,7 +136,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
FileEntry* entry = value.value<FileEntry*>(); FileEntry* entry = value.value<FileEntry*>();
if (!entry) { if (!entry) {
LOG_WARN("file entry is nullptr"); LOG_WARN("file entry is nullptr");
// 如果没有属性对象,清空属性面板
inFileEntryView_ = false; inFileEntryView_ = false;
browser_->clear(); browser_->clear();
propertyToId_.clear(); propertyToId_.clear();
@ -173,7 +167,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
//if (!curve) //if (!curve)
{ {
LOG_WARN("file entry not a curve: %s", entry->GetFileName().toStdString().c_str()); LOG_WARN("file entry not a curve: %s", entry->GetFileName().toStdString().c_str());
// 基础信息组
const QString idBasic = QString("FileEntry:%1").arg(entry->GetFileName()); const QString idBasic = QString("FileEntry:%1").arg(entry->GetFileName());
const QString titleBasic = QString("File Entry - %1").arg(entry->GetName()); const QString titleBasic = QString("File Entry - %1").arg(entry->GetName());
QtProperty* groupBasic = groupManager_->addProperty(tr("Basic")); QtProperty* groupBasic = groupManager_->addProperty(tr("Basic"));
@ -205,7 +198,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
addProperty(groupBasic, idBasic); addProperty(groupBasic, idBasic);
// 类型专属属性显示
switch (entry->GetType()) switch (entry->GetType())
{ {
case FileEntryType::Curve: 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 titleChart = QString("Surface Chart - %1").arg(entry->GetName());
const QString titleItems = QString("Surfaces - %1").arg(entry->GetName()); const QString titleItems = QString("Surfaces - %1").arg(entry->GetName());
// Chart 属性
QtProperty* chartGroup = groupManager_->addProperty(tr("Chart")); QtProperty* chartGroup = groupManager_->addProperty(tr("Chart"));
const auto& chart = surf->GetChartProperties(); const auto& chart = surf->GetChartProperties();
QtProperty* xCountProp = intManager_->addProperty(tr("xCount")); QtProperty* xCountProp = intManager_->addProperty(tr("xCount"));
@ -600,7 +591,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
addProperty(chartGroup, idChart); addProperty(chartGroup, idChart);
// Surface 列表
QtProperty* itemsGroup = groupManager_->addProperty(tr("SurfacesProp")); QtProperty* itemsGroup = groupManager_->addProperty(tr("SurfacesProp"));
const auto& items = surf->GetSurfaceProperties(); const auto& items = surf->GetSurfaceProperties();
for (int i = 0; i < items.size(); ++i) for (int i = 0; i < items.size(); ++i)
@ -626,7 +616,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
QtProperty* col = colorManager_->addProperty(tr("color")); QtProperty* col = colorManager_->addProperty(tr("color"));
colorManager_->setValue(col, s.color); colorManager_->setValue(col, s.color);
itemGroup->addSubProperty(col); itemGroup->addSubProperty(col);
// 写回 Surface 条目颜色
colorSetters_[col] = [surf, entry, i](const QColor& c) colorSetters_[col] = [surf, entry, i](const QColor& c)
{ {
auto props = surf->GetSurfaceProperties(); auto props = surf->GetSurfaceProperties();
@ -768,7 +757,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
// QtProperty* col = colorManager_->addProperty(tr("color")); // QtProperty* col = colorManager_->addProperty(tr("color"));
// colorManager_->setValue(col, t.color); // colorManager_->setValue(col, t.color);
// itemGroup->addSubProperty(col); // itemGroup->addSubProperty(col);
// // 写回 Table 条目颜色
// colorSetters_[col] = [tbl, entry, i](const QColor& c){ // colorSetters_[col] = [tbl, entry, i](const QColor& c){
// auto props = tbl->GetTableProperties(); // auto props = tbl->GetTableProperties();
// if (i >= 0 && i < props.size()) { // 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()); // if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType());
// } // }
// }; // };
// // datas 展示为拼接字符串
// QStringList values; // QStringList values;
// for (const auto& v : t.datas) values << QString::number(v); // for (const auto& v : t.datas) values << QString::number(v);
// QtProperty* ds = stringManager_->addProperty(tr("datas")); // 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 titleColor = QString("Light Colors - %1").arg(entry->GetName());
const QString titleRows = QString("Light Rows - %1").arg(entry->GetName()); const QString titleRows = QString("Light Rows - %1").arg(entry->GetName());
// 颜色与时间
QtProperty* colorGroup = groupManager_->addProperty(tr("Chart")); QtProperty* colorGroup = groupManager_->addProperty(tr("Chart"));
const auto& colorProps = lt->GetColorProperties(); const auto& colorProps = lt->GetColorProperties();
QtProperty* oc = colorManager_->addProperty(tr("openColor")); QtProperty* oc = colorManager_->addProperty(tr("openColor"));
@ -822,7 +808,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
}; };
addProperty(colorGroup, idColor); addProperty(colorGroup, idColor);
// 写回处理:颜色变化更新到 FileEntryLight 并通知 Workspace
colorSetters_[oc] = [lt, entry](const QColor& c) colorSetters_[oc] = [lt, entry](const QColor& c)
{ {
auto props = lt->GetColorProperties(); auto props = lt->GetColorProperties();
@ -838,7 +823,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType()); if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType());
}; };
// 行数据
QtProperty* rowsGroup = groupManager_->addProperty(tr("Light Rows")); QtProperty* rowsGroup = groupManager_->addProperty(tr("Light Rows"));
const auto& rows = lt->GetLightProperties(); const auto& rows = lt->GetLightProperties();
for (int i = 0; i < rows.size(); ++i) for (int i = 0; i < rows.size(); ++i)
@ -987,7 +971,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
QtProperty* col = colorManager_->addProperty(tr("color")); QtProperty* col = colorManager_->addProperty(tr("color"));
colorManager_->setValue(col, ln.color); colorManager_->setValue(col, ln.color);
line->addSubProperty(col); line->addSubProperty(col);
// 写回 Polar 线颜色
colorSetters_[col] = [pl, entry, i](const QColor& c) colorSetters_[col] = [pl, entry, i](const QColor& c)
{ {
auto props = pl->GetLineProperties(); auto props = pl->GetLineProperties();
@ -1165,7 +1148,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
break; break;
} }
// 聚焦基础信息组
if (groupBasic) { if (groupBasic) {
QtBrowserItem* item = browser_->topLevelItem(groupBasic); QtBrowserItem* item = browser_->topLevelItem(groupBasic);
if (item) { if (item) {
@ -1270,7 +1252,6 @@ void PropertyBrowser::InitPropertyManager() {
browser_->setFactoryForManager(curveEntryManager_->subDoubleProperyManager(), doubleSpinBoxFactory); browser_->setFactoryForManager(curveEntryManager_->subDoubleProperyManager(), doubleSpinBoxFactory);
browser_->setFactoryForManager(curveEntryManager_->subColorProperyManager(), colorFactory); browser_->setFactoryForManager(curveEntryManager_->subColorProperyManager(), colorFactory);
// 颜色属性变更信号:触发对应写回处理器
connect(colorManager_, &QtColorPropertyManager::valueChanged, this, connect(colorManager_, &QtColorPropertyManager::valueChanged, this,
[this](QtProperty* prop, const QColor& color){ [this](QtProperty* prop, const QColor& color){
if (colorSetters_.contains(prop)) { if (colorSetters_.contains(prop)) {

View File

@ -61,9 +61,6 @@ const QString QWorkspaceAttribute::GetDescription() const {
return workspace_->GetDescribe(); return workspace_->GetDescribe();
} }
// 已移除:时间步长文件路径设置/获取(不再从文件读取)
void QWorkspaceAttribute::SetSimulationStart(double start) { void QWorkspaceAttribute::SetSimulationStart(double start) {
if (!workspace_) return; if (!workspace_) return;
Timestep* t = workspace_->GetTimestep(); Timestep* t = workspace_->GetTimestep();

View File

@ -62,8 +62,6 @@ public:
void SetDescription(const QString& desc); void SetDescription(const QString& desc);
const QString GetDescription() const; const QString GetDescription() const;
// 已移除:时间步长文件路径(不再从文件读取)
// Simulation time (manual range) for playback // Simulation time (manual range) for playback
void SetSimulationStart(double start); void SetSimulationStart(double start);
double GetSimulationStart() const; double GetSimulationStart() const;

View File

@ -53,7 +53,6 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent)
} }
bool ok = false; bool ok = false;
// 解析各字段
const double time = parts[0].toDouble(&ok); if (!ok) { LOG_WARN("invalid time: {}", parts[0].toStdString()); return {}; } 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 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 {}; } 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 {}; } const double roll = parts[6].toDouble(&ok); if (!ok) { LOG_WARN("invalid roll: {}", parts[6].toStdString()); return {}; }
Transform transform; Transform transform;
// 位置映射:经度->x纬度->y高度->z
transform.GetLocation().set(longitude, latitude, altitude); transform.GetLocation().set(longitude, latitude, altitude);
// 旋转向量采用代码库约定顺序Pitch, Roll, Heading与 OsgUtils::HPRToQuat/QuatToHPR 保持一致
transform.GetRotation().set(pitch, roll, heading); transform.GetRotation().set(pitch, roll, heading);
// 当前 PathComponent 使用 WorkSpace 的 Timestep 作为时间轴,这里暂不保存 time 字段
// 现在记录时间以支持按路径文件驱动回放
times.push_back(time); times.push_back(time);
transforms.push_back(transform); transforms.push_back(transform);

View File

@ -21,7 +21,6 @@
#include "OsgViewer.h" #include "OsgViewer.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "scene/OEScene.h" #include "scene/OEScene.h"
#include "ui/MainFrame.h"
#include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpaceManager.h"
#include "workspace/WorkSpace.h" #include "workspace/WorkSpace.h"
#include "scutcheon/osgScutcheon.h" #include "scutcheon/osgScutcheon.h"
@ -33,6 +32,10 @@
#include "entities/Entity.h" #include "entities/Entity.h"
#include "entities/Component.h" #include "entities/Component.h"
#include "ui/DockTitleBar.h"
#include "ui/DockWidget.h"
#include "ui/MainFrame.h"
static void ConfigureView( osgViewer::View* view ) { static void ConfigureView( osgViewer::View* view ) {
view->addEventHandler(new osgViewer::StatsHandler()); view->addEventHandler(new osgViewer::StatsHandler());
view->addEventHandler(new osgViewer::WindowSizeHandler()); view->addEventHandler(new osgViewer::WindowSizeHandler());
@ -55,14 +58,13 @@ OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags f)
setThreadingModel(osgViewer::ViewerBase::SingleThreaded); setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
setMouseTracking(true); setMouseTracking(true);
setKeyEventSetsDone(0); setKeyEventSetsDone(0);
// 启用拖拽接收
setAcceptDrops(true); setAcceptDrops(true);
connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) ); connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) );
timer_.start( 10 ); timer_.start( 10 );
setMinimumSize(100, 100); //setMinimumSize(800, 100);
LOG_INFO("OsgWidget::OsgWidget"); 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, osgQt::GraphicsWindowQt* OsgWidget::createGraphicsWindow(int x, int y, int w, int h, const std::string& name,
bool windowDecoration) { bool windowDecoration) {
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
@ -199,7 +214,6 @@ void OsgWidget::dragEnterEvent(QDragEnterEvent* event) {
} }
void OsgWidget::dragMoveEvent(QDragMoveEvent* event) { void OsgWidget::dragMoveEvent(QDragMoveEvent* event) {
// 检查是否是预制模型拖拽
if (event->mimeData()->hasFormat("application/x-preset-model")) { if (event->mimeData()->hasFormat("application/x-preset-model")) {
event->acceptProposedAction(); event->acceptProposedAction();
} else { } else {
@ -249,11 +263,9 @@ void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& mo
} }
osg::Viewport* vp = view_->getCamera()->getViewport(); osg::Viewport* vp = view_->getCamera()->getViewport();
// 将屏幕坐标转换为世界坐标
double longitude, latitude, height; double longitude, latitude, height;
if (!ScreenToWorldCoordinate(static_cast<int>(position.x()), static_cast<int>(vp->height() - position.y()), longitude, latitude, height)) { if (!ScreenToWorldCoordinate(static_cast<int>(position.x()), static_cast<int>(vp->height() - position.y()), longitude, latitude, height)) {
LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates"); LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates");
// 使用默认位置
longitude = 0.0; longitude = 0.0;
latitude = 0.0; latitude = 0.0;
height = 0.0; height = 0.0;

View File

@ -11,12 +11,14 @@ class OsgWidget : public QWidget, public osgViewer::CompositeViewer {
public: public:
OsgWidget(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); OsgWidget(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr);
~OsgWidget() override; ~OsgWidget() override;
QPaintEngine* paintEngine() const override { return nullptr; } QPaintEngine* paintEngine() const override { return nullptr; }
void Initialize(void); void Initialize(void);
void Uninitialize(void); void Uninitialize(void);
void LoadDefaultScene(void); void LoadDefaultScene(void);
void AttachDock(class DockWidget* dockWidget);
signals: signals:
void signalScaleInfo(const QString&); void signalScaleInfo(const QString&);
@ -28,18 +30,11 @@ protected:
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
void paintEvent( QPaintEvent* /*event*/ ) override; void paintEvent( QPaintEvent* /*event*/ ) override;
// 拖拽事件处理
void dragEnterEvent(QDragEnterEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override;
void dropEvent(QDropEvent* event) override; void dropEvent(QDropEvent* event) override;
public slots: public slots:
/**
* @brief
* @param modelType
* @param modelName
* @param position
*/
void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF()); void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude); bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude);

View File

@ -25,7 +25,6 @@ void Timestep::SetManualRange(double start, double end) {
manualStart_ = start; manualStart_ = start;
manualEnd_ = end; manualEnd_ = end;
maxTime_ = end; maxTime_ = end;
// 通知 UI 更新范围与步进
double minTime = 0.0, maxTime = 0.0, step = 1.0; double minTime = 0.0, maxTime = 0.0, step = 1.0;
GetRange(minTime, maxTime, step); GetRange(minTime, maxTime, step);
emit RangeChanged(minTime, maxTime, step, currentSpeed_); emit RangeChanged(minTime, maxTime, step, currentSpeed_);
@ -126,7 +125,6 @@ void Timestep::Stop() {
} }
void Timestep::Up() { void Timestep::Up() {
// 提升到下一个倍率(封顶)
if (speedIndex_ < int(speedLevels_.size()) - 1) { if (speedIndex_ < int(speedLevels_.size()) - 1) {
++speedIndex_; ++speedIndex_;
} }
@ -168,7 +166,6 @@ void Timestep::SetSpeed(double speed) {
} }
void Timestep::SetStep(double step) { void Timestep::SetStep(double step) {
// 更新时间轴步进间隔,并通知 UI 范围与步进发生变化
stepInterval_ = step; stepInterval_ = step;
double minTime = 0.0, maxTime = 0.0, s = 0.0; double minTime = 0.0, maxTime = 0.0, s = 0.0;
GetRange(minTime, maxTime, s); GetRange(minTime, maxTime, s);

View File

@ -367,13 +367,11 @@ void WorkSpace::ExecuteCommands(CommandWhen when) {
cmdMgr_->Execute(this, when); cmdMgr_->Execute(this, when);
} }
// 统一属性更新通知:不改变数量,仅提升序号并广播 FilesChanged
void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) { void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) {
++filesSeq_; ++filesSeq_;
emit FilesChanged(type, fileEntry); emit FilesChanged(type, fileEntry);
} }
// 删除指定指针的文件条目(不删除物理文件,仅移出工作空间管理)
bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) { bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) {
if (!entry) { if (!entry) {
LOG_WARN("RemoveFileEntry: entry is nullptr"); LOG_WARN("RemoveFileEntry: entry is nullptr");
@ -397,7 +395,6 @@ bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) {
return true; return true;
} }
// 按索引删除文件条目
bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) { bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) {
auto it = files_.find(type); auto it = files_.find(type);
if (it == files_.end()) { if (it == files_.end()) {
@ -416,7 +413,6 @@ bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) {
return true; return true;
} }
// 按文件名删除文件条目(匹配工作空间内记录的文件名)
bool WorkSpace::RemoveFileEntryByName(FileEntryType type, const QString& fileName) { bool WorkSpace::RemoveFileEntryByName(FileEntryType type, const QString& fileName) {
auto it = files_.find(type); auto it = files_.find(type);
if (it == files_.end()) { if (it == files_.end()) {

View File

@ -60,14 +60,13 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) {
LOG_WARN("element is nullptr"); LOG_WARN("element is nullptr");
return false; return false;
} }
// 确保存在 Timestep 实例
workSpace_->EnsureTimestep(); workSpace_->EnsureTimestep();
Timestep* t = workSpace_->GetTimestep(); Timestep* t = workSpace_->GetTimestep();
if (!t) { if (!t) {
return false; return false;
} }
// 解析属性manual(0/1)、start、end、step
int manualFlag = 0; int manualFlag = 0;
element->QueryIntAttribute("manual", &manualFlag); element->QueryIntAttribute("manual", &manualFlag);
double start = 0.0; double start = 0.0;
@ -85,7 +84,6 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) {
t->SetStep(step); t->SetStep(step);
} }
// 若标记为手动或具有完整的 start/end则设置手动范围否则按数据最大时间设置边界
if (manualFlag != 0 || (hasStart && hasEnd)) { if (manualFlag != 0 || (hasStart && hasEnd)) {
t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0); t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0);
} else if (hasEnd) { } else if (hasEnd) {
@ -122,7 +120,6 @@ bool WorkSpaceXMLParse::ParseCommond(const tinyxml2::XMLElement* element) {
return false; return false;
} }
// Set the command file path using the filename stored in XML
workSpace_->commondPath_ = path; workSpace_->commondPath_ = path;
return true; return true;
} }
@ -133,19 +130,15 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
return false; return false;
} }
// 首先处理新的Chart元素结构
const tinyxml2::XMLElement* chartElement = element->FirstChildElement("Chart"); const tinyxml2::XMLElement* chartElement = element->FirstChildElement("Chart");
while (nullptr != chartElement) { while (nullptr != chartElement) {
// 创建FileEntryCurve对象来解析Chart数据
auto curveEntry = CreateEmptyFileEntryCurve(); auto curveEntry = CreateEmptyFileEntryCurve();
if (curveEntry && curveEntry->ParseFiles(chartElement)) { if (curveEntry && curveEntry->ParseFiles(chartElement)) {
// 添加解析后的FileEntry到workspace
workSpace_->SetFileEntry(curveEntry, false); workSpace_->SetFileEntry(curveEntry, false);
} }
chartElement = chartElement->NextSiblingElement("Chart"); chartElement = chartElement->NextSiblingElement("Chart");
} }
// 保持向后兼容处理旧的type元素结构
const tinyxml2::XMLElement* typeElement = element->FirstChildElement("type"); const tinyxml2::XMLElement* typeElement = element->FirstChildElement("type");
while (nullptr != typeElement) { while (nullptr != typeElement) {
const char* name = typeElement->Attribute("name"); const char* name = typeElement->Attribute("name");
@ -155,17 +148,14 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
if (nullptr != name && count > 0) { if (nullptr != name && count > 0) {
QString typeName = QString::fromLocal8Bit(name); QString typeName = QString::fromLocal8Bit(name);
// Create FileEntry objects and call their ParseFiles method
FileEntryType enumType; FileEntryType enumType;
if (FileEntryTypeFromString(name, enumType)) { if (FileEntryTypeFromString(name, enumType)) {
const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart"); const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart");
while (nullptr != chartElement) { while (nullptr != chartElement) {
auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing auto fileEntry = CreateEmptyFileEntry(enumType);
if (fileEntry) { if (fileEntry) {
// Call the FileEntry's ParseFiles method to parse detailed data
if (fileEntry->ParseFiles(chartElement)) { if (fileEntry->ParseFiles(chartElement)) {
// Add the parsed FileEntry to workspace
workSpace_->SetFileEntry(fileEntry, false); workSpace_->SetFileEntry(fileEntry, false);
} }
} }
@ -173,19 +163,6 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
chartElement = chartElement->NextSiblingElement(); 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); workSpace_->SetFileEntryCount(enumType, count);
} }
} }

View File

@ -66,15 +66,12 @@ bool WorkSpaceXMLWrite::SaveScene(tinyxml2::XMLElement* scene) {
return true; return true;
} }
// Removed: SaveTimeStep — timestep is no longer file-based
// 新增:保存 Timestep 的手动范围与步长倍率
bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) { bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) {
if (nullptr == workSpace_) { if (nullptr == workSpace_) {
return false; return false;
} }
auto* t = workSpace_->GetTimestep(); auto* t = workSpace_->GetTimestep();
if (!t) { if (!t) {
// 若尚未创建,确保存在一个默认实例,以保证文件的一致性
workSpace_->EnsureTimestep(); workSpace_->EnsureTimestep();
t = workSpace_->GetTimestep(); t = workSpace_->GetTimestep();
} }
@ -114,7 +111,6 @@ bool WorkSpaceXMLWrite::SaveCommond(tinyxml2::XMLElement* scene) {
const QString commondPath = workSpace_->GetCommondFilePath(); const QString commondPath = workSpace_->GetCommondFilePath();
if (!commondPath.isEmpty()) { if (!commondPath.isEmpty()) {
tinyxml2::XMLElement* commond = scene->InsertNewChildElement("commond"); tinyxml2::XMLElement* commond = scene->InsertNewChildElement("commond");
// Extract just the filename from the full path for storage
QFileInfo fileInfo(commondPath); QFileInfo fileInfo(commondPath);
commond->SetAttribute("path", fileInfo.fileName().toStdString().c_str()); 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) 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"); tinyxml2::XMLElement* charts = doc->NewElement("charts");
scene->LinkEndChild(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) { bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
// Persist multi-file entries per type as counts
tinyxml2::XMLElement* files = doc->NewElement("files"); tinyxml2::XMLElement* files = doc->NewElement("files");
scene->LinkEndChild(files); scene->LinkEndChild(files);
@ -149,7 +143,6 @@ bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocu
typeElem->SetAttribute("count", static_cast<int>(vec.size())); typeElem->SetAttribute("count", static_cast<int>(vec.size()));
files->LinkEndChild(typeElem); files->LinkEndChild(typeElem);
// Call SaveFiles method for each FileEntry to save detailed data
for (const auto& fileEntry : vec) { for (const auto& fileEntry : vec) {
if (fileEntry) { if (fileEntry) {
fileEntry->SaveFiles(typeElem, doc); fileEntry->SaveFiles(typeElem, doc);