modify save and laod to display

This commit is contained in:
brige 2025-10-27 08:35:04 +08:00
parent 87091abf12
commit 52769cb830
16 changed files with 590 additions and 602 deletions

View File

@ -19,7 +19,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="33"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="36"/>
<source>Select curve data file...</source> <source>Select curve data file...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -90,32 +90,32 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="161"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="207"/>
<source>X Min:</source> <source>X Min:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="181"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="267"/>
<source>X Max:</source> <source>X Max:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="201"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="221"/>
<source>Y Min:</source> <source>Y Min:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="221"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="214"/>
<source>Y Max:</source> <source>Y Max:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="241"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="187"/>
<source>X Tick Count:</source> <source>X Tick Count:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="342"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="362"/>
<source>Curve Name:</source> <source>Curve Name:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -125,122 +125,72 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="264"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="274"/>
<source>Y Tick Count:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="284"/>
<source>Curve Management</source> <source>Curve Management</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="272"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="292"/>
<source>Curves:</source> <source>Curves:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="292"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="318"/>
<source>Add Curve</source> <source>Add Curve</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="305"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="331"/>
<source>Remove</source> <source>Remove</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="333"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="356"/>
<source>Selected Curve Properties</source> <source>Selected Curve Properties</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="349"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="369"/>
<source>Enter curve name...</source> <source>Enter curve name...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="356"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="376"/>
<source>Curve Color:</source> <source>Curve Color:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="365"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="391"/>
<source>Select Color</source> <source>Select Color</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="384"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="404"/>
<source>background-color: rgb(255, 0, 0); border: 1px solid black;</source> <source>background-color: rgb(255, 0, 0); border: 1px solid black;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="409"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="429"/>
<source>Data Start:</source> <source>Data Start:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="429"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="449"/>
<source>Data Stop:</source> <source>Data Stop:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="455"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="490"/>
<source>Data Format Parameters</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="461"/>
<source>X Column:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="481"/>
<source>Y Column:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="501"/>
<source>Separator:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="509"/>
<source>Comma (,)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="514"/>
<source>Tab</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="519"/>
<source>Space</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="524"/>
<source>Semicolon (;)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="532"/>
<source>File has header row</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="545"/>
<source>Description (Optional)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="557"/>
<source>Enter file description...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="595"/>
<source>Add File</source> <source>Add File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="605"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.ui" line="500"/>
<source>Cancel</source> <source>Cancel</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -268,11 +218,8 @@
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="427"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="427"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="438"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="438"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="443"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="443"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="452"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="451"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="457"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="458"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="464"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="471"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="477"/>
<source>Validation Error</source> <source>Validation Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -367,69 +314,54 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="452"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="451"/>
<source>X column and Y column cannot be the same.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="457"/>
<source>Data column indices must be greater than 0.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="464"/>
<source>Time parameter cannot be negative.</source> <source>Time parameter cannot be negative.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="471"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="458"/>
<source>X axis tick count must be at least 2.</source> <source>X axis tick count must be at least 2.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="477"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="478"/>
<source>Description is too long. Please limit to 500 characters.</source> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="506"/>
<translation type="unfinished"></translation> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="531"/>
</message>
<message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="497"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="524"/>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="549"/>
<source>Error</source> <source>Error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="497"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="478"/>
<source>Failed to create file entry</source> <source>Failed to create file entry</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="524"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="506"/>
<source>Unable to get current workspace</source> <source>Unable to get current workspace</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="534"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="516"/>
<source>Curve file count has reached the limit (9 files)</source> <source>Curve file count has reached the limit (9 files)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="537"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="519"/>
<source>File already exists</source> <source>File already exists</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="540"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="522"/>
<source>File copy failed</source> <source>File copy failed</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="543"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="525"/>
<source>Invalid file</source> <source>Invalid file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="546"/> <location filename="../ui/WorkSpace/AddCurveFileDlg.cpp" line="528"/>
<source>Failed to add file</source> <source>Failed to add file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -14,7 +14,6 @@
CurvePanel::CurvePanel(int index, const QString& filePath, QWidget* parent) CurvePanel::CurvePanel(int index, const QString& filePath, QWidget* parent)
: DataPanel(index, FileEntryType::Curve, filePath, parent) : DataPanel(index, FileEntryType::Curve, filePath, parent)
, hasChartData_(false)
{ {
m_iXMin = 0; m_iXMin = 0;
m_iXMax = 0; m_iXMax = 0;
@ -24,15 +23,13 @@ CurvePanel::CurvePanel(int index, const QString& filePath, QWidget* parent)
LOG_INFO("Created CurvePanel {} for file: {}", index, filePath.toStdString()); LOG_INFO("Created CurvePanel {} for file: {}", index, filePath.toStdString());
} }
CurvePanel::CurvePanel(int index, std::shared_ptr<BaseChartData> chartData, QWidget* parent) CurvePanel::CurvePanel(int index, std::shared_ptr<FileEntryCurve> fileEntry, QWidget* parent)
: DataPanel(index, FileEntryType::Curve, chartData ? chartData->path : QString(), parent) : DataPanel(index, fileEntry, parent)
, chartData_(chartData)
, hasChartData_(chartData != nullptr)
{ {
if (chartData) { if (fileEntry) {
LOG_INFO("Created CurvePanel {} for chart: {}", index, chartData->name.toStdString()); LOG_INFO("Created CurvePanel {} for chart: {}", index, fileEntry->GetName().toStdString());
// Override the title with chart name // Override the title with chart name
title_ = QString("Curve Panel %1 - %2").arg(index).arg(chartData->name); title_ = QString("Curve Panel %1 - %2").arg(index).arg(fileEntry->GetName());
} else { } else {
LOG_WARN("Created CurvePanel {} with null chart data", index); LOG_WARN("Created CurvePanel {} with null chart data", index);
} }
@ -48,38 +45,20 @@ void CurvePanel::RefreshPanel()
// Implement curve-specific refresh logic here // Implement curve-specific refresh logic here
DataPanel::RefreshPanel(); DataPanel::RefreshPanel();
if (auto fileEntry = std::dynamic_pointer_cast<FileEntryCurve>(fileEntry_)) { if (auto fileEntry = fileEntry_->AsCurve()) {
OnDataPanelUpdated(fileEntry.get()); OnDataPanelUpdated(fileEntry);
} }
if (hasChartData_) { if (IsValid()) {
UpdateCurveDisplay(); UpdateCurveDisplay();
} }
LOG_INFO("Refreshed CurvePanel {}", GetIndex()); LOG_INFO("Refreshed CurvePanel {}", GetIndex());
} }
void CurvePanel::SetChartData(std::shared_ptr<BaseChartData> chartData)
{
chartData_ = chartData;
hasChartData_ = (chartData != nullptr);
if (chartData) {
// Update title
title_ = QString("Curve Panel %1 - %2").arg(GetIndex()).arg(chartData->name);
// Refresh the display
UpdateCurveDisplay();
LOG_INFO("Set chart data for CurvePanel {}: {}", GetIndex(), chartData->name.toStdString());
} else {
LOG_WARN("Set null chart data for CurvePanel {}", GetIndex());
}
}
void CurvePanel::UpdateCurveDisplay() void CurvePanel::UpdateCurveDisplay()
{ {
if (!hasChartData_ || !chartData_) { if (!IsValid()) {
return; return;
} }
@ -97,197 +76,203 @@ void CurvePanel::UpdateCurveDisplay()
QVBoxLayout* mainLayout = new QVBoxLayout(this); QVBoxLayout* mainLayout = new QVBoxLayout(this);
// Chart info section // Chart info section
QGroupBox* chartInfoGroup = new QGroupBox(QString("Chart: %1").arg(chartData_->name)); QGroupBox* chartInfoGroup = new QGroupBox(QString("Chart: %1").arg(fileEntry_->GetName()));
QVBoxLayout* chartInfoLayout = new QVBoxLayout(chartInfoGroup); QVBoxLayout* chartInfoLayout = new QVBoxLayout(chartInfoGroup);
// Chart details - handle different chart types // Chart details - handle different chart types
QLabel* pathLabel = new QLabel(QString("File: %1").arg(QFileInfo(chartData_->path).fileName())); QLabel* pathLabel = new QLabel(QString("File: %1").arg(fileEntry_->GetFileName()));
chartInfoLayout->addWidget(pathLabel); chartInfoLayout->addWidget(pathLabel);
auto chartProperties = fileEntry_->AsCurve()->GetChartProperties();
// Type-specific information // Type-specific information
if (auto curveChart = std::dynamic_pointer_cast<CurveChartData>(chartData_)) { QLabel* titleLabel = new QLabel(QString("Title: X=%1, Y=%2").arg(chartProperties.xTitle, chartProperties.yTitle));
QLabel* titleLabel = new QLabel(QString("Title: X=%1, Y=%2").arg(curveChart->xTitle, curveChart->yTitle)); QLabel* rangeLabel = new QLabel(QString("Range: X[%1-%2], Y[%3-%4]")
QLabel* rangeLabel = new QLabel(QString("Range: X[%1-%2], Y[%3-%4]") .arg(chartProperties.xMin).arg(chartProperties.xMax)
.arg(curveChart->xMin).arg(curveChart->xMax) .arg(chartProperties.yMin).arg(chartProperties.yMax));
.arg(curveChart->yMin).arg(curveChart->yMax)); QLabel* countLabel = new QLabel(QString("Count: X=%1, T=%2").arg(chartProperties.xCount).arg(chartProperties.timeParam));
QLabel* countLabel = new QLabel(QString("Count: X=%1, T=%2").arg(curveChart->xCount).arg(curveChart->t));
chartInfoLayout->addWidget(titleLabel); chartInfoLayout->addWidget(titleLabel);
chartInfoLayout->addWidget(rangeLabel); chartInfoLayout->addWidget(rangeLabel);
chartInfoLayout->addWidget(countLabel); chartInfoLayout->addWidget(countLabel);
// Curves section // Curves section
if (!curveChart->curves.isEmpty()) { const auto& curveProperties = fileEntry_->AsCurve()->GetCurveProperties();
QGroupBox* curvesGroup = new QGroupBox(QString("Curves (%1)").arg(curveChart->curves.size())); if (!curveProperties.isEmpty()) {
QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup); QGroupBox* curvesGroup = new QGroupBox(QString("Curves (%1)").arg(curveProperties.size()));
QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
// Add scroll area for curves // Add scroll area for curves
QScrollArea* scrollArea = new QScrollArea(); QScrollArea* scrollArea = new QScrollArea();
QWidget* scrollWidget = new QWidget(); QWidget* scrollWidget = new QWidget();
QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget); QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
for (const CurveData& curve : curveChart->curves) { for (const auto& curve : curveProperties) {
QHBoxLayout* curveLayout = new QHBoxLayout(); QHBoxLayout* curveLayout = new QHBoxLayout();
// Curve checkbox for show/hide // Curve checkbox for show/hide
QCheckBox* curveCheckBox = new QCheckBox(curve.name); QCheckBox* curveCheckBox = new QCheckBox(curve.name);
curveCheckBox->setChecked(true); curveCheckBox->setChecked(true);
// Curve info // Curve info
QLabel* curveInfo = new QLabel(QString("Range: %1-%2, Color: %3") QString colorStr = QString("rgb(%1,%2,%3)").arg(curve.color.red()).arg(curve.color.green()).arg(curve.color.blue());
.arg(curve.start).arg(curve.stop).arg(curve.color)); QLabel* curveInfo = new QLabel(QString("Range: %1-%2, Color: %3")
curveInfo->setStyleSheet(QString("QLabel { color: rgb(%1); }").arg(curve.color)); .arg(curve.start).arg(curve.stop).arg(colorStr));
curveInfo->setStyleSheet(QString("QLabel { color: %1; }").arg(colorStr));
curveLayout->addWidget(curveCheckBox); curveLayout->addWidget(curveCheckBox);
curveLayout->addWidget(curveInfo); curveLayout->addWidget(curveInfo);
curveLayout->addStretch(); curveLayout->addStretch();
scrollLayout->addLayout(curveLayout); scrollLayout->addLayout(curveLayout);
}
scrollWidget->setLayout(scrollLayout);
scrollArea->setWidget(scrollWidget);
scrollArea->setWidgetResizable(true);
scrollArea->setMaximumHeight(200);
curvesLayout->addWidget(scrollArea);
mainLayout->addWidget(curvesGroup);
} }
} else if (auto surfaceChart = std::dynamic_pointer_cast<SurfaceChartData>(chartData_)) { scrollWidget->setLayout(scrollLayout);
QLabel* titleLabel = new QLabel(QString("Title: X=%1, Y=%2, Z=%3") scrollArea->setWidget(scrollWidget);
.arg(surfaceChart->xTitle, surfaceChart->yTitle, surfaceChart->zTitle)); scrollArea->setWidgetResizable(true);
QLabel* rangeLabel = new QLabel(QString("Range: X[%1-%2], Y[%3-%4], Z[%5-%6]") scrollArea->setMaximumHeight(200);
.arg(surfaceChart->xMin).arg(surfaceChart->xMax)
.arg(surfaceChart->yMin).arg(surfaceChart->yMax)
.arg(surfaceChart->zMin).arg(surfaceChart->zMax));
QLabel* countLabel = new QLabel(QString("Count: X=%1, Y=%2, Z=%3, T=%4")
.arg(surfaceChart->xCount).arg(surfaceChart->yCount)
.arg(surfaceChart->zCount).arg(surfaceChart->t));
chartInfoLayout->addWidget(titleLabel); curvesLayout->addWidget(scrollArea);
chartInfoLayout->addWidget(rangeLabel); mainLayout->addWidget(curvesGroup);
chartInfoLayout->addWidget(countLabel);
// Surface curves section
if (!surfaceChart->curves.isEmpty()) {
QGroupBox* curvesGroup = new QGroupBox(QString("Surface Curves (%1)").arg(surfaceChart->curves.size()));
QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
QScrollArea* scrollArea = new QScrollArea();
QWidget* scrollWidget = new QWidget();
QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
for (const SurfaceCurveData& curve : surfaceChart->curves) {
QHBoxLayout* curveLayout = new QHBoxLayout();
QCheckBox* curveCheckBox = new QCheckBox(curve.name);
curveCheckBox->setChecked(true);
QLabel* curveInfo = new QLabel(QString("Range: %1-%2, Color: %3, Pos: (%4,%5,%6)")
.arg(curve.start).arg(curve.stop).arg(curve.color)
.arg(curve.x).arg(curve.y).arg(curve.z));
curveInfo->setStyleSheet(QString("QLabel { color: rgb(%1); }").arg(curve.color));
curveLayout->addWidget(curveCheckBox);
curveLayout->addWidget(curveInfo);
curveLayout->addStretch();
scrollLayout->addLayout(curveLayout);
}
scrollWidget->setLayout(scrollLayout);
scrollArea->setWidget(scrollWidget);
scrollArea->setWidgetResizable(true);
scrollArea->setMaximumHeight(200);
curvesLayout->addWidget(scrollArea);
mainLayout->addWidget(curvesGroup);
}
} else if (auto tableChart = std::dynamic_pointer_cast<TableChartData>(chartData_)) {
QLabel* headLabel = new QLabel(QString("Head: %1").arg(tableChart->head));
QLabel* timeLabel = new QLabel(QString("Time: %1").arg(tableChart->t));
chartInfoLayout->addWidget(headLabel);
chartInfoLayout->addWidget(timeLabel);
// Table curves section
if (!tableChart->curves.isEmpty()) {
QGroupBox* curvesGroup = new QGroupBox(QString("Table Data (%1)").arg(tableChart->curves.size()));
QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
QScrollArea* scrollArea = new QScrollArea();
QWidget* scrollWidget = new QWidget();
QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
for (const TableCurveData& curve : tableChart->curves) {
QHBoxLayout* curveLayout = new QHBoxLayout();
QCheckBox* curveCheckBox = new QCheckBox(curve.name);
curveCheckBox->setChecked(true);
QLabel* curveInfo = new QLabel(QString("Color: %1, Data: %2")
.arg(curve.color).arg(curve.data));
curveInfo->setStyleSheet(QString("QLabel { color: rgb(%1); }").arg(curve.color));
curveLayout->addWidget(curveCheckBox);
curveLayout->addWidget(curveInfo);
curveLayout->addStretch();
scrollLayout->addLayout(curveLayout);
}
scrollWidget->setLayout(scrollLayout);
scrollArea->setWidget(scrollWidget);
scrollArea->setWidgetResizable(true);
scrollArea->setMaximumHeight(200);
curvesLayout->addWidget(scrollArea);
mainLayout->addWidget(curvesGroup);
}
} else if (auto lightChart = std::dynamic_pointer_cast<LightChartData>(chartData_)) {
QLabel* colorLabel = new QLabel(QString("Open Color: %1, Close Color: %2")
.arg(lightChart->openColor).arg(lightChart->closeColor));
QLabel* timeLabel = new QLabel(QString("Time: %1").arg(lightChart->t));
chartInfoLayout->addWidget(colorLabel);
chartInfoLayout->addWidget(timeLabel);
// Light curves section
if (!lightChart->curves.isEmpty()) {
QGroupBox* curvesGroup = new QGroupBox(QString("Light Data (%1)").arg(lightChart->curves.size()));
QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
QScrollArea* scrollArea = new QScrollArea();
QWidget* scrollWidget = new QWidget();
QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
for (const LightCurveData& curve : lightChart->curves) {
QHBoxLayout* curveLayout = new QHBoxLayout();
QCheckBox* curveCheckBox = new QCheckBox(curve.name);
curveCheckBox->setChecked(true);
QLabel* curveInfo = new QLabel(QString("Data: %1").arg(curve.data));
curveLayout->addWidget(curveCheckBox);
curveLayout->addWidget(curveInfo);
curveLayout->addStretch();
scrollLayout->addLayout(curveLayout);
}
scrollWidget->setLayout(scrollLayout);
scrollArea->setWidget(scrollWidget);
scrollArea->setWidgetResizable(true);
scrollArea->setMaximumHeight(200);
curvesLayout->addWidget(scrollArea);
mainLayout->addWidget(curvesGroup);
}
} }
// if (auto curveChart = std::dynamic_pointer_cast<CurveChartData>(fileEntry_->chartData)) {
// }
// }
// else if (auto surfaceChart = std::dynamic_pointer_cast<SurfaceChartData>(chartData_)) {
// QLabel* titleLabel = new QLabel(QString("Title: X=%1, Y=%2, Z=%3")
// .arg(surfaceChart->xTitle, surfaceChart->yTitle, surfaceChart->zTitle));
// QLabel* rangeLabel = new QLabel(QString("Range: X[%1-%2], Y[%3-%4], Z[%5-%6]")
// .arg(surfaceChart->xMin).arg(surfaceChart->xMax)
// .arg(surfaceChart->yMin).arg(surfaceChart->yMax)
// .arg(surfaceChart->zMin).arg(surfaceChart->zMax));
// QLabel* countLabel = new QLabel(QString("Count: X=%1, Y=%2, Z=%3, T=%4")
// .arg(surfaceChart->xCount).arg(surfaceChart->yCount)
// .arg(surfaceChart->zCount).arg(surfaceChart->t));
// chartInfoLayout->addWidget(titleLabel);
// chartInfoLayout->addWidget(rangeLabel);
// chartInfoLayout->addWidget(countLabel);
// // Surface curves section
// if (!surfaceChart->curves.isEmpty()) {
// QGroupBox* curvesGroup = new QGroupBox(QString("Surface Curves (%1)").arg(surfaceChart->curves.size()));
// QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
// QScrollArea* scrollArea = new QScrollArea();
// QWidget* scrollWidget = new QWidget();
// QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
// for (const SurfaceCurveData& curve : surfaceChart->curves) {
// QHBoxLayout* curveLayout = new QHBoxLayout();
// QCheckBox* curveCheckBox = new QCheckBox(curve.name);
// curveCheckBox->setChecked(true);
// QLabel* curveInfo = new QLabel(QString("Range: %1-%2, Color: %3, Pos: (%4,%5,%6)")
// .arg(curve.start).arg(curve.stop).arg(curve.color)
// .arg(curve.x).arg(curve.y).arg(curve.z));
// curveInfo->setStyleSheet(QString("QLabel { color: rgb(%1); }").arg(curve.color));
// curveLayout->addWidget(curveCheckBox);
// curveLayout->addWidget(curveInfo);
// curveLayout->addStretch();
// scrollLayout->addLayout(curveLayout);
// }
// scrollWidget->setLayout(scrollLayout);
// scrollArea->setWidget(scrollWidget);
// scrollArea->setWidgetResizable(true);
// scrollArea->setMaximumHeight(200);
// curvesLayout->addWidget(scrollArea);
// mainLayout->addWidget(curvesGroup);
// }
// } else if (auto tableChart = std::dynamic_pointer_cast<TableChartData>(chartData_)) {
// QLabel* headLabel = new QLabel(QString("Head: %1").arg(tableChart->head));
// QLabel* timeLabel = new QLabel(QString("Time: %1").arg(tableChart->t));
// chartInfoLayout->addWidget(headLabel);
// chartInfoLayout->addWidget(timeLabel);
// // Table curves section
// if (!tableChart->curves.isEmpty()) {
// QGroupBox* curvesGroup = new QGroupBox(QString("Table Data (%1)").arg(tableChart->curves.size()));
// QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
// QScrollArea* scrollArea = new QScrollArea();
// QWidget* scrollWidget = new QWidget();
// QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
// for (const TableCurveData& curve : tableChart->curves) {
// QHBoxLayout* curveLayout = new QHBoxLayout();
// QCheckBox* curveCheckBox = new QCheckBox(curve.name);
// curveCheckBox->setChecked(true);
// QLabel* curveInfo = new QLabel(QString("Color: %1, Data: %2")
// .arg(curve.color).arg(curve.data));
// curveInfo->setStyleSheet(QString("QLabel { color: rgb(%1); }").arg(curve.color));
// curveLayout->addWidget(curveCheckBox);
// curveLayout->addWidget(curveInfo);
// curveLayout->addStretch();
// scrollLayout->addLayout(curveLayout);
// }
// scrollWidget->setLayout(scrollLayout);
// scrollArea->setWidget(scrollWidget);
// scrollArea->setWidgetResizable(true);
// scrollArea->setMaximumHeight(200);
// curvesLayout->addWidget(scrollArea);
// mainLayout->addWidget(curvesGroup);
// }
// } else if (auto lightChart = std::dynamic_pointer_cast<LightChartData>(chartData_)) {
// QLabel* colorLabel = new QLabel(QString("Open Color: %1, Close Color: %2")
// .arg(lightChart->openColor).arg(lightChart->closeColor));
// QLabel* timeLabel = new QLabel(QString("Time: %1").arg(lightChart->t));
// chartInfoLayout->addWidget(colorLabel);
// chartInfoLayout->addWidget(timeLabel);
// // Light curves section
// if (!lightChart->curves.isEmpty()) {
// QGroupBox* curvesGroup = new QGroupBox(QString("Light Data (%1)").arg(lightChart->curves.size()));
// QVBoxLayout* curvesLayout = new QVBoxLayout(curvesGroup);
// QScrollArea* scrollArea = new QScrollArea();
// QWidget* scrollWidget = new QWidget();
// QVBoxLayout* scrollLayout = new QVBoxLayout(scrollWidget);
// for (const LightCurveData& curve : lightChart->curves) {
// QHBoxLayout* curveLayout = new QHBoxLayout();
// QCheckBox* curveCheckBox = new QCheckBox(curve.name);
// curveCheckBox->setChecked(true);
// QLabel* curveInfo = new QLabel(QString("Data: %1").arg(curve.data));
// curveLayout->addWidget(curveCheckBox);
// curveLayout->addWidget(curveInfo);
// curveLayout->addStretch();
// scrollLayout->addLayout(curveLayout);
// }
// scrollWidget->setLayout(scrollLayout);
// scrollArea->setWidget(scrollWidget);
// scrollArea->setWidgetResizable(true);
// scrollArea->setMaximumHeight(200);
// curvesLayout->addWidget(scrollArea);
// mainLayout->addWidget(curvesGroup);
// }
// }
mainLayout->addWidget(chartInfoGroup); mainLayout->addWidget(chartInfoGroup);
@ -306,22 +291,7 @@ void CurvePanel::UpdateCurveDisplay()
void CurvePanel::InitUI() void CurvePanel::InitUI()
{ {
initQChartView(); initQChartView();
//if (hasChartData_) {
// UpdateCurveDisplay();
//} else {
// // Create basic layout for file-based panel
// QVBoxLayout* layout = new QVBoxLayout(this);
//
// // Add placeholder label showing panel information
// QLabel* infoLabel = new QLabel(QString("Curve Panel %1\nFile: %2\n\nCurve Drawing Area\nPlease inherit this class to implement specific drawing functionality")
// .arg(GetIndex())
// .arg(QFileInfo(GetFilePath()).fileName()));
// infoLabel->setAlignment(Qt::AlignCenter);
// infoLabel->setStyleSheet("QLabel { color: #666; font-size: 12px; padding: 20px; }");
//
// layout->addWidget(infoLabel);
// setLayout(layout);
//}
} }
QString CurvePanel::GetTypeDisplayName() const QString CurvePanel::GetTypeDisplayName() const

View File

@ -38,7 +38,7 @@ public:
* @param chartData Chart data containing curve information * @param chartData Chart data containing curve information
* @param parent Parent widget * @param parent Parent widget
*/ */
explicit CurvePanel(int index, std::shared_ptr<BaseChartData> chartData, QWidget* parent = nullptr); explicit CurvePanel(int index, std::shared_ptr<FileEntryCurve> fileEntry, QWidget* parent = nullptr);
/** /**
* @brief Destructor * @brief Destructor
@ -56,18 +56,6 @@ public:
*/ */
void RefreshPanel() override; void RefreshPanel() override;
/**
* @brief Set chart data
* @param chartData Chart data to display
*/
void SetChartData(std::shared_ptr<BaseChartData> chartData);
/**
* @brief Get current chart data
* @return Current chart data
*/
std::shared_ptr<BaseChartData> GetChartData() const { return chartData_; }
protected: protected:
/** /**
* @brief Initialize UI for curve-specific layout * @brief Initialize UI for curve-specific layout
@ -92,9 +80,6 @@ private:
void UpdateCurveDisplay(); void UpdateCurveDisplay();
private: private:
std::shared_ptr<BaseChartData> chartData_; // Chart data containing curve information
bool hasChartData_; // Flag indicating if chart data is available
Ui::FitCurve* ui; Ui::FitCurve* ui;
FitCurveChartView* curveChartView; FitCurveChartView* curveChartView;
QChart* curveChart; QChart* curveChart;

View File

@ -21,6 +21,17 @@ DataPanel::DataPanel(int index, FileEntryType fileType, const QString& filePath,
LOG_INFO("Created DataPanel {} for {} file: {}", index_, FileEntryTypeToString(fileType_), filePath_.toStdString()); LOG_INFO("Created DataPanel {} for {} file: {}", index_, FileEntryTypeToString(fileType_), filePath_.toStdString());
} }
DataPanel::DataPanel(int index, std::shared_ptr<FileEntry> fileEntry, QWidget* parent)
: QWidget(parent)
, index_(index)
, fileType_(fileEntry->GetType())
, filePath_(fileEntry->GetPath())
, title_()
, dockWidget_(nullptr)
, fileEntry_(fileEntry)
{
}
DataPanel::~DataPanel() DataPanel::~DataPanel()
{ {
LOG_INFO("Destroyed DataPanel {} ({})", index_, FileEntryTypeToString(fileType_)); LOG_INFO("Destroyed DataPanel {} ({})", index_, FileEntryTypeToString(fileType_));
@ -34,21 +45,23 @@ void DataPanel::closeEvent(QCloseEvent* event)
void DataPanel::InitUI() void DataPanel::InitUI()
{ {
// Create basic layout // // Create basic layout
QVBoxLayout* layout = new QVBoxLayout(this); // QVBoxLayout* layout = new QVBoxLayout(this);
// Add placeholder label showing panel information // // Add placeholder label showing panel information
QString typeDisplayName = GetTypeDisplayName(); // QString typeDisplayName = GetTypeDisplayName();
QLabel* infoLabel = new QLabel(QString("Panel %1 (%2)\nFile: %3\n\n%4 Data Area\nPlease inherit this class to implement specific functionality") // QLabel* infoLabel = new QLabel(QString("Panel %1 (%2)\nFile: %3\n\n%4 Data Area\nPlease inherit this class to implement specific functionality")
.arg(index_) // .arg(index_)
.arg(typeDisplayName) // .arg(typeDisplayName)
.arg(QFileInfo(filePath_).fileName()) // .arg(QFileInfo(filePath_).fileName())
.arg(typeDisplayName)); // .arg(typeDisplayName));
infoLabel->setAlignment(Qt::AlignCenter); // infoLabel->setAlignment(Qt::AlignCenter);
infoLabel->setStyleSheet("QLabel { color: #666; font-size: 12px; padding: 20px; }"); // infoLabel->setStyleSheet("QLabel { color: #666; font-size: 12px; padding: 20px; }");
layout->addWidget(infoLabel); // layout->addWidget(infoLabel);
setLayout(layout); // setLayout(layout);
RefreshPanel();
} }
QString DataPanel::GenerateTitle() QString DataPanel::GenerateTitle()

View File

@ -28,6 +28,7 @@ public:
* @param parent Parent widget * @param parent Parent widget
*/ */
explicit DataPanel(int index, FileEntryType fileType, const QString& filePath, QWidget* parent = nullptr); explicit DataPanel(int index, FileEntryType fileType, const QString& filePath, QWidget* parent = nullptr);
explicit DataPanel(int index, std::shared_ptr<FileEntry> fileEntry, QWidget* parent = nullptr);
/** /**
* @brief Destructor * @brief Destructor
@ -84,6 +85,8 @@ public:
* @brief Initialize UI (virtual function, derived classes implement specific layout) * @brief Initialize UI (virtual function, derived classes implement specific layout)
*/ */
virtual void InitUI(); virtual void InitUI();
bool IsValid() const { return fileEntry_ != nullptr; }
signals: signals:
/** /**
* @brief Panel close signal * @brief Panel close signal
@ -118,5 +121,5 @@ protected:
QString title_; // Panel title QString title_; // Panel title
DockWidget* dockWidget_; // Dock widget reference DockWidget* dockWidget_; // Dock widget reference
std::shared_ptr<FileEntry> fileEntry_; // Associated file entry std::shared_ptr<FileEntry> fileEntry_{nullptr}; // Associated file entry
}; };

View File

@ -37,11 +37,11 @@ DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, cons
} }
} }
DataPanel* DataPanelFactory::CreatePanelWithChartData(FileEntryType type, int index, std::shared_ptr<BaseChartData> chartData, QWidget* parent) DataPanel* DataPanelFactory::CreatePanelWithChartData(FileEntryType type, int index, std::shared_ptr<FileEntryCurve> fileEntry, QWidget* parent)
{ {
// Currently only CurvePanel supports ChartData // Currently only CurvePanel supports ChartData
// In the future, other panel types may also support chart data // In the future, other panel types may also support chart data
return new CurvePanel(index, chartData, parent); return new CurvePanel(index, fileEntry, parent);
} }
bool DataPanelFactory::IsTypeSupported(FileEntryType fileType) bool DataPanelFactory::IsTypeSupported(FileEntryType fileType)

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "ui/Panel/DataPanel.h" #include "ui/Panel/DataPanel.h"
#include "workspace/ChartData.h" #include "workspace/FileEntry.h"
#include <memory> #include <memory>
class DataPanelFactory class DataPanelFactory
@ -11,7 +11,7 @@ public:
static DataPanel* CreatePanel(FileEntryType type, int index, const QString& filePath, QWidget* parent = nullptr); static DataPanel* CreatePanel(FileEntryType type, int index, const QString& filePath, QWidget* parent = nullptr);
// Create panel with chart data // Create panel with chart data
static DataPanel* CreatePanelWithChartData(FileEntryType type, int index, std::shared_ptr<BaseChartData> chartData, QWidget* parent = nullptr); static DataPanel* CreatePanelWithChartData(FileEntryType type, int index, std::shared_ptr<FileEntryCurve> fileEntry, QWidget* parent = nullptr);
// Check if a panel type is supported // Check if a panel type is supported
static bool IsTypeSupported(FileEntryType type); static bool IsTypeSupported(FileEntryType type);

View File

@ -198,6 +198,7 @@ DataPanel* DataPanelManager::CreateDataPanel(FileEntryType fileType, const QStri
auto fileEntries = currentWorkspace_->GetFileEntries(fileType); auto fileEntries = currentWorkspace_->GetFileEntries(fileType);
if (index < fileEntries.size()) { if (index < fileEntries.size()) {
panel->SetFileEntry(fileEntries[index]); panel->SetFileEntry(fileEntries[index]);
panel->InitUI();
} }
dockWidget->setWidget(panel); dockWidget->setWidget(panel);

View File

@ -444,19 +444,6 @@ bool AddCurveFileDlg::validateSpecificParams() {
return false; return false;
} }
// Data column validation
int xColumn = ui->xColumnSpinBox->value();
int yColumn = ui->yColumnSpinBox->value();
if (xColumn == yColumn) {
QMessageBox::warning(this, tr("Validation Error"), tr("X column and Y column cannot be the same."));
return false;
}
if (xColumn < 1 || yColumn < 1) {
QMessageBox::warning(this, tr("Validation Error"), tr("Data column indices must be greater than 0."));
return false;
}
// Time parameter validation // Time parameter validation
double timeParam = ui->timeParamSpinBox->value(); double timeParam = ui->timeParamSpinBox->value();
@ -472,12 +459,6 @@ bool AddCurveFileDlg::validateSpecificParams() {
return false; return false;
} }
// Description length validation
if (ui->descriptionEdit->toPlainText().length() > 500) {
QMessageBox::warning(this, tr("Validation Error"), tr("Description is too long. Please limit to 500 characters."));
return false;
}
return true; return true;
} }
@ -504,6 +485,7 @@ void AddCurveFileDlg::onSure() {
// Set chart properties // Set chart properties
FileEntryCurve::ChartProperties chartProps; FileEntryCurve::ChartProperties chartProps;
chartProps.xCount = ui->xCountSpinBox->value(); chartProps.xCount = ui->xCountSpinBox->value();
chartProps.yCount = ui->yCountSpinBox->value();
chartProps.xTitle = ui->xTitleEdit->text(); chartProps.xTitle = ui->xTitleEdit->text();
chartProps.yTitle = ui->yTitleEdit->text(); chartProps.yTitle = ui->yTitleEdit->text();
chartProps.xMin = ui->xMinSpinBox->value(); chartProps.xMin = ui->xMinSpinBox->value();

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>600</width>
<height>700</height> <height>705</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -29,12 +29,12 @@
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="filePathEdit"> <widget class="QLineEdit" name="filePathEdit">
<property name="placeholderText">
<string>Select curve data file...</string>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="placeholderText">
<string>Select curve data file...</string>
</property>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="0" column="2">
@ -155,10 +155,36 @@
<string>Axis Range Settings</string> <string>Axis Range Settings</string>
</property> </property>
<layout class="QGridLayout" name="axisRangeGridLayout"> <layout class="QGridLayout" name="axisRangeGridLayout">
<item row="0" column="0"> <item row="1" column="3">
<widget class="QLabel" name="xMinLabel"> <widget class="QDoubleSpinBox" name="yMaxSpinBox">
<property name="minimum">
<double>-999999.000000000000000</double>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
<property name="value">
<double>800.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="xCountSpinBox">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="value">
<number>6</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="xCountLabel">
<property name="text"> <property name="text">
<string>X Min:</string> <string>X Tick Count:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -175,23 +201,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="0" column="0">
<widget class="QLabel" name="xMaxLabel"> <widget class="QLabel" name="xMinLabel">
<property name="text"> <property name="text">
<string>X Max:</string> <string>X Min:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="3"> <item row="1" column="2">
<widget class="QDoubleSpinBox" name="xMaxSpinBox"> <widget class="QLabel" name="yMaxLabel">
<property name="minimum"> <property name="text">
<double>-999999.000000000000000</double> <string>Y Max:</string>
</property>
<property name="maximum">
<double>999999.000000000000000</double>
</property>
<property name="value">
<double>250.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@ -202,6 +222,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="3">
<widget class="QSpinBox" name="yCountSpinBox">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="value">
<number>6</number>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QDoubleSpinBox" name="yMinSpinBox"> <widget class="QDoubleSpinBox" name="yMinSpinBox">
<property name="minimum"> <property name="minimum">
@ -215,15 +248,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2"> <item row="0" column="3">
<widget class="QLabel" name="yMaxLabel"> <widget class="QDoubleSpinBox" name="xMaxSpinBox">
<property name="text">
<string>Y Max:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QDoubleSpinBox" name="yMaxSpinBox">
<property name="minimum"> <property name="minimum">
<double>-999999.000000000000000</double> <double>-999999.000000000000000</double>
</property> </property>
@ -231,27 +257,21 @@
<double>999999.000000000000000</double> <double>999999.000000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>800.000000000000000</double> <double>250.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="0" column="2">
<widget class="QLabel" name="xCountLabel"> <widget class="QLabel" name="xMaxLabel">
<property name="text"> <property name="text">
<string>X Tick Count:</string> <string>X Max:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="2">
<widget class="QSpinBox" name="xCountSpinBox"> <widget class="QLabel" name="xCountLabel_2">
<property name="minimum"> <property name="text">
<number>2</number> <string>Y Tick Count:</string>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="value">
<number>6</number>
</property> </property>
</widget> </widget>
</item> </item>
@ -288,28 +308,28 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="addCurveBtn"> <widget class="QPushButton" name="addCurveBtn">
<property name="text">
<string>Add Curve</string>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>80</width> <width>80</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<property name="text">
<string>Add Curve</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="removeCurveBtn"> <widget class="QPushButton" name="removeCurveBtn">
<property name="text">
<string>Remove</string>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>60</width> <width>60</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<property name="text">
<string>Remove</string>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -329,12 +349,12 @@
</item> </item>
<item> <item>
<widget class="QGroupBox" name="curvePropertiesGroupBox"> <widget class="QGroupBox" name="curvePropertiesGroupBox">
<property name="title">
<string>Selected Curve Properties</string>
</property>
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="title">
<string>Selected Curve Properties</string>
</property>
<layout class="QGridLayout" name="curvePropertiesGridLayout"> <layout class="QGridLayout" name="curvePropertiesGridLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="curveNameLabel"> <widget class="QLabel" name="curveNameLabel">
@ -361,15 +381,15 @@
<layout class="QHBoxLayout" name="colorLayout"> <layout class="QHBoxLayout" name="colorLayout">
<item> <item>
<widget class="QPushButton" name="colorButton"> <widget class="QPushButton" name="colorButton">
<property name="text">
<string>Select Color</string>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>100</width> <width>100</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<property name="text">
<string>Select Color</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -449,131 +469,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="paramsGroupBox">
<property name="title">
<string>Data Format Parameters</string>
</property>
<layout class="QGridLayout" name="paramsGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="xColumnLabel">
<property name="text">
<string>X Column:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="xColumnSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="yColumnLabel">
<property name="text">
<string>Y Column:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="yColumnSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="separatorLabel">
<property name="text">
<string>Separator:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="separatorComboBox">
<item>
<property name="text">
<string>Comma (,)</string>
</property>
</item>
<item>
<property name="text">
<string>Tab</string>
</property>
</item>
<item>
<property name="text">
<string>Space</string>
</property>
</item>
<item>
<property name="text">
<string>Semicolon (;)</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="hasHeaderCheckBox">
<property name="text">
<string>File has header row</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="descGroupBox">
<property name="title">
<string>Description (Optional)</string>
</property>
<layout class="QVBoxLayout" name="descVerticalLayout">
<item>
<widget class="QTextEdit" name="descriptionEdit">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>60</height>
</size>
</property>
<property name="placeholderText">
<string>Enter file description...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item> <item>
<layout class="QHBoxLayout" name="buttonLayout"> <layout class="QHBoxLayout" name="buttonLayout">
<item> <item>

View File

@ -4,6 +4,25 @@
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
// 颜色转换辅助函数
QString QColorToString(const QColor& color) {
return QString("%1,%2,%3").arg(color.red()).arg(color.green()).arg(color.blue());
}
QColor StringToQColor(const QString& colorStr) {
QStringList rgb = colorStr.split(',');
if (rgb.size() == 3) {
bool ok1, ok2, ok3;
int r = rgb[0].toInt(&ok1);
int g = rgb[1].toInt(&ok2);
int b = rgb[2].toInt(&ok3);
if (ok1 && ok2 && ok3) {
return QColor(r, g, b);
}
}
return QColor(); // 返回无效颜色
}
void FileEntry::SetPath(const QString& path) { void FileEntry::SetPath(const QString& path) {
QFileInfo fileInfo(path); QFileInfo fileInfo(path);
if (!fileInfo.exists()) { if (!fileInfo.exists()) {
@ -87,6 +106,47 @@ std::shared_ptr<FileEntryLight> CreateFileEntryLight(const QString& filePath) {
return fileEntry; return fileEntry;
} }
// Factory functions for creating empty FileEntry objects (for XML parsing)
std::shared_ptr<FileEntry> CreateEmptyFileEntry(FileEntryType type) {
switch (type) {
case FileEntryType::Curve:
return CreateEmptyFileEntryCurve();
case FileEntryType::Surface:
return CreateEmptyFileEntrySurface();
case FileEntryType::Table:
return CreateEmptyFileEntryTable();
case FileEntryType::Light:
return CreateEmptyFileEntryLight();
default:
LOG_ERROR("Unknown FileEntryType: {}", static_cast<int>(type));
return nullptr;
}
}
std::shared_ptr<FileEntryCurve> CreateEmptyFileEntryCurve() {
auto fileEntry = std::make_shared<FileEntryCurve>();
// Don't set path or name - these will be set during XML parsing
return fileEntry;
}
std::shared_ptr<FileEntry> CreateEmptyFileEntrySurface() {
auto fileEntry = std::make_shared<FileEntrySurface>();
// Don't set path or name - these will be set during XML parsing
return fileEntry;
}
std::shared_ptr<FileEntryTable> CreateEmptyFileEntryTable() {
auto fileEntry = std::make_shared<FileEntryTable>();
// Don't set path or name - these will be set during XML parsing
return fileEntry;
}
std::shared_ptr<FileEntryLight> CreateEmptyFileEntryLight() {
auto fileEntry = std::make_shared<FileEntryLight>();
// Don't set path or name - these will be set during XML parsing
return fileEntry;
}
// FileEntrySurface method implementations // FileEntrySurface method implementations
void FileEntrySurface::SetChartProperties(const ChartProperties& properties) { void FileEntrySurface::SetChartProperties(const ChartProperties& properties) {
chartProperties_ = properties; chartProperties_ = properties;
@ -184,3 +244,102 @@ void FileEntryTable::SetDescription(const QString& description) {
const QString& FileEntryTable::GetDescription() const { const QString& FileEntryTable::GetDescription() const {
return description_; return description_;
} }
// FileEntryCurve SaveFiles implementation
bool FileEntryCurve::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
if (!scene || !doc) {
LOG_ERROR("Invalid XML parameters");
return false;
}
// 创建 <chart> 元素
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
scene->InsertEndChild(chartElement);
// 设置chart属性
chartElement->SetAttribute("name", name_.toUtf8().constData());
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
chartElement->SetAttribute("xCount", chartProperties_.xCount);
chartElement->SetAttribute("yCount", chartProperties_.yCount);
chartElement->SetAttribute("xTitle", chartProperties_.xTitle.toUtf8().constData());
chartElement->SetAttribute("yTitle", chartProperties_.yTitle.toUtf8().constData());
chartElement->SetAttribute("xMin", chartProperties_.xMin);
chartElement->SetAttribute("xMax", chartProperties_.xMax);
chartElement->SetAttribute("yMin", chartProperties_.yMin);
chartElement->SetAttribute("yMax", chartProperties_.yMax);
chartElement->SetAttribute("t", chartProperties_.timeParam);
// 为每个CurveProperty创建<curve>元素
for (const auto& curve : curveProperties_) {
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
chartElement->InsertEndChild(curveElement);
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
curveElement->SetAttribute("startPoint", curve.start);
curveElement->SetAttribute("endPoint", curve.stop);
}
return true;
}
// FileEntryCurve ParseFiles implementation
bool FileEntryCurve::ParseFiles(const tinyxml2::XMLElement* element) {
if (!element) {
LOG_ERROR("Invalid XML element");
return false;
}
// 查找<chart>元素
const tinyxml2::XMLElement* chartElement = element->FirstChildElement("chart");
if (!chartElement) {
LOG_ERROR("No chart element found");
return false;
}
// 解析chart属性
const char* nameAttr = chartElement->Attribute("name");
const char* pathAttr = chartElement->Attribute("path");
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
if (pathAttr) {
QString fullPath = QString::fromUtf8(pathAttr);
QFileInfo fileInfo(fullPath);
fileName_ = fileInfo.fileName();
path_ = fileInfo.absolutePath();
}
chartProperties_.xCount = chartElement->IntAttribute("xCount", 0);
chartProperties_.yCount = chartElement->IntAttribute("yCount", 0);
const char* xTitleAttr = chartElement->Attribute("xTitle");
const char* yTitleAttr = chartElement->Attribute("yTitle");
if (xTitleAttr) chartProperties_.xTitle = QString::fromUtf8(xTitleAttr);
if (yTitleAttr) chartProperties_.yTitle = QString::fromUtf8(yTitleAttr);
chartProperties_.xMin = chartElement->DoubleAttribute("xMin", 0.0);
chartProperties_.xMax = chartElement->DoubleAttribute("xMax", 0.0);
chartProperties_.yMin = chartElement->DoubleAttribute("yMin", 0.0);
chartProperties_.yMax = chartElement->DoubleAttribute("yMax", 0.0);
chartProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0);
// 解析所有<curve>元素
curveProperties_.clear();
for (const tinyxml2::XMLElement* curveElement = chartElement->FirstChildElement("curve");
curveElement != nullptr;
curveElement = curveElement->NextSiblingElement("curve")) {
CurveProperty curve;
const char* curveNameAttr = curveElement->Attribute("name");
const char* colorAttr = curveElement->Attribute("color");
if (curveNameAttr) curve.name = QString::fromUtf8(curveNameAttr);
if (colorAttr) curve.color = StringToQColor(QString::fromUtf8(colorAttr));
curve.start = curveElement->IntAttribute("startPoint", 0);
curve.stop = curveElement->IntAttribute("endPoint", 0);
curveProperties_.append(curve);
}
return true;
}

View File

@ -2,6 +2,7 @@
#include <QString> #include <QString>
#include <QColor> #include <QColor>
#include "xml/tinyxml2.h"
enum class FileEntryType { enum class FileEntryType {
Curve, Curve,
@ -55,6 +56,9 @@ public:
virtual FileEntrySurface* AsSurface() { return nullptr; } virtual FileEntrySurface* AsSurface() { return nullptr; }
virtual FileEntryTable* AsTable() { return nullptr; } virtual FileEntryTable* AsTable() { return nullptr; }
virtual bool ParseFiles(const tinyxml2::XMLElement* element) { return false; }
virtual bool SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) { return false; }
protected: protected:
FileEntryType type_; FileEntryType type_;
QString path_; QString path_;
@ -69,18 +73,26 @@ std::shared_ptr<FileEntry> CreateFileEntrySurface(const QString& filePath);
std::shared_ptr<FileEntryTable> CreateFileEntryTable(const QString& filePath); std::shared_ptr<FileEntryTable> CreateFileEntryTable(const QString& filePath);
std::shared_ptr<FileEntryLight> CreateFileEntryLight(const QString& filePath); std::shared_ptr<FileEntryLight> CreateFileEntryLight(const QString& filePath);
// Factory functions for creating empty FileEntry objects (for XML parsing)
std::shared_ptr<FileEntry> CreateEmptyFileEntry(FileEntryType type);
std::shared_ptr<FileEntryCurve> CreateEmptyFileEntryCurve();
std::shared_ptr<FileEntry> CreateEmptyFileEntrySurface();
std::shared_ptr<FileEntryTable> CreateEmptyFileEntryTable();
std::shared_ptr<FileEntryLight> CreateEmptyFileEntryLight();
class FileEntryCurve : public FileEntry { class FileEntryCurve : public FileEntry {
public: public:
struct ChartProperties { struct ChartProperties {
int xCount; int xCount;
int yCount; // 对应XML的yCount
QString xTitle; QString xTitle;
QString yTitle; QString yTitle;
double xMin; double xMin;
double xMax; double xMax;
double yMin; double yMin;
double yMax; double yMax;
double timeParam; double timeParam; // 对应XML的t
}; };
struct CurveProperty { struct CurveProperty {
@ -104,6 +116,10 @@ public:
FileEntryCurve* AsCurve() override { return this; } FileEntryCurve* AsCurve() override { return this; }
// XML处理方法
bool SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) override;
bool ParseFiles(const tinyxml2::XMLElement* element) override;
private: private:
ChartProperties chartProperties_; ChartProperties chartProperties_;
CurveProperties curveProperties_; CurveProperties curveProperties_;

View File

@ -119,7 +119,7 @@ void WorkSpace::SetRDPath(const QString& path)
rdFile_ = fileInfo.fileName(); rdFile_ = fileInfo.fileName();
} }
WorkSpace::FileEntryResult WorkSpace::SetFileEntry(std::shared_ptr<FileEntry> fileEntry) { WorkSpace::FileEntryResult WorkSpace::SetFileEntry(std::shared_ptr<FileEntry> fileEntry, bool is_copy) {
if (!fileEntry) { if (!fileEntry) {
LOG_ERROR("FileEntry is null"); LOG_ERROR("FileEntry is null");
return FileEntryResult::InvalidFile; return FileEntryResult::InvalidFile;
@ -134,44 +134,53 @@ WorkSpace::FileEntryResult WorkSpace::SetFileEntry(std::shared_ptr<FileEntry> fi
return FileEntryResult::LimitExceeded; return FileEntryResult::LimitExceeded;
} }
// Check for duplicates by file path QString fileName;
QString filePath = QString("%1/%2").arg(fileEntry->GetPath(), fileEntry->GetFileName()); if (is_copy) {
for (const auto& existingEntry : vec) { // Check for duplicates by file path
if (existingEntry->GetPath() == filePath) { QString filePath = QString("%1/%2").arg(fileEntry->GetPath(), fileEntry->GetFileName());
LOG_WARN("Duplicate file entry: {}", filePath.toUtf8().constData()); for (const auto& existingEntry : vec) {
return FileEntryResult::Duplicate; if (existingEntry->GetPath() == filePath) {
LOG_WARN("Duplicate file entry: {}", filePath.toUtf8().constData());
return FileEntryResult::Duplicate;
}
} }
// Copy file to workspace directory
QFileInfo fileInfo(filePath);
if (!fileInfo.exists()) {
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
return FileEntryResult::InvalidFile;
}
QString targetPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName());
bool copySuccess = FileUtils::CopyFileToPath(filePath, targetPath, true);
LOG_INFO("Copy file {} to {}: {}",
filePath.toLocal8Bit().data(),
targetPath.toLocal8Bit().data(),
copySuccess);
if (!copySuccess) {
LOG_ERROR("Failed to copy file to workspace");
return FileEntryResult::CopyFailed;
}
// Update file entry with workspace-relative path
fileName = fileInfo.fileName();
fileEntry->SetFileNanme(fileInfo.fileName());
} }
else {
// Copy file to workspace directory QString filePath = QString("%1/%2").arg(GetDir(), fileEntry->GetFileName());
QFileInfo fileInfo(filePath); fileEntry->SetPath(filePath);
if (!fileInfo.exists()) { fileName = fileEntry->GetFileName();
LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData());
return FileEntryResult::InvalidFile;
} }
QString targetPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName());
bool copySuccess = FileUtils::CopyFileToPath(filePath, targetPath, true);
LOG_INFO("Copy file {} to {}: {}",
filePath.toLocal8Bit().data(),
targetPath.toLocal8Bit().data(),
copySuccess);
if (!copySuccess) {
LOG_ERROR("Failed to copy file to workspace");
return FileEntryResult::CopyFailed;
}
// Update file entry with workspace-relative path
fileEntry->SetFileNanme(fileInfo.fileName());
// Add to files collection // Add to files collection
vec.push_back(fileEntry); vec.push_back(fileEntry);
++filesSeq_; ++filesSeq_;
emit FilesChanged(type); emit FilesChanged(type);
LOG_INFO("Successfully added file entry: {} (type: {})", LOG_INFO("Successfully added file entry: {} (type: {})",
fileInfo.fileName().toUtf8().constData(), fileName.toUtf8().constData(),
FileEntryTypeToString(type)); FileEntryTypeToString(type));
return FileEntryResult::Ok; return FileEntryResult::Ok;

View File

@ -84,7 +84,7 @@ public:
enum class FileEntryResult { Ok, LimitExceeded, Duplicate, CopyFailed, TypeMismatch, InvalidFile }; enum class FileEntryResult { Ok, LimitExceeded, Duplicate, CopyFailed, TypeMismatch, InvalidFile };
// New unified file entry management // New unified file entry management
FileEntryResult SetFileEntry(std::shared_ptr<FileEntry> fileEntry); FileEntryResult SetFileEntry(std::shared_ptr<FileEntry> fileEntry, bool is_copy = true);
std::vector<std::shared_ptr<FileEntry>> GetFileEntries(FileEntryType type) const; std::vector<std::shared_ptr<FileEntry>> GetFileEntries(FileEntryType type) const;

View File

@ -122,7 +122,26 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
QString typeName = QString::fromLocal8Bit(name); QString typeName = QString::fromLocal8Bit(name);
// Parse chart elements within this type // Create FileEntry objects and call their ParseFiles method
FileEntryType enumType;
if (FileEntryTypeFromString(name, enumType)) {
// 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);
}
// Parse chart elements within this type (for chart data storage)
const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart"); const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart");
while (nullptr != chartElement) { while (nullptr != chartElement) {
std::shared_ptr<BaseChartData> chartData; std::shared_ptr<BaseChartData> chartData;
@ -385,11 +404,8 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
fileTypes.append(fileTypeData); fileTypes.append(fileTypeData);
// Also create file entries for backward compatibility // Note: FileEntry creation and parsing is already handled above
FileEntryType enumType; // No need for additional backward compatibility code here
if (FileEntryTypeFromString(name, enumType)) {
workSpace_->SetFileEntryCount(enumType, count);
}
} }
typeElement = typeElement->NextSiblingElement("type"); typeElement = typeElement->NextSiblingElement("type");
} }

View File

@ -150,6 +150,13 @@ bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocu
typeElem->SetAttribute("name", FileEntryTypeToString(type)); typeElem->SetAttribute("name", FileEntryTypeToString(type));
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) {
if (fileEntry) {
fileEntry->SaveFiles(typeElem, doc);
}
}
} }
return true; return true;
} }