From 05d2968d41efe6e431b5b929f6da4c93ca4d1e44 Mon Sep 17 00:00:00 2001 From: brige Date: Sun, 26 Oct 2025 15:55:41 +0800 Subject: [PATCH 1/3] modify file entity --- src/translations/Dyt_zh_CN.ts | 220 ++++++++++------ src/ui/Menu/FileManagerMenu.cpp | 116 +++++---- src/ui/Panel/DataPanelManager.cpp | 6 +- .../PropertyBrowser/qtworkspaceattribute.cpp | 15 +- src/ui/PropertyBrowser/qtworkspaceattribute.h | 2 +- src/ui/WorkSpace/AddCurveFileDlg.cpp | 245 +++++++++--------- src/ui/WorkSpace/AddCurveFileDlg.h | 59 +---- src/ui/WorkSpace/AddLightFileDlg.cpp | 4 - src/ui/WorkSpace/AddLightFileDlg.h | 2 +- src/ui/WorkSpace/AddSurfaceFileDlg.cpp | 5 - src/ui/WorkSpace/AddSurfaceFileDlg.h | 1 - src/ui/WorkSpace/AddTableFileDlg.cpp | 5 - src/ui/WorkSpace/AddTableFileDlg.h | 1 - src/ui/WorkSpace/BaseAddFileDlg.cpp | 85 +----- src/ui/WorkSpace/BaseAddFileDlg.h | 23 +- src/workspace/FileEntry.cpp | 79 ++++++ src/workspace/FileEntry.h | 82 +++++- src/workspace/WorkSpace.cpp | 125 ++++++--- src/workspace/WorkSpace.h | 13 +- src/workspace/WorkSpaceXMLParse.cpp | 4 +- 20 files changed, 608 insertions(+), 484 deletions(-) create mode 100644 src/workspace/FileEntry.cpp diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index bbabbc89..e3bf245a 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -245,152 +245,194 @@ - + Curve %1 - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + Validation Error - + Please select a data file. - + Selected file does not exist. - + Selected file is not readable. Please check file permissions. - + File is too large (over 100MB). Please select a smaller file. - + At least one curve must be defined. - + Curve %1 name cannot be empty. - + Curve name '%1' is duplicated. Please use different names. - + Curve name '%1' is too long. Please limit to 50 characters. - + Curve '%1' start and stop values must be greater than 0. - + Curve '%1' start value cannot be greater than stop value. - + Curve '%1' data range is too small. At least 2 data points are required. - + Curve '%1' stop value is too large. Please ensure it does not exceed 1000000. - + Chart name cannot be empty. - + Chart name is too long. Please limit to 100 characters. - + X axis title is too long. Please limit to 50 characters. - + Y axis title is too long. Please limit to 50 characters. - + X axis minimum value must be less than maximum value. - + Y axis minimum value must be less than maximum value. - + X column and Y column cannot be the same. - + Data column indices must be greater than 0. - + Time parameter cannot be negative. - + X axis tick count must be at least 2. - + Description is too long. Please limit to 500 characters. + + + + + Error + + + + + Failed to create file entry + + + + + Unable to get current workspace + + + + + Curve file count has reached the limit (9 files) + + + + + File already exists + + + + + File copy failed + + + + + Invalid file + + + + + Failed to add file + + AddLightFileDlg @@ -1740,30 +1782,34 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + prompt - - - + + + please create workspace first @@ -1773,42 +1819,50 @@ - - + + - + Error - - + + - - Failed to set file path + + Failed to create file entry - - - - + + + + + invalid file + + + + + + + up to 9 files allowed for this type - - - - + + + + file already added for this type - - - - + + + + copy file failed diff --git a/src/ui/Menu/FileManagerMenu.cpp b/src/ui/Menu/FileManagerMenu.cpp index b10caebb..f5c94408 100644 --- a/src/ui/Menu/FileManagerMenu.cpp +++ b/src/ui/Menu/FileManagerMenu.cpp @@ -96,20 +96,19 @@ void FileManagerMenu::AddWaveFile() { if (dialog && dialog->exec() == QDialog::Accepted) { QString selectedPath = dialog->getSelectedFilePath(); - // Create file entry - switch (current->CreateFileEntry(FileEntryType::Curve)) { - case WorkSpace::FileEntryResult::Ok: { - // Get the index of the newly created file entry - auto entries = current->GetFileEntries(FileEntryType::Curve); - int newIndex = static_cast(entries.size()) - 1; - - // Set file path - if (!current->SetFileEntryPath(FileEntryType::Curve, newIndex, selectedPath)) { - QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), - QObject::tr("Failed to set file path")); - } - break; + // Create file entry using factory function + auto fileEntry = CreateFileEntryCurve(selectedPath); + if (!fileEntry) { + QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), + QObject::tr("Failed to create file entry")); + return; } + + // Add to workspace + switch (current->SetFileEntry(fileEntry)) { + case WorkSpace::FileEntryResult::Ok: + // Success - no action needed + break; case WorkSpace::FileEntryResult::LimitExceeded: QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("up to 9 files allowed for this type")); @@ -122,6 +121,10 @@ void FileManagerMenu::AddWaveFile() { QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("copy file failed")); break; + case WorkSpace::FileEntryResult::InvalidFile: + QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + QObject::tr("invalid file")); + break; } } } @@ -138,20 +141,19 @@ void FileManagerMenu::AddSurfaceFile() { if (dialog && dialog->exec() == QDialog::Accepted) { QString selectedPath = dialog->getSelectedFilePath(); - // Create file entry - switch (current->CreateFileEntry(FileEntryType::Surface)) { - case WorkSpace::FileEntryResult::Ok: { - // Get the index of the newly created file entry - auto entries = current->GetFileEntries(FileEntryType::Surface); - int newIndex = static_cast(entries.size()) - 1; - - // Set file path - if (!current->SetFileEntryPath(FileEntryType::Surface, newIndex, selectedPath)) { - QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), - QObject::tr("Failed to set file path")); - } - break; + // Create file entry using factory function + auto fileEntry = CreateFileEntrySurface(selectedPath); + if (!fileEntry) { + QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), + QObject::tr("Failed to create file entry")); + return; } + + // Add to workspace + switch (current->SetFileEntry(fileEntry)) { + case WorkSpace::FileEntryResult::Ok: + // Success - no action needed + break; case WorkSpace::FileEntryResult::LimitExceeded: QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("up to 9 files allowed for this type")); @@ -164,6 +166,10 @@ void FileManagerMenu::AddSurfaceFile() { QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("copy file failed")); break; + case WorkSpace::FileEntryResult::InvalidFile: + QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + QObject::tr("invalid file")); + break; } } } @@ -180,20 +186,19 @@ void FileManagerMenu::AddTableFile() { if (dialog && dialog->exec() == QDialog::Accepted) { QString selectedPath = dialog->getSelectedFilePath(); - // Create file entry - switch (current->CreateFileEntry(FileEntryType::Table)) { - case WorkSpace::FileEntryResult::Ok: { - // Get the index of the newly created file entry - auto entries = current->GetFileEntries(FileEntryType::Table); - int newIndex = static_cast(entries.size()) - 1; - - // Set file path - if (!current->SetFileEntryPath(FileEntryType::Table, newIndex, selectedPath)) { - QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), - QObject::tr("Failed to set file path")); - } - break; + // Create file entry using factory function + auto fileEntry = CreateFileEntryTable(selectedPath); + if (!fileEntry) { + QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), + QObject::tr("Failed to create file entry")); + return; } + + // Add to workspace + switch (current->SetFileEntry(fileEntry)) { + case WorkSpace::FileEntryResult::Ok: + // Success - no action needed + break; case WorkSpace::FileEntryResult::LimitExceeded: QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("up to 9 files allowed for this type")); @@ -206,6 +211,10 @@ void FileManagerMenu::AddTableFile() { QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("copy file failed")); break; + case WorkSpace::FileEntryResult::InvalidFile: + QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + QObject::tr("invalid file")); + break; } } } @@ -222,20 +231,19 @@ void FileManagerMenu::AddLightFile() { if (dialog && dialog->exec() == QDialog::Accepted) { QString selectedPath = dialog->getSelectedFilePath(); - // Create file entry - switch (current->CreateFileEntry(FileEntryType::Light)) { - case WorkSpace::FileEntryResult::Ok: { - // Get the index of the newly created file entry - auto entries = current->GetFileEntries(FileEntryType::Light); - int newIndex = static_cast(entries.size()) - 1; - - // Set file path - if (!current->SetFileEntryPath(FileEntryType::Light, newIndex, selectedPath)) { - QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), - QObject::tr("Failed to set file path")); - } - break; + // Create file entry using factory function + auto fileEntry = CreateFileEntryLight(selectedPath); + if (!fileEntry) { + QMessageBox::warning(&MainFrame::Get(), QObject::tr("Error"), + QObject::tr("Failed to create file entry")); + return; } + + // Add to workspace + switch (current->SetFileEntry(fileEntry)) { + case WorkSpace::FileEntryResult::Ok: + // Success - no action needed + break; case WorkSpace::FileEntryResult::LimitExceeded: QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("up to 9 files allowed for this type")); @@ -248,6 +256,10 @@ void FileManagerMenu::AddLightFile() { QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("copy file failed")); break; + case WorkSpace::FileEntryResult::InvalidFile: + QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + QObject::tr("invalid file")); + break; } } } diff --git a/src/ui/Panel/DataPanelManager.cpp b/src/ui/Panel/DataPanelManager.cpp index 46eb1b64..d35f4d74 100644 --- a/src/ui/Panel/DataPanelManager.cpp +++ b/src/ui/Panel/DataPanelManager.cpp @@ -114,7 +114,7 @@ void DataPanelManager::UpdatePanelsForType(FileEntryType fileType) } // Get files of specified type from current workspace - std::vector files = currentWorkspace_->GetFileEntries(fileType); + std::vector> files = currentWorkspace_->GetFileEntries(fileType); // Limit to maximum panels per type const int maxPanels = qMin(static_cast(files.size()), GetMaxPanelCount()); @@ -135,8 +135,8 @@ void DataPanelManager::UpdatePanelsForType(FileEntryType fileType) // Create or update panels for (int i = 0; i < maxPanels; ++i) { - const FileEntry& fileEntry = files[i]; - QString filePath = currentWorkspace_->GetFileEntryAbsPath(fileEntry.type, i); + std::shared_ptr fileEntry = files[i]; + QString filePath = currentWorkspace_->GetFileEntryAbsPath(fileEntry->GetType(), i); QString panelKey = QString("%1_%2").arg(FileEntryTypeToString(fileType)).arg(i); if (dataPanels_.contains(panelKey)) { diff --git a/src/ui/PropertyBrowser/qtworkspaceattribute.cpp b/src/ui/PropertyBrowser/qtworkspaceattribute.cpp index b402d5f9..6ef94bee 100644 --- a/src/ui/PropertyBrowser/qtworkspaceattribute.cpp +++ b/src/ui/PropertyBrowser/qtworkspaceattribute.cpp @@ -192,7 +192,7 @@ const QString QWorkspaceAttribute::GetCommondFilePath() const return workspace_->GetCommondFilePath(); } -std::vector QWorkspaceAttribute::GetFileEntries(FileEntryType type) const { +std::vector> QWorkspaceAttribute::GetFileEntries(FileEntryType type) const { if (nullptr == workspace_) { return {}; } @@ -210,7 +210,18 @@ void QWorkspaceAttribute::SetFileEntryPath(FileEntryType type, int index, const if (nullptr == workspace_) { return; } - workspace_->SetFileEntryPath(type, index, path); + + // Get the file entries for this type + auto entries = workspace_->GetFileEntries(type); + if (index < 0 || index >= static_cast(entries.size())) { + return; + } + + // Update the path of the specific entry + entries[index]->SetPath(path); + + // Trigger files changed signal + workspace_->SetFileEntryCount(type, static_cast(entries.size())); } QString QWorkspaceAttribute::GetFileEntryAbsPath(FileEntryType type, int index) const { diff --git a/src/ui/PropertyBrowser/qtworkspaceattribute.h b/src/ui/PropertyBrowser/qtworkspaceattribute.h index f1add88a..7efdc1a6 100644 --- a/src/ui/PropertyBrowser/qtworkspaceattribute.h +++ b/src/ui/PropertyBrowser/qtworkspaceattribute.h @@ -85,7 +85,7 @@ public: const QString GetCommondFilePath() const; // Grouped files API - std::vector GetFileEntries(FileEntryType type) const; + std::vector> GetFileEntries(FileEntryType type) const; void SetFileEntryCount(FileEntryType type, int count); void SetFileEntryPath(FileEntryType type, int index, const QString& path); QString GetFileEntryAbsPath(FileEntryType type, int index) const; diff --git a/src/ui/WorkSpace/AddCurveFileDlg.cpp b/src/ui/WorkSpace/AddCurveFileDlg.cpp index a10e49f3..3c75f77c 100644 --- a/src/ui/WorkSpace/AddCurveFileDlg.cpp +++ b/src/ui/WorkSpace/AddCurveFileDlg.cpp @@ -6,6 +6,9 @@ #include #include +#include "workspace/WorkSpace.h" +#include "workspace/WorkSpaceManager.h" + #include "ui_AddCurveFileDlg.h" AddCurveFileDlg::AddCurveFileDlg(QWidget* parent) @@ -16,7 +19,6 @@ AddCurveFileDlg::AddCurveFileDlg(QWidget* parent) SetupUI(ui); SetTitle(getDialogTitle()); - setupSpecificUI(); setupConnections(); } @@ -24,44 +26,15 @@ AddCurveFileDlg::~AddCurveFileDlg() { delete ui; } -void AddCurveFileDlg::setupSpecificUI() { - // Initialize curve properties group as disabled - enableCurveProperties(false); - - // Initialize color preview - updateColorPreview(selectedColor_); - - // Add a default curve - CurveProperties defaultCurve; - defaultCurve.name = generateCurveName(); - defaultCurve.color = generateCurveColor(); - defaultCurve.start = 1; - defaultCurve.stop = 241; - - curves_.append(defaultCurve); - addCurveToList(defaultCurve); - - // Select the first curve - if (ui->curveListWidget->count() > 0) { - ui->curveListWidget->setCurrentRow(0); - onCurveSelectionChanged(); - } -} - void AddCurveFileDlg::setupConnections() { // File selection connections - connect(ui->selectFileBtn, &QToolButton::clicked, this, &AddCurveFileDlg::onSelectFileClicked); - connect(ui->filePathEdit, &QLineEdit::textChanged, this, &AddCurveFileDlg::onFilePathChanged); - - // Data format connections - connect(ui->separatorComboBox, QOverload::of(&QComboBox::currentIndexChanged), - this, &AddCurveFileDlg::onDelimiterChanged); - connect(ui->hasHeaderCheckBox, &QCheckBox::toggled, this, &AddCurveFileDlg::onHeaderToggled); + connect(ui->selectFileBtn, &QToolButton::clicked, this, &AddCurveFileDlg::OnSelectFile); // Curve management connections connect(ui->addCurveBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onAddCurveClicked); connect(ui->removeCurveBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onRemoveCurveClicked); connect(ui->curveListWidget, &QListWidget::currentRowChanged, this, &AddCurveFileDlg::onCurveSelectionChanged); + connect(ui->curveListWidget, &QListWidget::itemClicked, this, &AddCurveFileDlg::onCurveListWidgetItemClicked); // Curve properties connections connect(ui->colorButton, &QPushButton::clicked, this, &AddCurveFileDlg::onColorButtonClicked); @@ -74,36 +47,29 @@ void AddCurveFileDlg::setupConnections() { connect(ui->cancelBtn, &QPushButton::clicked, this, &QDialog::reject); } -void AddCurveFileDlg::onSelectFileClicked() { - QString fileName = QFileDialog::getOpenFileName( - this, - getDialogTitle(), - QString(), - getFileFilter() - ); - - if (!fileName.isEmpty()) { - ui->filePathEdit->setText(fileName); - updateFileInfo(fileName); - } -} void AddCurveFileDlg::updateFileInfo(const QString& filePath) { QFileInfo fileInfo(filePath); if (fileInfo.exists()) { ui->fileNameValue->setText(fileInfo.fileName()); - ui->fileSizeValue->setText(QString::number(fileInfo.size()) + " bytes"); + qint64 size = fileInfo.size(); + QString sizeText; + if (size < 1024) { + sizeText = QString("%1 B").arg(size); + } + else if (size < 1024 * 1024) { + sizeText = QString("%1 KB").arg(size / 1024.0, 0, 'f', 1); + } + else { + sizeText = QString("%1 MB").arg(size / (1024.0 * 1024.0), 0, 'f', 1); + } + ui->fileSizeValue->setText(sizeText); } else { ui->fileNameValue->setText("-"); ui->fileSizeValue->setText("-"); } -} -void AddCurveFileDlg::onFilePathChanged() { - QString filePath = ui->filePathEdit->text(); - if (!filePath.isEmpty()) { - updateFileInfo(filePath); - } + ui->filePathEdit->setText(filePath); } void AddCurveFileDlg::onAddCurveClicked() { @@ -113,7 +79,7 @@ void AddCurveFileDlg::onAddCurveClicked() { } // Create new curve with default properties - CurveProperties newCurve; + FileEntryCurve::CurveProperty newCurve; newCurve.name = generateCurveName(); newCurve.color = generateCurveColor(); newCurve.start = 1; @@ -121,7 +87,17 @@ void AddCurveFileDlg::onAddCurveClicked() { // Add to curves list and UI curves_.append(newCurve); - addCurveToList(newCurve); + + // Add to UI list widget + QListWidgetItem* item = new QListWidgetItem(QString("%1 [%2,%3] (%4,%5,%6)") + .arg(newCurve.name) + .arg(newCurve.start) + .arg(newCurve.stop) + .arg(newCurve.color.red()) + .arg(newCurve.color.green()) + .arg(newCurve.color.blue())); + ui->curveListWidget->addItem(item); + ++currentCurveIndex_; // Select the new curve ui->curveListWidget->setCurrentRow(curves_.size() - 1); @@ -134,7 +110,7 @@ void AddCurveFileDlg::onRemoveCurveClicked() { } // Don't allow removing the last curve - if (curves_.size() <= 1) { + if (curves_.size() <= 0) { QMessageBox::information(this, "Information", "At least one curve must remain."); return; } @@ -157,6 +133,33 @@ void AddCurveFileDlg::onRemoveCurveClicked() { } } +void AddCurveFileDlg::onCurveListWidgetItemClicked(QListWidgetItem* item) { + if (!item) { + return; + } + + // 获取点击项的索引 + int clickedIndex = ui->curveListWidget->row(item); + + // 如果点击的是当前选中项,可以进入编辑模式 + if (clickedIndex == currentCurveIndex_) { + ui->curveNameEdit->setText(curves_[currentCurveIndex_].name); + ui->dataStartSpinBox->setValue(curves_[currentCurveIndex_].start); + ui->dataStopSpinBox->setValue(curves_[currentCurveIndex_].stop); + updateColorPreview(curves_[currentCurveIndex_].color); + + // 启用曲线属性编辑 + enableCurveProperties(true); + + // 将焦点设置到曲线名称编辑框,方便用户直接编辑 + ui->curveNameEdit->setFocus(); + ui->curveNameEdit->selectAll(); + } else { + // 如果点击的是不同的项,更新选择 + onCurveSelectionChanged(); + } +} + void AddCurveFileDlg::onCurveSelectionChanged() { int currentRow = ui->curveListWidget->currentRow(); @@ -238,7 +241,7 @@ void AddCurveFileDlg::onColorButtonClicked() { } } -void AddCurveFileDlg::addCurveToList(const CurveProperties& curve) { +void AddCurveFileDlg::addCurveToList(const FileEntryCurve::CurveProperty& curve) { QString itemText = QString("%1 [%2,%3] (%4,%5,%6)") .arg(curve.name) .arg(curve.start) @@ -252,7 +255,7 @@ void AddCurveFileDlg::addCurveToList(const CurveProperties& curve) { void AddCurveFileDlg::updateCurveProperties() { if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) { - const CurveProperties& curve = curves_[currentCurveIndex_]; + const FileEntryCurve::CurveProperty& curve = curves_[currentCurveIndex_]; ui->curveNameEdit->setText(curve.name); ui->dataStartSpinBox->setValue(curve.start); @@ -315,13 +318,14 @@ void AddCurveFileDlg::updateColorPreview(const QColor& color) { bool AddCurveFileDlg::validateSpecificParams() { // File path validation - if (ui->filePathEdit->text().isEmpty()) { + const QString& selectFilePath = getSelectedFilePath(); + if (selectFilePath.isEmpty()) { QMessageBox::warning(this, tr("Validation Error"), tr("Please select a data file.")); return false; } // File existence validation - QFileInfo fileInfo(ui->filePathEdit->text()); + QFileInfo fileInfo(selectFilePath); if (!fileInfo.exists()) { QMessageBox::warning(this, tr("Validation Error"), tr("Selected file does not exist.")); return false; @@ -353,7 +357,7 @@ bool AddCurveFileDlg::validateSpecificParams() { // Curve name uniqueness validation QStringList curveNames; for (int i = 0; i < curves_.size(); ++i) { - const CurveProperties& curve = curves_[i]; + const FileEntryCurve::CurveProperty& curve = curves_[i]; if (curve.name.isEmpty()) { QMessageBox::warning(this, tr("Validation Error"), @@ -485,68 +489,67 @@ QString AddCurveFileDlg::getDialogTitle() const { return "Add Curve Data File"; } -AddCurveFileDlg::CurveParams AddCurveFileDlg::getCurveParams() const { - CurveParams params; - params.chart = getChartProperties(); - params.curves = getCurveProperties(); - params.format = getDataFormatParams(); - return params; -} - -AddCurveFileDlg::ChartProperties AddCurveFileDlg::getChartProperties() const { - ChartProperties chart; - chart.name = ui->chartNameEdit->text(); - chart.path = ui->filePathEdit->text(); - chart.xTitle = ui->xTitleEdit->text(); - chart.yTitle = ui->yTitleEdit->text(); - chart.xMin = ui->xMinSpinBox->value(); - chart.xMax = ui->xMaxSpinBox->value(); - chart.xCount = ui->xCountSpinBox->value(); - chart.yMin = ui->yMinSpinBox->value(); - chart.yMax = ui->yMaxSpinBox->value(); - chart.timeParam = ui->timeParamSpinBox->value(); - return chart; -} - -QList AddCurveFileDlg::getCurveProperties() const { - return curves_; -} - -AddCurveFileDlg::DataFormatParams AddCurveFileDlg::getDataFormatParams() const { - DataFormatParams format; - - // Get delimiter based on combo box selection - QString delimiterText = ui->separatorComboBox->currentText(); - if (delimiterText.contains("Comma")) { - format.delimiter = ","; - } else if (delimiterText.contains("Tab")) { - format.delimiter = "\t"; - } else if (delimiterText.contains("Space")) { - format.delimiter = " "; - } else if (delimiterText.contains("Semicolon")) { - format.delimiter = ";"; - } else { - format.delimiter = ","; // Default - } - - format.hasHeader = ui->hasHeaderCheckBox->isChecked(); - format.xColumn = ui->xColumnSpinBox->value(); - format.yColumn = ui->yColumnSpinBox->value(); - format.description = ui->descriptionEdit->toPlainText(); - - return format; -} - -void AddCurveFileDlg::onDelimiterChanged() { - // This slot can be used for future delimiter-related logic -} - -void AddCurveFileDlg::onHeaderToggled(bool hasHeader) { - // This slot can be used for future header-related logic -} - void AddCurveFileDlg::onSure() { if (validateSpecificParams()) { + // Create FileEntryCurve object using factory function + auto fileEntryCurve = CreateFileEntryCurve(getSelectedFilePath()); + if (!fileEntryCurve) { + QMessageBox::warning(this, tr("Error"), tr("Failed to create file entry")); + return; + } + + // Set curve properties + fileEntryCurve->SetName(ui->chartNameEdit->text()); + + // Set chart properties + FileEntryCurve::ChartProperties chartProps; + chartProps.xCount = ui->xCountSpinBox->value(); + chartProps.xTitle = ui->xTitleEdit->text(); + chartProps.yTitle = ui->yTitleEdit->text(); + chartProps.xMin = ui->xMinSpinBox->value(); + chartProps.xMax = ui->xMaxSpinBox->value(); + chartProps.yMin = ui->yMinSpinBox->value(); + chartProps.yMax = ui->yMaxSpinBox->value(); + chartProps.timeParam = ui->timeParamSpinBox->value(); + fileEntryCurve->SetChartProperties(chartProps); + + // Add curve properties + for (const auto& curve : curves_) { + fileEntryCurve->AddCurveProperty(curve); + } + + // Get current workspace + WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent(); + if (!workspace) { + QMessageBox::warning(this, tr("Error"), tr("Unable to get current workspace")); + return; + } + + // Add FileEntryCurve to workspace using new SetFileEntry method + auto result = workspace->SetFileEntry(fileEntryCurve); + if (result != WorkSpace::FileEntryResult::Ok) { + QString errorMsg; + switch (result) { + case WorkSpace::FileEntryResult::LimitExceeded: + errorMsg = tr("Curve file count has reached the limit (9 files)"); + break; + case WorkSpace::FileEntryResult::Duplicate: + errorMsg = tr("File already exists"); + break; + case WorkSpace::FileEntryResult::CopyFailed: + errorMsg = tr("File copy failed"); + break; + case WorkSpace::FileEntryResult::InvalidFile: + errorMsg = tr("Invalid file"); + break; + default: + errorMsg = tr("Failed to add file"); + break; + } + QMessageBox::warning(this, tr("Error"), errorMsg); + return; + } + accept(); } -} \ No newline at end of file +} diff --git a/src/ui/WorkSpace/AddCurveFileDlg.h b/src/ui/WorkSpace/AddCurveFileDlg.h index e9c20631..2da9ed32 100644 --- a/src/ui/WorkSpace/AddCurveFileDlg.h +++ b/src/ui/WorkSpace/AddCurveFileDlg.h @@ -1,8 +1,10 @@ #pragma once #include "BaseAddFileDlg.h" +#include "workspace/FileEntry.h" #include #include +#include class QLineEdit; class QCheckBox; @@ -24,66 +26,20 @@ class AddCurveFileDlg : public BaseAddFileDlg { Q_OBJECT public: - // Chart properties structure - struct ChartProperties { - QString name; - QString path; - QString xTitle; - QString yTitle; - double xMin; - double xMax; - int xCount; - double yMin; - double yMax; - double timeParam; - }; - - // Curve properties structure - struct CurveProperties { - QString name; - QColor color; - int start; - int stop; - }; - - // Data format parameters structure - struct DataFormatParams { - QString delimiter; - bool hasHeader; - int xColumn; - int yColumn; - QString description; - }; - - // Combined parameters structure - struct CurveParams { - ChartProperties chart; - QList curves; // Changed to support multiple curves - DataFormatParams format; - }; - explicit AddCurveFileDlg(QWidget* parent = nullptr); ~AddCurveFileDlg() override; - CurveParams getCurveParams() const; - ChartProperties getChartProperties() const; - QList getCurveProperties() const; // Changed to return list - DataFormatParams getDataFormatParams() const; - protected: QString getFileFilter() const override; QString getDialogTitle() const override; - void setupSpecificUI() override; bool validateSpecificParams() override; + void updateFileInfo(const QString& filePath) override; private slots: - void onDelimiterChanged(); - void onHeaderToggled(bool hasHeader); - void onSelectFileClicked(); - void onFilePathChanged(); void onColorButtonClicked(); void onAddCurveClicked(); void onRemoveCurveClicked(); + void onCurveListWidgetItemClicked(QListWidgetItem* item); void onCurveSelectionChanged(); void onCurveNameChanged(); void onCurveDataChanged(); @@ -91,9 +47,8 @@ private slots: private: void setupConnections(); - void updateFileInfo(const QString& filePath); void updateColorPreview(const QColor& color); - void addCurveToList(const CurveProperties& curve); + void addCurveToList(const FileEntryCurve::CurveProperty& curve); void updateCurveProperties(); void saveCurveProperties(); void clearCurveProperties(); @@ -102,7 +57,9 @@ private: QColor generateCurveColor() const; Ui::AddCurveFileDlg* ui; - QList curves_; int currentCurveIndex_; QColor selectedColor_; + + FileEntryCurve::ChartProperties chartProperties_; + FileEntryCurve::CurveProperties curves_; }; \ No newline at end of file diff --git a/src/ui/WorkSpace/AddLightFileDlg.cpp b/src/ui/WorkSpace/AddLightFileDlg.cpp index f67844ee..dd5b8b0a 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.cpp +++ b/src/ui/WorkSpace/AddLightFileDlg.cpp @@ -11,16 +11,12 @@ AddLightFileDlg::AddLightFileDlg(QWidget* parent) ui->setupUi(this); SetTitle(getDialogTitle()); - setupSpecificUI(); } AddLightFileDlg::~AddLightFileDlg() { delete ui; } -void AddLightFileDlg::setupSpecificUI() { -} - bool AddLightFileDlg::validateSpecificParams() { LightParams params = getLightParams(); diff --git a/src/ui/WorkSpace/AddLightFileDlg.h b/src/ui/WorkSpace/AddLightFileDlg.h index 04588887..f5a6ba30 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.h +++ b/src/ui/WorkSpace/AddLightFileDlg.h @@ -27,8 +27,8 @@ public: protected: QString getFileFilter() const override; QString getDialogTitle() const override; - void setupSpecificUI() override; bool validateSpecificParams() override; + void updateFileInfo(const QString& filePath) override {} private slots: void onDelimiterChanged(); diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.cpp b/src/ui/WorkSpace/AddSurfaceFileDlg.cpp index 65faa002..c924087f 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.cpp +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.cpp @@ -14,7 +14,6 @@ AddSurfaceFileDlg::AddSurfaceFileDlg(QWidget* parent) ui_->setupUi(this); SetTitle(getDialogTitle()); - setupSpecificUI(); setupConnections(); } @@ -22,10 +21,6 @@ AddSurfaceFileDlg::~AddSurfaceFileDlg() { delete ui_; } -void AddSurfaceFileDlg::setupSpecificUI() { - // UI is already set up in constructor -} - void AddSurfaceFileDlg::setupConnections() { connect(ui_->selectFileBtn, &QToolButton::clicked, this, &AddSurfaceFileDlg::onSelectFileClicked); connect(ui_->filePathEdit, &QLineEdit::textChanged, this, &AddSurfaceFileDlg::onFilePathChanged); diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.h b/src/ui/WorkSpace/AddSurfaceFileDlg.h index 367ba2e2..07738b19 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.h +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.h @@ -41,7 +41,6 @@ public: protected: QString getFileFilter() const override; QString getDialogTitle() const override; - void setupSpecificUI() override; bool validateSpecificParams() override; private slots: diff --git a/src/ui/WorkSpace/AddTableFileDlg.cpp b/src/ui/WorkSpace/AddTableFileDlg.cpp index ef6f9181..8f666f4d 100644 --- a/src/ui/WorkSpace/AddTableFileDlg.cpp +++ b/src/ui/WorkSpace/AddTableFileDlg.cpp @@ -16,7 +16,6 @@ AddTableFileDlg::AddTableFileDlg(QWidget* parent) ui->setupUi(this); SetTitle(getDialogTitle()); - setupSpecificUI(); setupConnections(); } @@ -24,10 +23,6 @@ AddTableFileDlg::~AddTableFileDlg() { delete ui; } -void AddTableFileDlg::setupSpecificUI() { - // UI is already set up in constructor -} - void AddTableFileDlg::setupConnections() { // Connect file selection connect(ui->selectFileBtn, &QToolButton::clicked, this, &AddTableFileDlg::onSelectFileClicked); diff --git a/src/ui/WorkSpace/AddTableFileDlg.h b/src/ui/WorkSpace/AddTableFileDlg.h index f91de097..8ed648b3 100644 --- a/src/ui/WorkSpace/AddTableFileDlg.h +++ b/src/ui/WorkSpace/AddTableFileDlg.h @@ -28,7 +28,6 @@ public: protected: QString getFileFilter() const override; QString getDialogTitle() const override; - void setupSpecificUI() override; bool validateSpecificParams() override; private slots: diff --git a/src/ui/WorkSpace/BaseAddFileDlg.cpp b/src/ui/WorkSpace/BaseAddFileDlg.cpp index 8efc49c7..1036464d 100644 --- a/src/ui/WorkSpace/BaseAddFileDlg.cpp +++ b/src/ui/WorkSpace/BaseAddFileDlg.cpp @@ -18,15 +18,8 @@ BaseAddFileDlg::BaseAddFileDlg(FileEntryType fileType, QWidget* parent) : Dialog(parent) - , fileType_(fileType) - , leFilePath_(nullptr) - , tbSelectFile_(nullptr) - , lblFileName_(nullptr) - , lblFileSize_(nullptr) - , teDescription_(nullptr) { + , fileType_(fileType) { - //setupBaseUI(); - initBaseConnect(); } BaseAddFileDlg::~BaseAddFileDlg() { @@ -40,67 +33,12 @@ QString BaseAddFileDlg::getSelectedFilePath() const { return selectedFilePath_; } -QString BaseAddFileDlg::getDescription() const { - return teDescription_->toPlainText().trimmed(); -} - -void BaseAddFileDlg::setupBaseUI() { - setFixedSize(500, 400); - - QVBoxLayout* mainLayout = new QVBoxLayout(this); - mainLayout->setContentsMargins(20, 20, 20, 20); - mainLayout->setSpacing(15); - - QGroupBox* fileGroup = new QGroupBox(QStringLiteral("File Selection"), this); - QGridLayout* fileLayout = new QGridLayout(fileGroup); - - QLabel* pathLabel = new QLabel(QStringLiteral("File Path:"), this); - leFilePath_ = new QLineEdit(this); - leFilePath_->setReadOnly(true); - tbSelectFile_ = new QToolButton(this); - tbSelectFile_->setText(QStringLiteral("...")); - tbSelectFile_->setFixedSize(30, 25); - - fileLayout->addWidget(pathLabel, 0, 0); - fileLayout->addWidget(leFilePath_, 0, 1); - fileLayout->addWidget(tbSelectFile_, 0, 2); - - mainLayout->addWidget(fileGroup); - - QGroupBox* infoGroup = new QGroupBox(QStringLiteral("File Information"), this); - QGridLayout* infoLayout = new QGridLayout(infoGroup); - - QLabel* nameLabel = new QLabel(QStringLiteral("File Name:"), this); - lblFileName_ = new QLabel(QStringLiteral("No file selected"), this); - QLabel* sizeLabel = new QLabel(QStringLiteral("File Size:"), this); - lblFileSize_ = new QLabel(QStringLiteral("0 bytes"), this); - - infoLayout->addWidget(nameLabel, 0, 0); - infoLayout->addWidget(lblFileName_, 0, 1); - infoLayout->addWidget(sizeLabel, 1, 0); - infoLayout->addWidget(lblFileSize_, 1, 1); - - mainLayout->addWidget(infoGroup); - - QGroupBox* descGroup = new QGroupBox(QStringLiteral("Description"), this); - QVBoxLayout* descLayout = new QVBoxLayout(descGroup); - teDescription_ = new QTextEdit(this); - teDescription_->setMaximumHeight(80); - descLayout->addWidget(teDescription_); - mainLayout->addWidget(descGroup); - -} - -void BaseAddFileDlg::initBaseConnect() { - connect(tbSelectFile_, &QToolButton::clicked, this, &BaseAddFileDlg::OnSelectFile); -} - void BaseAddFileDlg::OnSelectFile() { const QString workspacePath = Application::GetWorkSpacePath(); QString filePath = QFileDialog::getOpenFileName( this, - QStringLiteral("Select File"), - workspacePath, + getDialogTitle(), + QString(), getFileFilter() ); @@ -109,7 +47,6 @@ void BaseAddFileDlg::OnSelectFile() { } selectedFilePath_ = filePath; - leFilePath_->setText(filePath); updateFileInfo(filePath); LOG_INFO("Selected file: {}", filePath.toStdString()); @@ -123,22 +60,6 @@ void BaseAddFileDlg::OnSure() { accept(); } -void BaseAddFileDlg::updateFileInfo(const QString& filePath) { - QFileInfo fileInfo(filePath); - lblFileName_->setText(fileInfo.fileName()); - - qint64 size = fileInfo.size(); - QString sizeText; - if (size < 1024) { - sizeText = QString("%1 B").arg(size); - } else if (size < 1024 * 1024) { - sizeText = QString("%1 KB").arg(size / 1024.0, 0, 'f', 1); - } else { - sizeText = QString("%1 MB").arg(size / (1024.0 * 1024.0), 0, 'f', 1); - } - lblFileSize_->setText(sizeText); -} - bool BaseAddFileDlg::validateBaseInput() { if (selectedFilePath_.isEmpty()) { QMessageBox::warning(this, QStringLiteral("Warning"), diff --git a/src/ui/WorkSpace/BaseAddFileDlg.h b/src/ui/WorkSpace/BaseAddFileDlg.h index 4de55b03..b584e3e3 100644 --- a/src/ui/WorkSpace/BaseAddFileDlg.h +++ b/src/ui/WorkSpace/BaseAddFileDlg.h @@ -7,11 +7,6 @@ #include -class QLineEdit; -class QLabel; -class QTextEdit; -class QToolButton; - class BaseAddFileDlg : public Dialog { Q_OBJECT @@ -21,7 +16,7 @@ public: FileEntryType getSelectedFileType() const; QString getSelectedFilePath() const; - QString getDescription() const; + QString getDescription() const { return description_; } virtual bool validateSpecificParams() = 0; virtual QString getFileFilter() const = 0; @@ -32,21 +27,15 @@ protected slots: void OnSure(); protected: - QLineEdit* leFilePath_; - QToolButton* tbSelectFile_; - QLabel* lblFileName_; - QLabel* lblFileSize_; - QTextEdit* teDescription_; - - void setupBaseUI(); - void initBaseConnect(); - void updateFileInfo(const QString& filePath); bool validateBaseInput(); void SetTitle(const QString& title); - virtual void setupSpecificUI() = 0; + virtual void updateFileInfo(const QString& filePath) = 0; + +protected: + QString selectedFilePath_; + QString description_; private: FileEntryType fileType_; - QString selectedFilePath_; }; \ No newline at end of file diff --git a/src/workspace/FileEntry.cpp b/src/workspace/FileEntry.cpp new file mode 100644 index 00000000..e8334725 --- /dev/null +++ b/src/workspace/FileEntry.cpp @@ -0,0 +1,79 @@ +#include "workspace/FileEntry.h" + +#include + +#include "common/SpdLogger.h" + +void FileEntry::SetPath(const QString& path) { + QFileInfo fileInfo(path); + if (!fileInfo.exists()) { + LOG_WARN("file not exist: {}", path.toLocal8Bit().constData()); + return; + } + path_ = fileInfo.path(); + fileName_ = fileInfo.fileName(); +} + +// Factory function implementations +std::shared_ptr CreateFileEntry(FileEntryType type, const QString& filePath) { + switch (type) { + case FileEntryType::Curve: + return CreateFileEntryCurve(filePath); + case FileEntryType::Surface: + return CreateFileEntrySurface(filePath); + case FileEntryType::Table: + return CreateFileEntryTable(filePath); + case FileEntryType::Light: + return CreateFileEntryLight(filePath); + default: + LOG_ERROR("Unknown FileEntryType: {}", static_cast(type)); + return nullptr; + } +} + +std::shared_ptr CreateFileEntryCurve(const QString& filePath) { + QFileInfo fileInfo(filePath); + if (!fileInfo.exists()) { + LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData()); + return nullptr; + } + + auto fileEntry = std::make_shared(); + fileEntry->SetPath(filePath); + fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name + + return fileEntry; +} + +std::shared_ptr CreateFileEntrySurface(const QString& filePath) { + auto fileEntry = std::make_shared(); + fileEntry->SetType(FileEntryType::Surface); + + if (!filePath.isEmpty()) { + fileEntry->SetPath(filePath); + } + + return fileEntry; +} + +std::shared_ptr CreateFileEntryTable(const QString& filePath) { + auto fileEntry = std::make_shared(); + fileEntry->SetType(FileEntryType::Table); + + if (!filePath.isEmpty()) { + fileEntry->SetPath(filePath); + } + + return fileEntry; +} + +std::shared_ptr CreateFileEntryLight(const QString& filePath) { + auto fileEntry = std::make_shared(); + fileEntry->SetType(FileEntryType::Light); + + if (!filePath.isEmpty()) { + fileEntry->SetPath(filePath); + } + + return fileEntry; +} \ No newline at end of file diff --git a/src/workspace/FileEntry.h b/src/workspace/FileEntry.h index 51495ff6..5a63f5d5 100644 --- a/src/workspace/FileEntry.h +++ b/src/workspace/FileEntry.h @@ -1,6 +1,7 @@ #pragma once #include +#include enum class FileEntryType { Curve, @@ -9,11 +10,6 @@ enum class FileEntryType { Light }; -struct FileEntry { - FileEntryType type; - QString fileName; // relative file name under workspace dir; may be empty -}; - inline const char* FileEntryTypeToString(FileEntryType t) { switch (t) { case FileEntryType::Curve: return "curve"; @@ -31,4 +27,78 @@ inline bool FileEntryTypeFromString(const char* s, FileEntryType& out) { if (0 == strcmp(s, "table")) { out = FileEntryType::Table; return true; } if (0 == strcmp(s, "light")) { out = FileEntryType::Light; return true; } return false; -} \ No newline at end of file +} + +class FileEntryCurve; + +class FileEntry { +public: + virtual ~FileEntry() = default; + + FileEntryType GetType() const { return type_; } + void SetType(FileEntryType type) { type_ = type; } + + void SetPath(const QString& path); + QString GetPath() const { return path_; } + + void SetFileNanme(const QString& fileNmae) { fileName_ = fileNmae; } + const QString& GetFileName() const { return fileName_; } + + void SetName(const QString& name) { name_ = name; } + QString GetName() const { return name_; } + + virtual FileEntryCurve* AsCurve() { return nullptr; } + +protected: + FileEntryType type_; + QString path_; + QString fileName_; + QString name_; +}; + +// Factory functions for creating FileEntry objects +std::shared_ptr CreateFileEntry(FileEntryType type, const QString& filePath); +std::shared_ptr CreateFileEntryCurve(const QString& filePath); +std::shared_ptr CreateFileEntrySurface(const QString& filePath); +std::shared_ptr CreateFileEntryTable(const QString& filePath); +std::shared_ptr CreateFileEntryLight(const QString& filePath); + + +class FileEntryCurve : public FileEntry { +public: + struct ChartProperties { + int xCount; + QString xTitle; + QString yTitle; + double xMin; + double xMax; + double yMin; + double yMax; + double timeParam; + }; + + struct CurveProperty { + QString name; + QColor color; + int start; + int stop; + }; + + using CurveProperties = QList; + +public: + FileEntryCurve() { type_ = FileEntryType::Curve; } + + void SetChartProperties(const ChartProperties& props) { chartProperties_ = props; } + const ChartProperties& GetChartProperties() const { return chartProperties_; } + + void AddCurveProperty(const CurveProperty& prop) { curveProperties_.append(prop); } + void RemoveCurveProperty(int index) { curveProperties_.removeAt(index); } + const CurveProperties& GetCurveProperties() const { return curveProperties_; } + + FileEntryCurve* AsCurve() override { return this; } + +private: + ChartProperties chartProperties_; + CurveProperties curveProperties_; +}; diff --git a/src/workspace/WorkSpace.cpp b/src/workspace/WorkSpace.cpp index 7605814f..07c910e7 100644 --- a/src/workspace/WorkSpace.cpp +++ b/src/workspace/WorkSpace.cpp @@ -7,6 +7,7 @@ #include "workspace/WorkSpaceXMLParse.h" #include "workspace/WorkSpaceXMLWrite.h" #include "workspace/CommandManager.h" +#include "workspace/FileEntry.h" #include "workspace/WorkSpaceItem.h" #include "workspace/Timestep.h" @@ -118,7 +119,64 @@ void WorkSpace::SetRDPath(const QString& path) rdFile_ = fileInfo.fileName(); } -std::vector WorkSpace::GetFileEntries(FileEntryType type) const { +WorkSpace::FileEntryResult WorkSpace::SetFileEntry(std::shared_ptr fileEntry) { + if (!fileEntry) { + LOG_ERROR("FileEntry is null"); + return FileEntryResult::InvalidFile; + } + + FileEntryType type = fileEntry->GetType(); + auto& vec = files_[type]; + + // Check limit (max 9 per type) + if (vec.size() >= 9) { + LOG_WARN("File entry limit exceeded for type: {}", FileEntryTypeToString(type)); + return FileEntryResult::LimitExceeded; + } + + // Check for duplicates by file path + QString filePath = QString("%1/%2").arg(fileEntry->GetPath(), fileEntry->GetFileName()); + for (const auto& existingEntry : vec) { + 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 + fileEntry->SetFileNanme(fileInfo.fileName()); + + // Add to files collection + vec.push_back(fileEntry); + ++filesSeq_; + + emit FilesChanged(type); + LOG_INFO("Successfully added file entry: {} (type: {})", + fileInfo.fileName().toUtf8().constData(), + FileEntryTypeToString(type)); + + return FileEntryResult::Ok; +} +std::vector> WorkSpace::GetFileEntries(FileEntryType type) const { auto it = files_.find(type); if (it == files_.end()) { return {}; @@ -126,19 +184,6 @@ std::vector WorkSpace::GetFileEntries(FileEntryType type) const { return it->second; } -WorkSpace::FileEntryResult WorkSpace::CreateFileEntry(FileEntryType type) { - auto& vec = files_[type]; - if (vec.size() >= 9) { - return FileEntryResult::LimitExceeded; - } - // push a placeholder; actual filename may be set elsewhere via SetWavePath/SetRDPath/etc - vec.push_back(FileEntry{ type, QString() }); - ++filesSeq_; - // Notify listeners (e.g., PropertyBrowser) to refresh workspace properties - emit FilesChanged(type); - return FileEntryResult::Ok; -} - bool WorkSpace::SetFileEntryCount(FileEntryType type, int count) { if (count < 0) count = 0; if (count > 9) count = 9; @@ -149,7 +194,31 @@ bool WorkSpace::SetFileEntryCount(FileEntryType type, int count) { if (static_cast(vec.size()) < count) { int toAdd = count - static_cast(vec.size()); for (int i = 0; i < toAdd; ++i) { - vec.push_back(FileEntry{ type, QString() }); + // Create the appropriate FileEntry subclass based on type + std::shared_ptr fileEntry; + switch (type) { + case FileEntryType::Curve: + fileEntry = std::make_shared(); + break; + case FileEntryType::Surface: + // TODO: Create FileEntrySurface when implemented + fileEntry = std::make_shared(); + fileEntry->SetType(FileEntryType::Surface); + break; + case FileEntryType::Table: + // TODO: Create FileEntryTable when implemented + fileEntry = std::make_shared(); + fileEntry->SetType(FileEntryType::Table); + break; + case FileEntryType::Light: + // TODO: Create FileEntryLight when implemented + fileEntry = std::make_shared(); + fileEntry->SetType(FileEntryType::Light); + break; + default: + return false; // Invalid type + } + vec.push_back(fileEntry); } } else { vec.resize(count); @@ -159,30 +228,6 @@ bool WorkSpace::SetFileEntryCount(FileEntryType type, int count) { return true; } -bool WorkSpace::SetFileEntryPath(FileEntryType type, int index, const QString& path) { - auto& vec = files_[type]; - if (index < 0 || index >= static_cast(vec.size())) { - return false; - } - QFileInfo fileInfo(path); - if (!fileInfo.exists()) { - return false; - } - QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); - bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); - LOG_INFO("copy grouped file {}: {} to {}", - path.toLocal8Bit().data(), - dirPath.toLocal8Bit().data(), - sucess); - if (!sucess) { - return false; - } - vec[index].fileName = fileInfo.fileName(); - ++filesSeq_; - emit FilesChanged(type); - return true; -} - QString WorkSpace::GetFileEntryAbsPath(FileEntryType type, int index) const { auto it = files_.find(type); if (it == files_.end()) { @@ -192,7 +237,7 @@ QString WorkSpace::GetFileEntryAbsPath(FileEntryType type, int index) const { if (index < 0 || index >= static_cast(vec.size())) { return QString(); } - const QString& name = vec[index].fileName; + const QString& name = vec[index]->GetFileName(); if (name.isEmpty()) { return QString(); } diff --git a/src/workspace/WorkSpace.h b/src/workspace/WorkSpace.h index 30a3db3d..3a0396ae 100644 --- a/src/workspace/WorkSpace.h +++ b/src/workspace/WorkSpace.h @@ -81,13 +81,15 @@ public: const QString GetRDPath() const; // Files list API (per-type, max 9 per type) - enum class FileEntryResult { Ok, LimitExceeded, Duplicate, CopyFailed }; - FileEntryResult CreateFileEntry(FileEntryType type); - std::vector GetFileEntries(FileEntryType type) const; + enum class FileEntryResult { Ok, LimitExceeded, Duplicate, CopyFailed, TypeMismatch, InvalidFile }; + + // New unified file entry management + FileEntryResult SetFileEntry(std::shared_ptr fileEntry); + + std::vector> GetFileEntries(FileEntryType type) const; // Manage grouped file entries bool SetFileEntryCount(FileEntryType type, int count); - bool SetFileEntryPath(FileEntryType type, int index, const QString& path); QString GetFileEntryAbsPath(FileEntryType type, int index) const; // Chart data management @@ -154,7 +156,6 @@ Q_SIGNALS: void EntityRemoved(class Entity* entity); void TimestepChanged(class Timestep* timestep); void LampStatusChanged(class LampStatus* lampStatus); - // Emitted when grouped file entries change (count or path or creation) void FilesChanged(FileEntryType type); protected: @@ -184,7 +185,7 @@ private: class LampStatus* lampStatus_{ nullptr }; class Entity* trackedEntity_{ nullptr }; // Stored as file entries under workspace dir, keyed by type - std::map> files_; + std::map>> files_; // Chart data storage QList fileTypeData_; // Monotonic sequence for file entries changes, used to trigger UI refresh diff --git a/src/workspace/WorkSpaceXMLParse.cpp b/src/workspace/WorkSpaceXMLParse.cpp index b6614015..141139e4 100644 --- a/src/workspace/WorkSpaceXMLParse.cpp +++ b/src/workspace/WorkSpaceXMLParse.cpp @@ -379,9 +379,7 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) { // Also create file entries for backward compatibility FileEntryType enumType; if (FileEntryTypeFromString(name, enumType)) { - for (int i = 0; i < count; ++i) { - workSpace_->CreateFileEntry(enumType); - } + workSpace_->SetFileEntryCount(enumType, count); } } typeElement = typeElement->NextSiblingElement("type"); From 8c0f3454540314617989bf1c0b17a2dca2e92ac3 Mon Sep 17 00:00:00 2001 From: brige Date: Sun, 26 Oct 2025 16:44:23 +0800 Subject: [PATCH 2/3] modify light --- src/translations/Dyt_zh_CN.ts | 161 ++++------ src/ui/WorkSpace/AddLightFileDlg.cpp | 349 +++++++++++++++++++-- src/ui/WorkSpace/AddLightFileDlg.h | 59 +++- src/ui/WorkSpace/AddLightFileDlg.ui | 450 +++++++++++++-------------- src/workspace/FileEntry.cpp | 17 +- src/workspace/FileEntry.h | 36 ++- src/workspace/WorkSpace.cpp | 4 +- 7 files changed, 685 insertions(+), 391 deletions(-) diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index e3bf245a..3308cc7d 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -436,11 +436,6 @@ AddLightFileDlg - - - Add Light Spectrum File - - File Selection @@ -452,8 +447,13 @@ - - Select light spectrum file... + + Add Light Data File + + + + + Select light data file... @@ -479,144 +479,121 @@ - Spectrum Parameters + Color Properties - Wavelength Column: + Open Color: - - Intensity Column: + + + Select Color - - Separator: - - - - - Comma (,) + + background-color: rgb(0, 255, 0); border: 1px solid black; - Tab + Close Color: - - Space + + background-color: rgb(255, 0, 0); border: 1px solid black; - - Semicolon (;) + + Light Management - - Wavelength Unit: - - - - - nm (nanometer) - - - - - μm (micrometer) - - - - - cm⁻¹ (wavenumber) - - - - - eV (electron volt) - - - - - Intensity Unit: - - - - - Arbitrary Units - - - - - Counts - - - - - W/m²/nm - - - - - μW/cm²/nm - - - - - File has header row + + Lights: - Normalize intensity values + Add Light - Wavelength Range (Optional) + Remove - - Min Wavelength: + + Selected Light Properties - - Max Wavelength: + + Light Name: - - Enable wavelength range filtering + + Enter light name... - - Description (Optional) + + Light Index: - - Enter file description... - - - - + Add File - + Cancel + + + + Error + + + + + Unable to get current workspace + + + + + Curve file count has reached the limit (9 files) + + + + + File already exists + + + + + File copy failed + + + + + Invalid file + + + + + Failed to add file + + AddParamSetting diff --git a/src/ui/WorkSpace/AddLightFileDlg.cpp b/src/ui/WorkSpace/AddLightFileDlg.cpp index dd5b8b0a..4acd76b7 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.cpp +++ b/src/ui/WorkSpace/AddLightFileDlg.cpp @@ -1,28 +1,277 @@ #include "AddLightFileDlg.h" -#include +#include #include +#include +#include +#include + +#include "workspace/WorkSpace.h" +#include "workspace/WorkSpaceManager.h" #include "ui_AddLightFileDlg.h" AddLightFileDlg::AddLightFileDlg(QWidget* parent) : BaseAddFileDlg(FileEntryType::Light, parent) - , ui(new Ui::AddLightFileDlg) { + , ui(new Ui::AddLightFileDlg) + , currentLightIndex_(-1) + , openColor_(0, 255, 0) // Default to green color + , closeColor_(255, 0, 0) { // Default to red color - ui->setupUi(this); + SetupUI(ui); SetTitle(getDialogTitle()); + setupConnections(); + + // Initialize color properties + colorProperties_.openColor = openColor_; + colorProperties_.closeColor = closeColor_; + + // Update color previews + updateOpenColorPreview(openColor_); + updateCloseColorPreview(closeColor_); } AddLightFileDlg::~AddLightFileDlg() { delete ui; } -bool AddLightFileDlg::validateSpecificParams() { - LightParams params = getLightParams(); +void AddLightFileDlg::setupConnections() { + // File selection connections + connect(ui->selectFileBtn, &QToolButton::clicked, this, &AddLightFileDlg::OnSelectFile); - if (params.delimiter.isEmpty()) { - QMessageBox::warning(this, QStringLiteral("Warning"), - QStringLiteral("Please specify a delimiter for light data.")); + // Color selection connections + connect(ui->openColorButton, &QPushButton::clicked, this, &AddLightFileDlg::onOpenColorButtonClicked); + connect(ui->closeColorButton, &QPushButton::clicked, this, &AddLightFileDlg::onCloseColorButtonClicked); + + // Light management connections + connect(ui->addLightBtn, &QPushButton::clicked, this, &AddLightFileDlg::onAddLightClicked); + connect(ui->removeLightBtn, &QPushButton::clicked, this, &AddLightFileDlg::onRemoveLightClicked); + connect(ui->lightListWidget, &QListWidget::currentRowChanged, this, &AddLightFileDlg::onLightSelectionChanged); + connect(ui->lightListWidget, &QListWidget::itemClicked, this, &AddLightFileDlg::onLightListWidgetItemClicked); + + // Light properties connections + connect(ui->lightNameEdit, &QLineEdit::textChanged, this, &AddLightFileDlg::onLightNameChanged); + connect(ui->lightIndexSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &AddLightFileDlg::onLightIndexChanged); + + // Dialog buttons + connect(ui->addFileBtn, &QPushButton::clicked, this, &AddLightFileDlg::onSure); + connect(ui->cancelBtn, &QPushButton::clicked, this, &QDialog::reject); +} + +void AddLightFileDlg::updateFileInfo(const QString& filePath) { + QFileInfo fileInfo(filePath); + if (fileInfo.exists()) { + ui->fileNameValue->setText(fileInfo.fileName()); + qint64 size = fileInfo.size(); + QString sizeText; + if (size < 1024) { + sizeText = QString("%1 B").arg(size); + } + else if (size < 1024 * 1024) { + sizeText = QString("%1 KB").arg(size / 1024.0, 0, 'f', 1); + } + else { + sizeText = QString("%1 MB").arg(size / (1024.0 * 1024.0), 0, 'f', 1); + } + ui->fileSizeValue->setText(sizeText); + } else { + ui->fileNameValue->setText("-"); + ui->fileSizeValue->setText("-"); + } + + ui->filePathEdit->setText(filePath); +} + +void AddLightFileDlg::onOpenColorButtonClicked() { + QColor color = QColorDialog::getColor(openColor_, this, "Select Open Color"); + if (color.isValid()) { + openColor_ = color; + colorProperties_.openColor = color; + updateOpenColorPreview(color); + } +} + +void AddLightFileDlg::onCloseColorButtonClicked() { + QColor color = QColorDialog::getColor(closeColor_, this, "Select Close Color"); + if (color.isValid()) { + closeColor_ = color; + colorProperties_.closeColor = color; + updateCloseColorPreview(color); + } +} + +void AddLightFileDlg::onAddLightClicked() { + // Save current light properties if any light is selected + if (currentLightIndex_ >= 0) { + saveLightProperties(); + } + + // Create new light with default properties + FileEntryLight::LightProperty newLight; + newLight.name = generateLightName(); + newLight.index = lights_.size(); + + // Add to lights list + lights_.append(newLight); + + // Add to UI list widget + QListWidgetItem* item = new QListWidgetItem(QString("%1 [Index: %2]") + .arg(newLight.name) + .arg(newLight.index)); + ui->lightListWidget->addItem(item); + + // Select the new item + ui->lightListWidget->setCurrentRow(lights_.size() - 1); + currentLightIndex_ = lights_.size() - 1; + + // Enable properties editing + enableLightProperties(true); + updateLightProperties(); +} + +void AddLightFileDlg::onRemoveLightClicked() { + int currentRow = ui->lightListWidget->currentRow(); + if (currentRow >= 0 && currentRow < lights_.size()) { + // Remove from data + lights_.removeAt(currentRow); + + // Remove from UI + delete ui->lightListWidget->takeItem(currentRow); + + // Update current index + if (lights_.isEmpty()) { + currentLightIndex_ = -1; + enableLightProperties(false); + clearLightProperties(); + } else { + // Select next item or previous if at end + int newIndex = qMin(currentRow, lights_.size() - 1); + ui->lightListWidget->setCurrentRow(newIndex); + currentLightIndex_ = newIndex; + updateLightProperties(); + } + + // Update list display with new indices + for (int i = 0; i < lights_.size(); ++i) { + lights_[i].index = i; + QListWidgetItem* item = ui->lightListWidget->item(i); + if (item) { + item->setText(QString("%1 [Index: %2]") + .arg(lights_[i].name) + .arg(lights_[i].index)); + } + } + } +} + +void AddLightFileDlg::onLightListWidgetItemClicked(QListWidgetItem* item) { + Q_UNUSED(item) + onLightSelectionChanged(); +} + +void AddLightFileDlg::onLightSelectionChanged() { + int currentRow = ui->lightListWidget->currentRow(); + if (currentRow >= 0 && currentRow < lights_.size()) { + // Save previous light properties + if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) { + saveLightProperties(); + } + + currentLightIndex_ = currentRow; + enableLightProperties(true); + updateLightProperties(); + } else { + currentLightIndex_ = -1; + enableLightProperties(false); + clearLightProperties(); + } +} + +void AddLightFileDlg::onLightNameChanged() { + if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) { + QString newName = ui->lightNameEdit->text(); + lights_[currentLightIndex_].name = newName; + + // Update list widget item text + QListWidgetItem* item = ui->lightListWidget->item(currentLightIndex_); + if (item) { + item->setText(QString("%1 [Index: %2]") + .arg(newName) + .arg(lights_[currentLightIndex_].index)); + } + } +} + +void AddLightFileDlg::onLightIndexChanged() { + if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) { + int newIndex = ui->lightIndexSpinBox->value(); + lights_[currentLightIndex_].index = newIndex; + + // Update list widget item text + QListWidgetItem* item = ui->lightListWidget->item(currentLightIndex_); + if (item) { + item->setText(QString("%1 [Index: %2]") + .arg(lights_[currentLightIndex_].name) + .arg(newIndex)); + } + } +} + +void AddLightFileDlg::updateOpenColorPreview(const QColor& color) { + QString styleSheet = QString("background-color: rgb(%1, %2, %3); border: 1px solid black;") + .arg(color.red()) + .arg(color.green()) + .arg(color.blue()); + ui->openColorPreview->setStyleSheet(styleSheet); +} + +void AddLightFileDlg::updateCloseColorPreview(const QColor& color) { + QString styleSheet = QString("background-color: rgb(%1, %2, %3); border: 1px solid black;") + .arg(color.red()) + .arg(color.green()) + .arg(color.blue()); + ui->closeColorPreview->setStyleSheet(styleSheet); +} + +void AddLightFileDlg::addLightToList(const FileEntryLight::LightProperty& light) { + QListWidgetItem* item = new QListWidgetItem(QString("%1 [Index: %2]") + .arg(light.name) + .arg(light.index)); + ui->lightListWidget->addItem(item); +} + +void AddLightFileDlg::updateLightProperties() { + if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) { + const FileEntryLight::LightProperty& light = lights_[currentLightIndex_]; + ui->lightNameEdit->setText(light.name); + ui->lightIndexSpinBox->setValue(light.index); + } +} + +void AddLightFileDlg::saveLightProperties() { + if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) { + lights_[currentLightIndex_].name = ui->lightNameEdit->text(); + lights_[currentLightIndex_].index = ui->lightIndexSpinBox->value(); + } +} + +void AddLightFileDlg::clearLightProperties() { + ui->lightNameEdit->clear(); + ui->lightIndexSpinBox->setValue(0); +} + +void AddLightFileDlg::enableLightProperties(bool enabled) { + ui->lightPropertiesGroupBox->setEnabled(enabled); +} + +QString AddLightFileDlg::generateLightName() { + return QString("Light %1").arg(lights_.size() + 1); +} + +bool AddLightFileDlg::validateSpecificParams() { + // Check if at least one light is defined + if (lights_.isEmpty()) { + QMessageBox::warning(this, "Validation Error", "At least one light must be defined."); return false; } @@ -30,37 +279,69 @@ bool AddLightFileDlg::validateSpecificParams() { } QString AddLightFileDlg::getFileFilter() const { - return QStringLiteral("Light Spectrum Files (*.txt *.csv *.dat *.spe *.asc);;All Files (*.*)"); + return "Light Data Files (*.txt *.csv *.dat);;All Files (*.*)"; } QString AddLightFileDlg::getDialogTitle() const { - return QStringLiteral("Add Light Spectrum File"); + return "Add Light Data File"; } -void AddLightFileDlg::onDelimiterChanged() { - // Handle delimiter change if needed -} - -void AddLightFileDlg::onHeaderToggled(bool hasHeader) { - // Handle header toggle if needed -} - -AddLightFileDlg::LightParams AddLightFileDlg::getLightParams() const { - LightParams params; - params.wavelengthColumn = ui->wavelengthColumnSpinBox->value(); - params.intensityColumn = ui->intensityColumnSpinBox->value(); - - // Get delimiter from combo box - int index = ui->separatorComboBox->currentIndex(); - switch (index) { - case 0: params.delimiter = ","; break; - case 1: params.delimiter = "\t"; break; - case 2: params.delimiter = " "; break; - case 3: params.delimiter = ";"; break; - default: params.delimiter = ","; break; +void AddLightFileDlg::onSure() { + // Save current light properties if any light is selected + if (currentLightIndex_ >= 0) { + saveLightProperties(); } - params.hasHeader = ui->hasHeaderCheckBox->isChecked(); - params.description = ui->descriptionEdit->toPlainText().trimmed(); - return params; + if (!validateSpecificParams()) { + return; + } + + // Get current workspace + WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent(); + if (!workspace) { + QMessageBox::warning(this, tr("Error"), tr("Unable to get current workspace")); + return; + } + + + // Create FileEntryLight and set properties + auto lightEntry = CreateFileEntryLight(getSelectedFilePath()); + if (lightEntry) { + // Set color properties + lightEntry->SetColorProperties(colorProperties_); + + // Add all light properties + for (const auto& light : lights_) { + lightEntry->AddLightProperty(light); + } + + // Add to workspace + auto result = workspace->SetFileEntry(lightEntry); + if (result != WorkSpace::FileEntryResult::Ok) { + QString errorMsg; + switch (result) { + case WorkSpace::FileEntryResult::LimitExceeded: + errorMsg = tr("Curve file count has reached the limit (9 files)"); + break; + case WorkSpace::FileEntryResult::Duplicate: + errorMsg = tr("File already exists"); + break; + case WorkSpace::FileEntryResult::CopyFailed: + errorMsg = tr("File copy failed"); + break; + case WorkSpace::FileEntryResult::InvalidFile: + errorMsg = tr("Invalid file"); + break; + default: + errorMsg = tr("Failed to add file"); + break; + } + QMessageBox::warning(this, tr("Error"), errorMsg); + return; + } + + accept(); + } else { + QMessageBox::critical(this, "Error", "Failed to create light file entry."); + } } \ No newline at end of file diff --git a/src/ui/WorkSpace/AddLightFileDlg.h b/src/ui/WorkSpace/AddLightFileDlg.h index f5a6ba30..d0cd3d44 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.h +++ b/src/ui/WorkSpace/AddLightFileDlg.h @@ -1,39 +1,66 @@ #pragma once +#include "BaseAddFileDlg.h" +#include "workspace/FileEntry.h" +#include +#include +#include + +class QLineEdit; +class QCheckBox; +class QSpinBox; +class QDoubleSpinBox; +class QTextEdit; +class QToolButton; +class QLabel; +class QPushButton; +class QListWidget; +class QListWidgetItem; + namespace Ui { class AddLightFileDlg; } -#include "BaseAddFileDlg.h" - - class AddLightFileDlg : public BaseAddFileDlg { Q_OBJECT public: - struct LightParams { - QString delimiter; - bool hasHeader; - int wavelengthColumn; - int intensityColumn; - QString description; - }; - explicit AddLightFileDlg(QWidget* parent = nullptr); ~AddLightFileDlg() override; - LightParams getLightParams() const; - protected: QString getFileFilter() const override; QString getDialogTitle() const override; bool validateSpecificParams() override; - void updateFileInfo(const QString& filePath) override {} + void updateFileInfo(const QString& filePath) override; private slots: - void onDelimiterChanged(); - void onHeaderToggled(bool hasHeader); + void onOpenColorButtonClicked(); + void onCloseColorButtonClicked(); + void onAddLightClicked(); + void onRemoveLightClicked(); + void onLightListWidgetItemClicked(QListWidgetItem* item); + void onLightSelectionChanged(); + void onLightNameChanged(); + void onLightIndexChanged(); + void onSure(); private: + void setupConnections(); + void updateOpenColorPreview(const QColor& color); + void updateCloseColorPreview(const QColor& color); + void addLightToList(const FileEntryLight::LightProperty& light); + void updateLightProperties(); + void saveLightProperties(); + void clearLightProperties(); + void enableLightProperties(bool enabled); + QString generateLightName(); + Ui::AddLightFileDlg* ui; + int currentLightIndex_; + QColor openColor_; + QColor closeColor_; + + FileEntryLight::ColorProperties colorProperties_; + FileEntryLight::LightProperties lights_; }; \ No newline at end of file diff --git a/src/ui/WorkSpace/AddLightFileDlg.ui b/src/ui/WorkSpace/AddLightFileDlg.ui index 9e10051a..c302c410 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.ui +++ b/src/ui/WorkSpace/AddLightFileDlg.ui @@ -6,12 +6,12 @@ 0 0 - 500 - 480 + 600 + 487 - Add Light Spectrum File + Add Light Data File @@ -29,12 +29,12 @@ - - Select light spectrum file... - true + + Select light data file... + @@ -76,265 +76,242 @@ - + - Spectrum Parameters + Color Properties - + - + - Wavelength Column: + Open Color: - - - 1 - - - 100 - - - 1 - - + + + + + + 100 + 16777215 + + + + Select Color + + + + + + + + 50 + 25 + + + + background-color: rgb(0, 255, 0); border: 1px solid black; + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - + - Intensity Column: + Close Color: - - - 1 - - - 100 - - - 2 - - + + + + + + 100 + 16777215 + + + + Select Color + + + + + + + + 50 + 25 + + + + background-color: rgb(255, 0, 0); border: 1px solid black; + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - - Separator: + + + + + + + Light Management + + + + + + + + Lights: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 80 + 16777215 + + + + Add Light + + + + + + + + 60 + 16777215 + + + + Remove + + + + + + + + + + 16777215 + 120 + - - - - - - - Comma (,) - - - - - Tab - - - - - Space - - - - - Semicolon (;) - - - - - - - - Wavelength Unit: - - - - - - - - nm (nanometer) - - - - - μm (micrometer) - - - - - cm⁻¹ (wavenumber) - - - - - eV (electron volt) - - - - - - - - Intensity Unit: - - - - - - - - Arbitrary Units - - - - - Counts - - - - - W/m²/nm - - - - - μW/cm²/nm - - - - - - - - File has header row - - + true - - - - Normalize intensity values - - - false - - - - - - - - - - Wavelength Range (Optional) - - - - - - Min Wavelength: - - - - - - - 0.000000000000000 - - - 10000.000000000000000 - - - 380.000000000000000 - - - - - - - Max Wavelength: - - - - - - - 0.000000000000000 - - - 10000.000000000000000 - - - 780.000000000000000 - - - - - - - Enable wavelength range filtering - - - false - - - - - - - - - - Description (Optional) - - - - - - 16777215 - 60 - + + + false - - Enter file description... + + Selected Light Properties + + + + + Light Name: + + + + + + + Enter light name... + + + + + + + Light Index: + + + + + + + 0 + + + 999999 + + + 0 + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Qt::Horizontal @@ -347,13 +324,10 @@ - + Add File - - true - @@ -369,4 +343,4 @@ - \ No newline at end of file + diff --git a/src/workspace/FileEntry.cpp b/src/workspace/FileEntry.cpp index e8334725..706f8131 100644 --- a/src/workspace/FileEntry.cpp +++ b/src/workspace/FileEntry.cpp @@ -67,13 +67,16 @@ std::shared_ptr CreateFileEntryTable(const QString& filePath) { return fileEntry; } -std::shared_ptr CreateFileEntryLight(const QString& filePath) { - auto fileEntry = std::make_shared(); - fileEntry->SetType(FileEntryType::Light); - - if (!filePath.isEmpty()) { - fileEntry->SetPath(filePath); +std::shared_ptr CreateFileEntryLight(const QString& filePath) { + QFileInfo fileInfo(filePath); + if (!fileInfo.exists()) { + LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData()); + return nullptr; } - + + auto fileEntry = std::make_shared(); + fileEntry->SetPath(filePath); + fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name + return fileEntry; } \ No newline at end of file diff --git a/src/workspace/FileEntry.h b/src/workspace/FileEntry.h index 5a63f5d5..33cf4326 100644 --- a/src/workspace/FileEntry.h +++ b/src/workspace/FileEntry.h @@ -30,6 +30,7 @@ inline bool FileEntryTypeFromString(const char* s, FileEntryType& out) { } class FileEntryCurve; +class FileEntryLight; class FileEntry { public: @@ -48,6 +49,7 @@ public: QString GetName() const { return name_; } virtual FileEntryCurve* AsCurve() { return nullptr; } + virtual FileEntryLight* AsLight() { return nullptr; } protected: FileEntryType type_; @@ -61,7 +63,7 @@ std::shared_ptr CreateFileEntry(FileEntryType type, const QString& fi std::shared_ptr CreateFileEntryCurve(const QString& filePath); std::shared_ptr CreateFileEntrySurface(const QString& filePath); std::shared_ptr CreateFileEntryTable(const QString& filePath); -std::shared_ptr CreateFileEntryLight(const QString& filePath); +std::shared_ptr CreateFileEntryLight(const QString& filePath); class FileEntryCurve : public FileEntry { @@ -102,3 +104,35 @@ private: ChartProperties chartProperties_; CurveProperties curveProperties_; }; + +class FileEntryLight : public FileEntry { +public: + struct ColorProperties { + QColor openColor; + QColor closeColor; + }; + + struct LightProperty { + QString name; + int index; + }; + + using LightProperties = QList; + +public: + FileEntryLight() { type_ = FileEntryType::Light; } + + void SetColorProperties(const ColorProperties& props) { colorProperties_ = props; } + const ColorProperties& GetColorProperties() const { return colorProperties_; } + + void AddLightProperty(const LightProperty& prop) { lightProperties_.append(prop); } + void RemoveLightProperty(int index) { lightProperties_.removeAt(index); } + const LightProperties& GetLightProperties() const { return lightProperties_; } + + FileEntryLight* AsLight() override { return this; } + +private: + ColorProperties colorProperties_; + LightProperties lightProperties_; +}; + diff --git a/src/workspace/WorkSpace.cpp b/src/workspace/WorkSpace.cpp index 07c910e7..8a9990fd 100644 --- a/src/workspace/WorkSpace.cpp +++ b/src/workspace/WorkSpace.cpp @@ -211,9 +211,7 @@ bool WorkSpace::SetFileEntryCount(FileEntryType type, int count) { fileEntry->SetType(FileEntryType::Table); break; case FileEntryType::Light: - // TODO: Create FileEntryLight when implemented - fileEntry = std::make_shared(); - fileEntry->SetType(FileEntryType::Light); + fileEntry = std::make_shared(); break; default: return false; // Invalid type From 1e7538796a35eb5a6bef3bdddca14547cb33b052 Mon Sep 17 00:00:00 2001 From: brige Date: Sun, 26 Oct 2025 17:48:34 +0800 Subject: [PATCH 3/3] modify AddSurfaceFileDlg --- .gitignore | 1 + src/translations/Dyt_zh_CN.ts | 224 +++++++--- src/ui/WorkSpace/AddSurfaceFileDlg.cpp | 485 +++++++++++++++----- src/ui/WorkSpace/AddSurfaceFileDlg.h | 72 ++- src/ui/WorkSpace/AddSurfaceFileDlg.ui | 585 ++++++++++++++++++------- src/workspace/FileEntry.cpp | 54 ++- src/workspace/FileEntry.h | 62 ++- 7 files changed, 1148 insertions(+), 335 deletions(-) diff --git a/.gitignore b/.gitignore index 5ae90f68..8d70c6c4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ build/ bin/ thirdparty/ tritoin/ +CMakeFiles/ QWEN.md diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index 3308cc7d..6e9c6e2e 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -683,11 +683,6 @@ AddSurfaceFileDlg - - - Add Surface Data File - - File Selection @@ -695,113 +690,242 @@ - File Path: - - - - Select surface data file... + + + Add Surface File + + + + + Browse... + + - ... + Chart Properties - - File Name: + + X Axis Title: - - - - + + Y Axis Title: - - File Size: + + Z Axis Title: - - Surface Parameters + + Time Parameter: - + + X Range: + + + + + + + to + + + + + X Count: + + + + + Y Range: + + + + + Y Count: + + + + + Z Range: + + + + + Z Count: + + + + + Surface Management + + + + + Add Surface + + + + + Remove + + + + + Surface Properties + + + + + Name: + + + + + Color: + + + + + Select Color + + + + + Start Point: + + + + + End Point: + + + + + Data Format Parameters + + + + X Column: - + Y Column: - + Z Column: - + Separator: - - Comma (,) + + , - - Tab + + Has Header Row - - Space - - - - - Semicolon (;) - - - - + X Grid Size: - + Y Grid Size: - - File has header row + + Select Surface Data File - - Description (Optional) + + Please add at least one surface. - - Enter file description... + + Surface Data Files (*.txt *.dat *.csv);;All Files (*.*) - - Add File + + + Warning - - Cancel + + Please fill in all axis titles. + + + + + Select Surface Color + + + + + + + Error + + + + + Failed to create surface file entry. + + + + + Unable to get current workspace + + + + + Surface file count has reached the limit (9 files) + + + + + File already exists + + + + + File copy failed + + + + + Invalid file + + + + + Failed to add file diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.cpp b/src/ui/WorkSpace/AddSurfaceFileDlg.cpp index c924087f..c95b6e4d 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.cpp +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.cpp @@ -1,135 +1,414 @@ #include "AddSurfaceFileDlg.h" - -#include -#include -#include -#include "app/Application.h" +#include "ui_AddSurfaceFileDlg.h" +#include "workspace/WorkSpaceManager.h" +#include "workspace/WorkSpace.h" #include "common/SpdLogger.h" -#include "ui_AddSurfaceFileDlg.h" +#include +#include +#include +#include +#include +#include +#include -AddSurfaceFileDlg::AddSurfaceFileDlg(QWidget* parent) +AddSurfaceFileDlg::AddSurfaceFileDlg(QWidget *parent) : BaseAddFileDlg(FileEntryType::Surface, parent) - , ui_(new Ui::AddSurfaceFileDlg) { - - ui_->setupUi(this); + , ui(new Ui::AddSurfaceFileDlg) + , currentSurfaceIndex_(-1) + , selectedColor_(Qt::blue) +{ + SetupUI(ui); SetTitle(getDialogTitle()); setupConnections(); -} - -AddSurfaceFileDlg::~AddSurfaceFileDlg() { - delete ui_; -} - -void AddSurfaceFileDlg::setupConnections() { - connect(ui_->selectFileBtn, &QToolButton::clicked, this, &AddSurfaceFileDlg::onSelectFileClicked); - connect(ui_->filePathEdit, &QLineEdit::textChanged, this, &AddSurfaceFileDlg::onFilePathChanged); - connect(ui_->addBtn, &QPushButton::clicked, this, [this]() { OnSure(); }); - connect(ui_->cancelBtn, &QPushButton::clicked, this, &QDialog::reject); -} - -void AddSurfaceFileDlg::onSelectFileClicked() { - const QString workspacePath = Application::GetWorkSpacePath(); - QString filePath = QFileDialog::getOpenFileName( - this, - QStringLiteral("Select Surface Data File"), - workspacePath, - getFileFilter() - ); - if (filePath.isEmpty()) { - return; - } + // Initialize chart properties with default values + chartProperties_.xCount = 100; + chartProperties_.yCount = 100; + chartProperties_.zCount = 100; + chartProperties_.xMin = 0.0; + chartProperties_.xMax = 1.0; + chartProperties_.yMin = 0.0; + chartProperties_.yMax = 1.0; + chartProperties_.zMin = 0.0; + chartProperties_.zMax = 1.0; + chartProperties_.timeParam = 0.0; + chartProperties_.xTitle = "X Axis"; + chartProperties_.yTitle = "Y Axis"; + chartProperties_.zTitle = "Z Axis"; - ui_->filePathEdit->setText(filePath); - updateFileInfo(filePath); + // Set default UI values + ui->xCountSpinBox->setValue(chartProperties_.xCount); + ui->yCountSpinBox->setValue(chartProperties_.yCount); + ui->zCountSpinBox->setValue(chartProperties_.zCount); + ui->xMinSpinBox->setValue(chartProperties_.xMin); + ui->xMaxSpinBox->setValue(chartProperties_.xMax); + ui->yMinSpinBox->setValue(chartProperties_.yMin); + ui->yMaxSpinBox->setValue(chartProperties_.yMax); + ui->zMinSpinBox->setValue(chartProperties_.zMin); + ui->zMaxSpinBox->setValue(chartProperties_.zMax); + ui->timeParamSpinBox->setValue(chartProperties_.timeParam); + ui->xTitleLineEdit->setText(chartProperties_.xTitle); + ui->yTitleLineEdit->setText(chartProperties_.yTitle); + ui->zTitleLineEdit->setText(chartProperties_.zTitle); - LOG_INFO("Selected surface file: {}", filePath.toStdString()); + // Initialize color preview + updateColorPreview(ui->surfaceColorButton, selectedColor_); + + // Clear surface properties initially + clearSurfaceProperties(); } -void AddSurfaceFileDlg::onFilePathChanged() { - QString filePath = ui_->filePathEdit->text(); - if (!filePath.isEmpty()) { - updateFileInfo(filePath); - } +AddSurfaceFileDlg::~AddSurfaceFileDlg() +{ + delete ui; } -void AddSurfaceFileDlg::updateFileInfo(const QString& filePath) { - QFileInfo fileInfo(filePath); - ui_->fileNameValue->setText(fileInfo.fileName()); +void AddSurfaceFileDlg::setupConnections() +{ + // File selection connections + connect(ui->browseButton, &QPushButton::clicked, this, &AddSurfaceFileDlg::onSelectFile); + connect(ui->filePathLineEdit, &QLineEdit::textChanged, this, &AddSurfaceFileDlg::onFilePathChanged); - qint64 size = fileInfo.size(); - QString sizeText; - if (size < 1024) { - sizeText = QString("%1 B").arg(size); - } else if (size < 1024 * 1024) { - sizeText = QString("%1 KB").arg(size / 1024.0, 0, 'f', 1); - } else { - sizeText = QString("%1 MB").arg(size / (1024.0 * 1024.0), 0, 'f', 1); - } - ui_->fileSizeValue->setText(sizeText); + // Surface management connections + connect(ui->surfaceColorButton, &QPushButton::clicked, this, &AddSurfaceFileDlg::onSurfaceColorButtonClicked); + connect(ui->addSurfaceButton, &QPushButton::clicked, this, &AddSurfaceFileDlg::onAddSurfaceClicked); + connect(ui->removeSurfaceButton, &QPushButton::clicked, this, &AddSurfaceFileDlg::onRemoveSurfaceClicked); + connect(ui->surfaceListWidget, &QListWidget::itemClicked, this, &AddSurfaceFileDlg::onSurfaceListItemClicked); + connect(ui->surfaceListWidget, &QListWidget::itemSelectionChanged, this, &AddSurfaceFileDlg::onSurfaceSelectionChanged); + + // Surface properties connections + connect(ui->surfaceNameLineEdit, &QLineEdit::textChanged, this, &AddSurfaceFileDlg::onSurfaceNameChanged); + connect(ui->surfaceStartSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &AddSurfaceFileDlg::onSurfaceDataChanged); + connect(ui->surfaceStopSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &AddSurfaceFileDlg::onSurfaceDataChanged); + + // Chart properties connections (save to member variables when changed) + connect(ui->xCountSpinBox, QOverload::of(&QSpinBox::valueChanged), [this](int value) { chartProperties_.xCount = value; }); + connect(ui->yCountSpinBox, QOverload::of(&QSpinBox::valueChanged), [this](int value) { chartProperties_.yCount = value; }); + connect(ui->zCountSpinBox, QOverload::of(&QSpinBox::valueChanged), [this](int value) { chartProperties_.zCount = value; }); + connect(ui->xMinSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.xMin = value; }); + connect(ui->xMaxSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.xMax = value; }); + connect(ui->yMinSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.yMin = value; }); + connect(ui->yMaxSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.yMax = value; }); + connect(ui->zMinSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.zMin = value; }); + connect(ui->zMaxSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.zMax = value; }); + connect(ui->timeParamSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double value) { chartProperties_.timeParam = value; }); + connect(ui->xTitleLineEdit, &QLineEdit::textChanged, [this](const QString& text) { chartProperties_.xTitle = text; }); + connect(ui->yTitleLineEdit, &QLineEdit::textChanged, [this](const QString& text) { chartProperties_.yTitle = text; }); + connect(ui->zTitleLineEdit, &QLineEdit::textChanged, [this](const QString& text) { chartProperties_.zTitle = text; }); + + // Dialog button connections + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &AddSurfaceFileDlg::accept); + connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &AddSurfaceFileDlg::reject); } -bool AddSurfaceFileDlg::validateSpecificParams() { - if (ui_->filePathEdit->text().isEmpty()) { - QMessageBox::warning(this, QStringLiteral("Warning"), - QStringLiteral("Please select a surface data file.")); +QString AddSurfaceFileDlg::getFileFilter() const +{ + return tr("Surface Data Files (*.txt *.dat *.csv);;All Files (*.*)"); +} + +QString AddSurfaceFileDlg::getDialogTitle() const +{ + return tr("Select Surface Data File"); +} + +bool AddSurfaceFileDlg::validateSpecificParams() +{ + if (surfaces_.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), tr("Please add at least one surface.")); return false; } - QFileInfo fileInfo(ui_->filePathEdit->text()); - if (!fileInfo.exists()) { - QMessageBox::warning(this, QStringLiteral("Warning"), - QStringLiteral("The selected file does not exist.")); - return false; - } - - if (ui_->xColumnSpinBox->value() == ui_->yColumnSpinBox->value() || - ui_->xColumnSpinBox->value() == ui_->zColumnSpinBox->value() || - ui_->yColumnSpinBox->value() == ui_->zColumnSpinBox->value()) { - QMessageBox::warning(this, QStringLiteral("Warning"), - QStringLiteral("X, Y, and Z columns must be different.")); + // Validate chart properties + if (chartProperties_.xTitle.isEmpty() || chartProperties_.yTitle.isEmpty() || chartProperties_.zTitle.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), tr("Please fill in all axis titles.")); return false; } return true; } -QString AddSurfaceFileDlg::getFileFilter() const { - return QStringLiteral("Surface Data Files (*.txt *.csv *.dat *.xyz);;All Files (*.*)"); +void AddSurfaceFileDlg::updateFileInfo(const QString& filePath) +{ + ui->filePathLineEdit->setText(filePath); } -QString AddSurfaceFileDlg::getDialogTitle() const { - return QStringLiteral("Add Surface Data File"); -} - -QString AddSurfaceFileDlg::getSelectedFilePath() const { - return ui_->filePathEdit->text(); -} - -QString AddSurfaceFileDlg::getDescription() const { - return ui_->descriptionEdit->toPlainText().trimmed(); -} - -AddSurfaceFileDlg::SurfaceParams AddSurfaceFileDlg::getSurfaceParams() const { - SurfaceParams params; - params.xColumn = ui_->xColumnSpinBox->value(); - params.yColumn = ui_->yColumnSpinBox->value(); - params.zColumn = ui_->zColumnSpinBox->value(); - params.xGridSize = ui_->xGridSizeSpinBox->value(); - params.yGridSize = ui_->yGridSizeSpinBox->value(); - params.hasHeader = ui_->hasHeaderCheckBox->isChecked(); - params.description = ui_->descriptionEdit->toPlainText().trimmed(); +void AddSurfaceFileDlg::onSelectFile() +{ + QString documentsPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + QString fileName = QFileDialog::getOpenFileName(this, getDialogTitle(), documentsPath, getFileFilter()); - // Get delimiter from combo box - int index = ui_->separatorComboBox->currentIndex(); - switch (index) { - case 0: params.delimiter = ","; break; - case 1: params.delimiter = "\t"; break; - case 2: params.delimiter = " "; break; - case 3: params.delimiter = ";"; break; - default: params.delimiter = ","; break; + if (!fileName.isEmpty()) { + updateFileInfo(fileName); + } +} + +void AddSurfaceFileDlg::onFilePathChanged() +{ + // File path changed, could update preview or validation here +} + +void AddSurfaceFileDlg::onSurfaceColorButtonClicked() +{ + QColor color = QColorDialog::getColor(selectedColor_, this, tr("Select Surface Color")); + if (color.isValid()) { + selectedColor_ = color; + updateColorPreview(ui->surfaceColorButton, selectedColor_); + + // Update current surface color if one is selected + if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) { + surfaces_[currentSurfaceIndex_].color = selectedColor_; + + // Update list item color + QListWidgetItem* item = ui->surfaceListWidget->item(currentSurfaceIndex_); + if (item) { + QPixmap pixmap(16, 16); + pixmap.fill(selectedColor_); + item->setIcon(QIcon(pixmap)); + } + } + } +} + +void AddSurfaceFileDlg::onAddSurfaceClicked() +{ + FileEntrySurface::SurfaceProperty surface; + surface.name = generateSurfaceName(); + surface.color = generateSurfaceColor(); + surface.start = 0; + surface.stop = 1000; + surface.x = QString::number(ui->xColumnSpinBox->value()); + surface.y = QString::number(ui->yColumnSpinBox->value()); + surface.z = QString::number(ui->zColumnSpinBox->value()); + + surfaces_.append(surface); + addSurfaceToList(surface); + + // Select the newly added surface + ui->surfaceListWidget->setCurrentRow(surfaces_.size() - 1); +} + +void AddSurfaceFileDlg::onRemoveSurfaceClicked() +{ + int currentRow = ui->surfaceListWidget->currentRow(); + if (currentRow >= 0 && currentRow < surfaces_.size()) { + surfaces_.removeAt(currentRow); + delete ui->surfaceListWidget->takeItem(currentRow); + + // Update current surface index + if (currentRow < surfaces_.size()) { + ui->surfaceListWidget->setCurrentRow(currentRow); + } else if (surfaces_.size() > 0) { + ui->surfaceListWidget->setCurrentRow(surfaces_.size() - 1); + } else { + currentSurfaceIndex_ = -1; + clearSurfaceProperties(); + } + } +} + +void AddSurfaceFileDlg::onSurfaceListItemClicked(QListWidgetItem* item) +{ + int row = ui->surfaceListWidget->row(item); + if (row >= 0 && row < surfaces_.size()) { + saveSurfaceProperties(); // Save current surface properties + currentSurfaceIndex_ = row; + updateSurfaceProperties(); // Load new surface properties + } +} + +void AddSurfaceFileDlg::onSurfaceSelectionChanged() +{ + int currentRow = ui->surfaceListWidget->currentRow(); + if (currentRow >= 0 && currentRow < surfaces_.size()) { + saveSurfaceProperties(); // Save current surface properties + currentSurfaceIndex_ = currentRow; + updateSurfaceProperties(); // Load new surface properties + } else { + currentSurfaceIndex_ = -1; + clearSurfaceProperties(); + } +} + +void AddSurfaceFileDlg::onSurfaceNameChanged() +{ + if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) { + QString newName = ui->surfaceNameLineEdit->text(); + surfaces_[currentSurfaceIndex_].name = newName; + + // Update list item text + QListWidgetItem* item = ui->surfaceListWidget->item(currentSurfaceIndex_); + if (item) { + item->setText(newName); + } + } +} + +void AddSurfaceFileDlg::onSurfaceDataChanged() +{ + if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) { + surfaces_[currentSurfaceIndex_].start = ui->surfaceStartSpinBox->value(); + surfaces_[currentSurfaceIndex_].stop = ui->surfaceStopSpinBox->value(); + } +} + +void AddSurfaceFileDlg::updateColorPreview(QPushButton* button, const QColor& color) +{ + if (button && color.isValid()) { + QString styleSheet = QString("QPushButton { background-color: %1; }").arg(color.name()); + button->setStyleSheet(styleSheet); + } +} + +void AddSurfaceFileDlg::addSurfaceToList(const FileEntrySurface::SurfaceProperty& surface) +{ + QListWidgetItem* item = new QListWidgetItem(surface.name); + + // Set color icon + QPixmap pixmap(16, 16); + pixmap.fill(surface.color); + item->setIcon(QIcon(pixmap)); + + ui->surfaceListWidget->addItem(item); +} + +void AddSurfaceFileDlg::updateSurfaceProperties() +{ + if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) { + const auto& surface = surfaces_[currentSurfaceIndex_]; + + ui->surfaceNameLineEdit->setText(surface.name); + ui->surfaceStartSpinBox->setValue(surface.start); + ui->surfaceStopSpinBox->setValue(surface.stop); + + selectedColor_ = surface.color; + updateColorPreview(ui->surfaceColorButton, selectedColor_); + + ui->surfacePropertiesGroupBox->setEnabled(true); + } else { + clearSurfaceProperties(); + } +} + +void AddSurfaceFileDlg::saveSurfaceProperties() +{ + if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) { + surfaces_[currentSurfaceIndex_].name = ui->surfaceNameLineEdit->text(); + surfaces_[currentSurfaceIndex_].start = ui->surfaceStartSpinBox->value(); + surfaces_[currentSurfaceIndex_].stop = ui->surfaceStopSpinBox->value(); + surfaces_[currentSurfaceIndex_].color = selectedColor_; + } +} + +void AddSurfaceFileDlg::clearSurfaceProperties() +{ + ui->surfaceNameLineEdit->clear(); + ui->surfaceStartSpinBox->setValue(0); + ui->surfaceStopSpinBox->setValue(1000); + selectedColor_ = Qt::blue; + updateColorPreview(ui->surfaceColorButton, selectedColor_); + ui->surfacePropertiesGroupBox->setEnabled(false); +} + +QString AddSurfaceFileDlg::generateSurfaceName() const +{ + return QString("Surface %1").arg(surfaces_.size() + 1); +} + +QColor AddSurfaceFileDlg::generateSurfaceColor() const +{ + // Generate different colors for each surface + static const QColor colors[] = { + Qt::blue, Qt::red, Qt::green, Qt::magenta, Qt::cyan, Qt::yellow, + Qt::darkBlue, Qt::darkRed, Qt::darkGreen, Qt::darkMagenta, Qt::darkCyan, Qt::darkYellow + }; + + int colorIndex = surfaces_.size() % (sizeof(colors) / sizeof(colors[0])); + return colors[colorIndex]; +} + +AddSurfaceFileDlg::SurfaceParams AddSurfaceFileDlg::GetSurfaceParams() const +{ + SurfaceParams params; + params.xColumn = ui->xColumnSpinBox->value(); + params.yColumn = ui->yColumnSpinBox->value(); + params.zColumn = ui->zColumnSpinBox->value(); + params.separator = ui->separatorLineEdit->text(); + params.xGridSize = ui->xGridSizeSpinBox->value(); + params.yGridSize = ui->yGridSizeSpinBox->value(); + params.hasHeader = ui->hasHeaderCheckBox->isChecked(); + return params; +} + +QString AddSurfaceFileDlg::GetSelectedFilePath() const +{ + return ui->filePathLineEdit->text(); +} + +QString AddSurfaceFileDlg::GetDescription() const +{ + return getDescription(); // 使用基类的getDescription方法 +} + +void AddSurfaceFileDlg::accept() +{ + if (!validateSpecificParams()) { + return; } - return params; + // Save current surface properties before creating FileEntry + saveSurfaceProperties(); + + // Create FileEntrySurface + auto fileEntry = std::dynamic_pointer_cast(CreateFileEntrySurface(GetSelectedFilePath())); + if (!fileEntry) { + QMessageBox::critical(this, tr("Error"), tr("Failed to create surface file entry.")); + return; + } + + // Set chart properties + fileEntry->SetChartProperties(chartProperties_); + + // Set surface properties + for (const auto& surface : surfaces_) { + fileEntry->AddSurfaceProperty(surface); + } + + // Set description + fileEntry->SetDescription(GetDescription()); + + // Add to workspace + WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent(); + if (!workspace) { + QMessageBox::critical(this, tr("Error"), tr("Unable to get current workspace")); + return; + } + + // Add FileEntrySurface to workspace using SetFileEntry method + auto result = workspace->SetFileEntry(fileEntry); + if (result != WorkSpace::FileEntryResult::Ok) { + QString errorMsg; + switch (result) { + case WorkSpace::FileEntryResult::LimitExceeded: + errorMsg = tr("Surface file count has reached the limit (9 files)"); + break; + case WorkSpace::FileEntryResult::Duplicate: + errorMsg = tr("File already exists"); + break; + case WorkSpace::FileEntryResult::CopyFailed: + errorMsg = tr("File copy failed"); + break; + case WorkSpace::FileEntryResult::InvalidFile: + errorMsg = tr("Invalid file"); + break; + default: + errorMsg = tr("Failed to add file"); + break; + } + QMessageBox::warning(this, tr("Error"), errorMsg); + return; + } + + LOG_INFO("Added surface file to workspace: {}", GetSelectedFilePath().toUtf8().constData()); + QDialog::accept(); } \ No newline at end of file diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.h b/src/ui/WorkSpace/AddSurfaceFileDlg.h index 07738b19..9a6531e7 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.h +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.h @@ -1,56 +1,86 @@ #pragma once #include "BaseAddFileDlg.h" +#include "workspace/FileEntry.h" +#include +#include +#include +#include -QT_BEGIN_NAMESPACE class QLineEdit; -class QCheckBox; class QSpinBox; -class QComboBox; +class QCheckBox; class QTextEdit; -class QToolButton; -class QLabel; -QT_END_NAMESPACE +class QComboBox; +class QPushButton; +class QListWidget; +class QListWidgetItem; +class QDoubleSpinBox; namespace Ui { - class AddSurfaceFileDlg; +class AddSurfaceFileDlg; } -class AddSurfaceFileDlg : public BaseAddFileDlg { +class AddSurfaceFileDlg : public BaseAddFileDlg +{ Q_OBJECT public: struct SurfaceParams { - QString delimiter; - bool hasHeader; int xColumn; int yColumn; int zColumn; + QString separator; int xGridSize; int yGridSize; - QString description; + bool hasHeader; }; - explicit AddSurfaceFileDlg(QWidget* parent = nullptr); - ~AddSurfaceFileDlg() override; +public: + explicit AddSurfaceFileDlg(QWidget *parent = nullptr); + ~AddSurfaceFileDlg(); - SurfaceParams getSurfaceParams() const; - QString getSelectedFilePath() const; - QString getDescription() const; - -protected: + // BaseAddFileDlg interface QString getFileFilter() const override; QString getDialogTitle() const override; bool validateSpecificParams() override; + void updateFileInfo(const QString& filePath) override; + + // Get surface parameters + SurfaceParams GetSurfaceParams() const; + QString GetSelectedFilePath() const; + QString GetDescription() const; private slots: - void onSelectFileClicked(); + void onSelectFile(); void onFilePathChanged(); + + // Surface management slots + void onSurfaceColorButtonClicked(); + void onAddSurfaceClicked(); + void onRemoveSurfaceClicked(); + void onSurfaceListItemClicked(QListWidgetItem* item); + void onSurfaceSelectionChanged(); + void onSurfaceNameChanged(); + void onSurfaceDataChanged(); + +public slots: + void accept() override; private: void setupConnections(); - void updateFileInfo(const QString& filePath); + void updateColorPreview(QPushButton* button, const QColor& color); + void addSurfaceToList(const FileEntrySurface::SurfaceProperty& surface); + void updateSurfaceProperties(); + void saveSurfaceProperties(); + void clearSurfaceProperties(); + QString generateSurfaceName() const; + QColor generateSurfaceColor() const; private: - Ui::AddSurfaceFileDlg* ui_; + Ui::AddSurfaceFileDlg *ui; + int currentSurfaceIndex_; + QColor selectedColor_; + FileEntrySurface::ChartProperties chartProperties_; + FileEntrySurface::SurfaceProperties surfaces_; }; \ No newline at end of file diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.ui b/src/ui/WorkSpace/AddSurfaceFileDlg.ui index e7446dae..5a91dc25 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.ui +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.ui @@ -6,12 +6,12 @@ 0 0 - 500 - 520 + 800 + 726 - Add Surface Data File + Add Surface File @@ -19,56 +19,18 @@ File Selection - - - - - File Path: - - - - - + + + Select surface data file... - - true - - - + + - ... - - - - - - - File Name: - - - - - - - - - - - - - - - File Size: - - - - - - - - + Browse... @@ -76,11 +38,372 @@ - + - Surface Parameters + Chart Properties - + + + + + X Axis Title: + + + + + + + + + + Y Axis Title: + + + + + + + + + + Z Axis Title: + + + + + + + + + + Time Parameter: + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + X Range: + + + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + to + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + + + X Count: + + + + + + + 1 + + + 10000 + + + 100 + + + + + + + Y Range: + + + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + to + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + + + Y Count: + + + + + + + 1 + + + 10000 + + + 100 + + + + + + + Z Range: + + + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + to + + + + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + + + Z Count: + + + + + + + 1 + + + 10000 + + + 100 + + + + + + + + + + Surface Management + + + + + + + + Add Surface + + + + + + + + 200 + 150 + + + + + + + + Remove + + + + + + + + + Surface Properties + + + + + + Name: + + + + + + + + + + Color: + + + + + + + + 100 + 30 + + + + Select Color + + + + + + + Start Point: + + + + + + + 0 + + + 999999 + + + + + + + End Point: + + + + + + + 0 + + + 999999 + + + + + + + + + + + + + Data Format Parameters + + @@ -94,92 +417,75 @@ 1 - 100 + 1000 1 - + Y Column: - + 1 - 100 + 1000 2 - + Z Column: - + 1 - 100 + 1000 3 - + Separator: - - - - - Comma (,) - - - - - Tab - - - - - Space - - - - - Semicolon (;) - - + + + + , + - + X Grid Size: - + 1 @@ -192,14 +498,14 @@ - + Y Grid Size: - + 1 @@ -212,13 +518,10 @@ - + - File has header row - - - true + Has Header Row @@ -226,76 +529,50 @@ - - - Description (Optional) - - - - - - - 16777215 - 80 - - - - Enter file description... - - - - - - - - + - Qt::Vertical + Qt::Horizontal - - - 20 - 40 - + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Add File - - - true - - - - - - - Cancel - - - - + - + + + buttonBox + accepted() + AddSurfaceFileDlg + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AddSurfaceFileDlg + reject() + + + 316 + 260 + + + 286 + 274 + + + + \ No newline at end of file diff --git a/src/workspace/FileEntry.cpp b/src/workspace/FileEntry.cpp index 706f8131..9598ecc5 100644 --- a/src/workspace/FileEntry.cpp +++ b/src/workspace/FileEntry.cpp @@ -46,13 +46,16 @@ std::shared_ptr CreateFileEntryCurve(const QString& filePath) { } std::shared_ptr CreateFileEntrySurface(const QString& filePath) { - auto fileEntry = std::make_shared(); - fileEntry->SetType(FileEntryType::Surface); - - if (!filePath.isEmpty()) { - fileEntry->SetPath(filePath); + QFileInfo fileInfo(filePath); + if (!fileInfo.exists()) { + LOG_ERROR("File does not exist: {}", filePath.toUtf8().constData()); + return nullptr; } + auto fileEntry = std::make_shared(); + fileEntry->SetPath(filePath); + fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name + return fileEntry; } @@ -79,4 +82,45 @@ std::shared_ptr CreateFileEntryLight(const QString& filePath) { fileEntry->SetName(fileInfo.baseName()); // Use base name as default display name return fileEntry; +} + +// FileEntrySurface method implementations +void FileEntrySurface::SetChartProperties(const ChartProperties& properties) { + chartProperties_ = properties; +} + +const FileEntrySurface::ChartProperties& FileEntrySurface::GetChartProperties() const { + return chartProperties_; +} + +void FileEntrySurface::AddSurfaceProperty(const SurfaceProperty& surface) { + surfaceProperties_.append(surface); +} + +void FileEntrySurface::RemoveSurfaceProperty(int index) { + if (index >= 0 && index < surfaceProperties_.size()) { + surfaceProperties_.removeAt(index); + } +} + +void FileEntrySurface::SetSurfaceProperty(int index, const SurfaceProperty& surface) { + if (index >= 0 && index < surfaceProperties_.size()) { + surfaceProperties_[index] = surface; + } +} + +const FileEntrySurface::SurfaceProperties& FileEntrySurface::GetSurfaceProperties() const { + return surfaceProperties_; +} + +FileEntrySurface* FileEntrySurface::AsSurface() { + return this; +} + +void FileEntrySurface::SetDescription(const QString& description) { + description_ = description; +} + +const QString& FileEntrySurface::GetDescription() const { + return description_; } \ No newline at end of file diff --git a/src/workspace/FileEntry.h b/src/workspace/FileEntry.h index 33cf4326..a3791cfe 100644 --- a/src/workspace/FileEntry.h +++ b/src/workspace/FileEntry.h @@ -31,6 +31,7 @@ inline bool FileEntryTypeFromString(const char* s, FileEntryType& out) { class FileEntryCurve; class FileEntryLight; +class FileEntrySurface; class FileEntry { public: @@ -48,8 +49,9 @@ public: void SetName(const QString& name) { name_ = name; } QString GetName() const { return name_; } - virtual FileEntryCurve* AsCurve() { return nullptr; } - virtual FileEntryLight* AsLight() { return nullptr; } + virtual FileEntryCurve* AsCurve() { return nullptr; } + virtual FileEntryLight* AsLight() { return nullptr; } + virtual FileEntrySurface* AsSurface() { return nullptr; } protected: FileEntryType type_; @@ -105,6 +107,62 @@ private: CurveProperties curveProperties_; }; +class FileEntrySurface : public FileEntry { +public: + struct ChartProperties { + int xCount; + int yCount; // Added missing yCount + int zCount; // Added missing zCount + QString xTitle; + QString yTitle; + QString zTitle; + double xMin; + double xMax; + double yMin; + double yMax; + double zMin; + double zMax; + double timeParam; + }; + + struct SurfaceProperty { + QString name; + QColor color; + int start; + int stop; + QString x; + QString y; + QString z; + }; + + using SurfaceProperties = QList; + +public: + FileEntrySurface() { type_ = FileEntryType::Surface; } + + // Chart properties management + void SetChartProperties(const ChartProperties& properties); + const ChartProperties& GetChartProperties() const; + + // Surface properties management + void AddSurfaceProperty(const SurfaceProperty& surface); + void RemoveSurfaceProperty(int index); + void SetSurfaceProperty(int index, const SurfaceProperty& surface); + const SurfaceProperties& GetSurfaceProperties() const; + + // Type conversion + FileEntrySurface* AsSurface() override; + + // Description management + void SetDescription(const QString& description); + const QString& GetDescription() const; + +private: + ChartProperties chartProperties_; + SurfaceProperties surfaceProperties_; + QString description_; +}; + class FileEntryLight : public FileEntry { public: struct ColorProperties {