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