diff --git a/src/Dyt.qrc b/src/Dyt.qrc index bea57361..eaa97f2e 100644 --- a/src/Dyt.qrc +++ b/src/Dyt.qrc @@ -31,6 +31,7 @@ res/default/menu_window_manager.png res/default/menu_window_setting.png res/default/Command.png + res/default/polar.png diff --git a/src/res/default/polar.png b/src/res/default/polar.png new file mode 100644 index 00000000..17a6c55c Binary files /dev/null and b/src/res/default/polar.png differ diff --git a/src/ui/DialogTitleBar.ui b/src/ui/DialogTitleBar.ui index d55d0e04..4eb8530f 100644 --- a/src/ui/DialogTitleBar.ui +++ b/src/ui/DialogTitleBar.ui @@ -18,16 +18,16 @@ 0 - 0 + 20 - 0 + 5 - 0 + 5 - 0 + 5 diff --git a/src/ui/Menu/FileManagerMenu.cpp b/src/ui/Menu/FileManagerMenu.cpp index f5c94408..2b7d4e8c 100644 --- a/src/ui/Menu/FileManagerMenu.cpp +++ b/src/ui/Menu/FileManagerMenu.cpp @@ -41,6 +41,7 @@ void FileManagerMenu::InitConnect() { connect(ui->menu_surface_file, &QToolButton::clicked, this, &FileManagerMenu::AddSurfaceFile); connect(ui->menu_table_file, &QToolButton::clicked, this, &FileManagerMenu::AddTableFile); connect(ui->menu_light_file, &QToolButton::clicked, this, &FileManagerMenu::AddLightFile); + connect(ui->menu_polar_file, &QToolButton::clicked, this, &FileManagerMenu::AddPolarFile); } void FileManagerMenu::NewWorkSpace() { @@ -94,38 +95,41 @@ void FileManagerMenu::AddWaveFile() { // Show curve file addition dialog auto dialog = AddFileDialogFactory::createDialog(FileEntryType::Curve, &MainFrame::Get()); if (dialog && dialog->exec() == QDialog::Accepted) { - QString selectedPath = dialog->getSelectedFilePath(); - - // 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")); - break; - case WorkSpace::FileEntryResult::Duplicate: - QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), - QObject::tr("file already added for this type")); - break; - case WorkSpace::FileEntryResult::CopyFailed: - 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; - } + + SaveWorkSpace(); + + //QString selectedPath = dialog->getSelectedFilePath(); + // + //// 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")); + // break; + //case WorkSpace::FileEntryResult::Duplicate: + // QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + // QObject::tr("file already added for this type")); + // break; + //case WorkSpace::FileEntryResult::CopyFailed: + // 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; + //} } } @@ -139,38 +143,41 @@ void FileManagerMenu::AddSurfaceFile() { // Show surface file addition dialog auto dialog = AddFileDialogFactory::createDialog(FileEntryType::Surface, &MainFrame::Get()); if (dialog && dialog->exec() == QDialog::Accepted) { - QString selectedPath = dialog->getSelectedFilePath(); - - // 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")); - break; - case WorkSpace::FileEntryResult::Duplicate: - QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), - QObject::tr("file already added for this type")); - break; - case WorkSpace::FileEntryResult::CopyFailed: - 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; - } + + SaveWorkSpace(); + + //QString selectedPath = dialog->getSelectedFilePath(); + // + //// 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")); + // break; + //case WorkSpace::FileEntryResult::Duplicate: + // QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + // QObject::tr("file already added for this type")); + // break; + //case WorkSpace::FileEntryResult::CopyFailed: + // 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; + //} } } @@ -184,38 +191,41 @@ void FileManagerMenu::AddTableFile() { // Show table file addition dialog auto dialog = AddFileDialogFactory::createDialog(FileEntryType::Table, &MainFrame::Get()); if (dialog && dialog->exec() == QDialog::Accepted) { - QString selectedPath = dialog->getSelectedFilePath(); - - // 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")); - break; - case WorkSpace::FileEntryResult::Duplicate: - QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), - QObject::tr("file already added for this type")); - break; - case WorkSpace::FileEntryResult::CopyFailed: - 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; - } + + SaveWorkSpace(); + + //QString selectedPath = dialog->getSelectedFilePath(); + // + //// 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")); + // break; + //case WorkSpace::FileEntryResult::Duplicate: + // QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + // QObject::tr("file already added for this type")); + // break; + //case WorkSpace::FileEntryResult::CopyFailed: + // 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; + //} } } @@ -229,37 +239,55 @@ void FileManagerMenu::AddLightFile() { // Show light file addition dialog auto dialog = AddFileDialogFactory::createDialog(FileEntryType::Light, &MainFrame::Get()); if (dialog && dialog->exec() == QDialog::Accepted) { - QString selectedPath = dialog->getSelectedFilePath(); - - // 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")); - break; - case WorkSpace::FileEntryResult::Duplicate: - QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), - QObject::tr("file already added for this type")); - break; - case WorkSpace::FileEntryResult::CopyFailed: - 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; - } + + SaveWorkSpace(); + + //QString selectedPath = dialog->getSelectedFilePath(); + // + //// 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")); + // break; + //case WorkSpace::FileEntryResult::Duplicate: + // QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), + // QObject::tr("file already added for this type")); + // break; + //case WorkSpace::FileEntryResult::CopyFailed: + // 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; + //} } } + +void FileManagerMenu::AddPolarFile() { + auto current = WorkSpaceManager::Get().GetCurrent(); + if (nullptr == current) { + QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("please create workspace first")); + return; + } + + // Show light file addition dialog + auto dialog = AddFileDialogFactory::createDialog(FileEntryType::Polar, &MainFrame::Get()); + if (dialog && dialog->exec() == QDialog::Accepted) { + + SaveWorkSpace(); + } +} \ No newline at end of file diff --git a/src/ui/Menu/FileManagerMenu.h b/src/ui/Menu/FileManagerMenu.h index da08123b..5162b618 100644 --- a/src/ui/Menu/FileManagerMenu.h +++ b/src/ui/Menu/FileManagerMenu.h @@ -25,6 +25,7 @@ protected: void AddSurfaceFile(); void AddTableFile(); void AddLightFile(); + void AddPolarFile(); signals: void LoadDyt(const QString& path); diff --git a/src/ui/Menu/FileManagerMenu.ui b/src/ui/Menu/FileManagerMenu.ui index 0aa0b80b..c92bbb90 100644 --- a/src/ui/Menu/FileManagerMenu.ui +++ b/src/ui/Menu/FileManagerMenu.ui @@ -94,6 +94,16 @@ + + + + new polar file + + + + + + diff --git a/src/ui/Panel/DataPanel.cpp b/src/ui/Panel/DataPanel.cpp index e24245ed..74229192 100644 --- a/src/ui/Panel/DataPanel.cpp +++ b/src/ui/Panel/DataPanel.cpp @@ -82,6 +82,8 @@ QString DataPanel::GetTypeDisplayName() const return "Table"; case FileEntryType::Light: return "Light"; + case FileEntryType::Polar: + return "Polar"; default: return "Unknown"; } diff --git a/src/ui/Panel/DataPanelFactory.cpp b/src/ui/Panel/DataPanelFactory.cpp index 153c5e78..fc937f56 100644 --- a/src/ui/Panel/DataPanelFactory.cpp +++ b/src/ui/Panel/DataPanelFactory.cpp @@ -4,9 +4,10 @@ #include "common/SpdLogger.h" // Forward declarations for future panel types - #include "SurfacePanel.h" - #include "TablePanel.h" - #include "LightPanel.h" +#include "SurfacePanel.h" +#include "TablePanel.h" +#include "LightPanel.h" +#include "PolarPanel.h" DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, const QString& filePath, QWidget* parent) { @@ -30,6 +31,11 @@ DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, cons // TODO: Implement LightPanel LOG_WARN("LightPanel not implemented yet, creating base DataPanel"); return new LightPanel(index, filePath, parent); + + case FileEntryType::Polar: + // TODO: Implement LightPanel + LOG_WARN("PolarPanel not implemented yet, creating base DataPanel"); + return new PolarPanel(index, filePath, parent); default: LOG_ERROR("Unsupported file type: {}", static_cast(fileType)); @@ -51,6 +57,7 @@ bool DataPanelFactory::IsTypeSupported(FileEntryType fileType) case FileEntryType::Surface: case FileEntryType::Table: case FileEntryType::Light: + case FileEntryType::Polar: return true; default: return false; @@ -68,6 +75,8 @@ QString DataPanelFactory::GetTypeDisplayName(FileEntryType fileType) return "Table"; case FileEntryType::Light: return "Light"; + case FileEntryType::Polar: + return "Polar"; default: return "Unknown"; } diff --git a/src/ui/Panel/DataPanelManager.cpp b/src/ui/Panel/DataPanelManager.cpp index b5fa55db..636259d1 100644 --- a/src/ui/Panel/DataPanelManager.cpp +++ b/src/ui/Panel/DataPanelManager.cpp @@ -64,6 +64,7 @@ void DataPanelManager::SetWorkspace(WorkSpace* workspace) UpdatePanelsForType(FileEntryType::Surface); UpdatePanelsForType(FileEntryType::Table); UpdatePanelsForType(FileEntryType::Light); + UpdatePanelsForType(FileEntryType::Polar); } else { ClearAllPanels(); } diff --git a/src/ui/Panel/PolarPanel.cpp b/src/ui/Panel/PolarPanel.cpp new file mode 100644 index 00000000..979e6470 --- /dev/null +++ b/src/ui/Panel/PolarPanel.cpp @@ -0,0 +1,344 @@ +#include "ui/Panel/PolarPanel.h" +#include "ui/DockWidget.h" +#include "ui/DockTitleBar.h" +#include "common/SpdLogger.h" +#include +#include +#include + +PolarPanel::PolarPanel(int index, const QString& filePath, QWidget* parent) + : DataPanel(index, FileEntryType::Polar, filePath, parent) +{ + m_pChart = NULL; + m_pThetaAxis = NULL; + m_pRadiusAxis = NULL; + + m_iThetaMax = 0; + m_iThetaMin = 0; + m_iRadiusMax = 0; + m_iRadiusMin = 0; + + m_unitTheta = ""; + m_unitRadius = ""; + + LOG_INFO("Created PolarPanel {} for file: {}", index, filePath.toStdString()); +} + +PolarPanel::PolarPanel(int index, std::shared_ptr fileEntry, QWidget* parent) + : DataPanel(index, fileEntry, parent) +{ + m_pChart = NULL; + m_pThetaAxis = NULL; + m_pRadiusAxis = NULL; + + m_iThetaMax = 0; + m_iThetaMin = 0; + m_iRadiusMax = 0; + m_iRadiusMin = 0; + + m_unitTheta = ""; + m_unitRadius = ""; + + if (fileEntry) { + LOG_INFO("Created PolarPanel {} for chart: {}", index, fileEntry->GetName().toStdString()); + // Override the title with chart name + title_ = QString("Polar Panel %1 - %2").arg(index).arg(fileEntry->GetName()); + } + else { + LOG_WARN("Created PolarPanel {} with null chart data", index); + } +} + +PolarPanel::~PolarPanel() +{ + LOG_INFO("Destroyed PolarPanel {}", GetIndex()); +} + +void PolarPanel::RefreshPanel() +{ + // Implement curve-specific refresh logic here + DataPanel::RefreshPanel(); + + if (auto fileEntry = fileEntry_->AsPolar()) { + OnDataPanelUpdated(fileEntry); + } + + LOG_INFO("Refreshed TablePanel {}", GetIndex()); +} + +void PolarPanel::InitUI() +{ + m_pChart = new QPolarChart(); + //mPolarChart->addSeries(mCurveData); + //m_pChart->legend()->hide(); + m_pChart->layout()->setContentsMargins(0, 0, 0, 0); + m_pChart->setBackgroundRoundness(0); + m_pChart->setTheme(QChart::ChartThemeBlueIcy); + + // + m_pThetaAxis = new QValueAxis(); + m_pThetaAxis->setTickCount(13); + m_pThetaAxis->setLabelFormat("%d"); + m_pThetaAxis->setRange(0, 360); + m_pChart->addAxis(m_pThetaAxis, QPolarChart::PolarOrientationAngular); + + m_pRadiusAxis = new QValueAxis(); + m_pRadiusAxis->setTickCount(6); + m_pRadiusAxis->setLabelFormat("%d"); + m_pRadiusAxis->setRange(0, 30); + m_pChart->addAxis(m_pRadiusAxis, QPolarChart::PolarOrientationRadial); + + QChartView *mChartView = new QChartView(); + mChartView->setChart(m_pChart); + mChartView->setRenderHint(QPainter::Antialiasing); + + QHBoxLayout* mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addWidget(mChartView); + setLayout(mainLayout); +} + +QString PolarPanel::GetTypeDisplayName() const +{ + return "Polar"; +} + +void PolarPanel::OnDataPanelUpdated(FileEntryPolar* fileEntry) +{ + QString strName = fileEntry->GetName(); + updateTitle(strName); + + FileEntryPolar::ChartProperties propChart = fileEntry->GetChartProperties(); + updateTitleAxis(propChart.AngularTitle, propChart.RadialTitle); + updateMinMaxTheta(propChart.AngularMin, propChart.AngularMax, propChart.AngularCount, propChart.AngularUnit); + updateMinMaxRadius(propChart.RadialMin, propChart.RadialMax, propChart.RadialCount, propChart.RadialUnit); + + QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName(); + FileEntryPolar::LineProperties propCurves = fileEntry->GetLineProperties(); + updateParseFile(strFile, propChart.timeParam, propCurves); +} + +void PolarPanel::OnTimeChanged(double time) +{ + if (m_data.size() > 0) + { + for (QMap::Iterator itSeries = m_seriesIDMap.begin(); itSeries != m_seriesIDMap.end(); itSeries++) + { + QLineSeries * pSeries = itSeries.value(); + if (pSeries) + { + pSeries->clear(); + } + } + + QMap< double, QMap >::const_iterator ite = m_data.lowerBound(time); + if (ite != m_data.end()) + { + ite++; + } + + for (QMap< double, QMap >::Iterator itA = m_data.begin(); itA != ite; itA++) + { + double dTime = itA.key(); + QMap mapData = itA.value(); + for (QMap::Iterator it = mapData.begin(); it != mapData.end(); it++) + { + int nIndex = it.key(); + QPointF data = it.value(); + + QLineSeries * pSeries = m_seriesIDMap.value(nIndex); + if (pSeries) + { + pSeries->append(data); + } + } + } + + m_pChart->update(); + } +} + +void PolarPanel::updateTitle(const QString & title) +{ + if (nullptr != dockWidget_) + { + dockWidget_->setWindowTitle(title); + } +} + +void PolarPanel::updateTitleAxis(const QString& thetaTitle, const QString& radiusTitle) +{ + if (m_pThetaAxis) + { + if (!thetaTitle.isEmpty()) + { + m_pThetaAxis->setTitleText(thetaTitle); + } + } + if (m_pRadiusAxis) + { + if (!radiusTitle.isEmpty()) + { + m_pRadiusAxis->setTitleText(radiusTitle); + } + } +} + +void PolarPanel::updateMinMaxTheta(float min, float max, int count, const QString& unit) +{ + if (m_pThetaAxis) + { + if (max > min) + { + m_iThetaMax = max; + m_iThetaMin = min; + + m_pThetaAxis->setRange(min, max); + } + + if (count > 0) + { + m_pThetaAxis->setTickCount(count); + } + + if (!unit.isEmpty()) + { + m_pThetaAxis->setLabelFormat("%d" + unit); + + m_unitTheta = unit; + } + } +} + +void PolarPanel::updateMinMaxRadius(float min, float max, int count, const QString& unit) +{ + if (m_pRadiusAxis) + { + if (max > min) + { + m_iRadiusMax = max; + m_iRadiusMin = min; + + m_pRadiusAxis->setRange(min, max); + } + + if (count > 0) + { + m_pRadiusAxis->setTickCount(count); + } + + if (!unit.isEmpty()) + { + m_pRadiusAxis->setLabelFormat("%d" + unit); + + m_unitRadius = unit; + } + } +} + +void PolarPanel::updateParseFile(const QString& strFile, int nT, FileEntryPolar::LineProperties listCurve) +{ + if (strFile.isEmpty()) + { + QMessageBox::information(nullptr, QStringLiteral("Error"), QStringLiteral("Please check file path")); + return; + } + + m_seriesIDMap.clear(); + + QFile file(strFile); + if (file.open(QIODevice::ReadOnly)) + { + bool bResetAxisTheta = false; + if (m_iThetaMax == m_iThetaMin) + { + bResetAxisTheta = true; + } + bool bResetAxisRadius = false; + if (m_iRadiusMax == m_iRadiusMin) + { + bResetAxisRadius = true; + } + + float maxTheta = -10000000.0; + float minTheta = 10000000.0; + float maxRadius = -10000000.0; + float minRadius = 10000000.0; + + while (!file.atEnd()) + { + QString strLine = file.readLine().simplified(); + if (!strLine.isEmpty()) + { + QStringList listLine = strLine.split(" "); + double t = listLine.at(nT).toDouble(); + + QMap mapData; + for (int nI = 0; nI < listCurve.size(); nI++) + { + FileEntryPolar::LineProperty propCurve = listCurve.at(nI); + + double Angular = listLine.at(propCurve.Angular).toDouble(); + double Radial = listLine.at(propCurve.Radial).toDouble(); + + QPointF ptData = QPointF(Angular, Radial); + mapData.insert(nI, ptData); + + if (bResetAxisTheta) + { + if (Angular < minTheta) + { + minTheta = Angular; + } + if (Angular > maxTheta) + { + maxTheta = Angular; + } + } + if (bResetAxisRadius) + { + if (Radial < minRadius) + { + minRadius = Radial; + } + if (Radial > maxRadius) + { + maxRadius = Radial; + } + } + } + m_data.insert(t, mapData); + } + } + + if (bResetAxisTheta) + { + updateMinMaxTheta(minTheta * 0.9, maxTheta * 1.1, 0, m_unitTheta); + } + if (bResetAxisRadius) + { + updateMinMaxRadius(minRadius * 0.9, maxRadius * 1.1, 0, m_unitRadius); + } + + for (int nI = 0; nI < listCurve.size(); nI++) + { + FileEntryPolar::LineProperty propCurve = listCurve.at(nI); + + QLineSeries *pSeries = new QLineSeries(this); + pSeries->setName(propCurve.name); + pSeries->setColor(propCurve.color); + pSeries->setUseOpenGL(true); + m_pChart->addSeries(pSeries); + m_seriesIDMap.insert(nI, pSeries); + + QPen pen(propCurve.color); + pen.setWidth(2); + pSeries->setPen(pen); + + pSeries->attachAxis(m_pThetaAxis); + pSeries->attachAxis(m_pRadiusAxis); + } + + file.close(); + } +} \ No newline at end of file diff --git a/src/ui/Panel/PolarPanel.h b/src/ui/Panel/PolarPanel.h new file mode 100644 index 00000000..2eb1653e --- /dev/null +++ b/src/ui/Panel/PolarPanel.h @@ -0,0 +1,87 @@ +#pragma once + +#include "DataPanel.h" +#include "workspace/FileEntry.h" +#include + +#include + +class PolarPanel : public DataPanel +{ + Q_OBJECT + +public: + /** + * @brief Constructor + * @param index Panel index + * @param filePath Associated file path + * @param parent Parent widget + */ + explicit PolarPanel(int index, const QString& filePath, QWidget* parent = nullptr); + + /** + * @brief Constructor with chart data + * @param index Panel index + * @param chartData Chart data containing curve information + * @param parent Parent widget + */ + explicit PolarPanel(int index, std::shared_ptr fileEntry, QWidget* parent = nullptr); + + /** + * @brief Destructor + */ + virtual ~PolarPanel(); + + /** + * @brief Get file type + * @return File type (always Curve for this class) + */ + FileEntryType GetFileType() const override { return FileEntryType::Table; } + + /** + * @brief Refresh panel content + */ + void RefreshPanel() override; + +protected: + /** + * @brief Initialize UI for curve-specific layout + */ + virtual void InitUI(); + + /** + * @brief Get type display name + * @return Display name for curve type + */ + QString GetTypeDisplayName() const override; + + void OnDataPanelUpdated(FileEntryPolar* fileEntry); + + virtual void OnTimeChanged(double time); + +private: + void updateTitle(const QString& title); + void updateTitleAxis(const QString& thetaTitle, const QString& radiusTitle); + void updateMinMaxTheta(float min, float max, int count, const QString& unit); + void updateMinMaxRadius(float min, float max, int count, const QString& unit); + + void updateParseFile(const QString& strFile, int nT, FileEntryPolar::LineProperties listCurve); + +private: + QPolarChart *m_pChart; + QValueAxis *m_pThetaAxis; + QValueAxis *m_pRadiusAxis; + + float m_iThetaMax; + float m_iThetaMin; + float m_iRadiusMax; + float m_iRadiusMin; + + QString m_unitTheta; + QString m_unitRadius; + + QMap m_seriesIDMap; + + QMap< double, QMap > m_data; +}; + diff --git a/src/ui/PropertyBrowser/qtpropertymanager.cpp b/src/ui/PropertyBrowser/qtpropertymanager.cpp index 7d17810f..115408fc 100644 --- a/src/ui/PropertyBrowser/qtpropertymanager.cpp +++ b/src/ui/PropertyBrowser/qtpropertymanager.cpp @@ -7967,6 +7967,15 @@ public: QMap> m_properyToLightPaths; QMap m_lightPathToPropery; QMap m_lightPathIndex; + + // Polar + QMap m_properyToPolarGroup; + QMap m_polarGroupToPropery; + QMap m_properyToPolarCount; + QMap m_polarCountToPropery; + QMap> m_properyToPolarPaths; + QMap m_polarPathToPropery; + QMap m_polarPathIndex; }; void QtWorkspacePropertyManagerPrivate::slotStringChanged(QtProperty* property, QString value) { @@ -8026,7 +8035,12 @@ void QtWorkspacePropertyManagerPrivate::slotStringChanged(QtProperty* property, int idx = m_lightPathIndex.value(property, 0); c.SetFileEntryPath(FileEntryType::Light, idx, value); q_ptr->setValue(prop, c); - } + } else if (QtProperty* prop = m_polarPathToPropery.value(property, 0)) { + QWorkspaceAttribute c = m_values[prop]; + int idx = m_polarPathIndex.value(property, 0); + c.SetFileEntryPath(FileEntryType::Polar, idx, value); + q_ptr->setValue(prop, c); + } } void QtWorkspacePropertyManagerPrivate::slotIntChanged(QtProperty* property, int value) { @@ -8052,6 +8066,7 @@ void QtWorkspacePropertyManagerPrivate::slotIntChanged(QtProperty* property, int case FileEntryType::Surface: title = QObject::tr("Surface[%1]").arg(i + 1); break; case FileEntryType::Table: title = QObject::tr("Table[%1]").arg(i + 1); break; case FileEntryType::Light: title = QObject::tr("Light[%1]").arg(i + 1); break; + case FileEntryType::Polar: title = QObject::tr("Polar[%1]").arg(i + 1); break; } p->setPropertyName(title); group->addSubProperty(p); @@ -8080,6 +8095,7 @@ void QtWorkspacePropertyManagerPrivate::slotIntChanged(QtProperty* property, int handleType(FileEntryType::Surface, m_surfaceCountToPropery, m_properyToSurfacePaths, m_surfacePathToPropery, m_surfacePathIndex, m_properyToSurfaceGroup); handleType(FileEntryType::Table, m_tableCountToPropery, m_properyToTablePaths, m_tablePathToPropery, m_tablePathIndex, m_properyToTableGroup); handleType(FileEntryType::Light, m_lightCountToPropery, m_properyToLightPaths, m_lightPathToPropery, m_lightPathIndex, m_properyToLightGroup); + handleType(FileEntryType::Polar, m_polarCountToPropery, m_properyToPolarPaths, m_polarPathToPropery, m_polarPathIndex, m_properyToPolarGroup); } void QtWorkspacePropertyManagerPrivate::slotPropertyDestroyed(QtProperty* property) { @@ -8273,6 +8289,7 @@ void QtWorkspacePropertyManager::setValue(QtProperty* property, const QWorkspace syncGroup(FileEntryType::Surface, d_ptr->m_properyToSurfaceGroup, d_ptr->m_properyToSurfaceCount, d_ptr->m_properyToSurfacePaths, d_ptr->m_surfacePathToPropery, d_ptr->m_surfacePathIndex); syncGroup(FileEntryType::Table, d_ptr->m_properyToTableGroup, d_ptr->m_properyToTableCount, d_ptr->m_properyToTablePaths, d_ptr->m_tablePathToPropery, d_ptr->m_tablePathIndex); syncGroup(FileEntryType::Light, d_ptr->m_properyToLightGroup, d_ptr->m_properyToLightCount, d_ptr->m_properyToLightPaths, d_ptr->m_lightPathToPropery, d_ptr->m_lightPathIndex); + syncGroup(FileEntryType::Polar, d_ptr->m_properyToPolarGroup, d_ptr->m_properyToPolarCount, d_ptr->m_properyToPolarPaths, d_ptr->m_polarPathToPropery, d_ptr->m_polarPathIndex); emit propertyChanged(property); emit valueChanged(property, value); @@ -8408,6 +8425,9 @@ void QtWorkspacePropertyManager::initializeProperty(QtProperty* property) { addGroup(FileEntryType::Light, tr("Lights"), d_ptr->m_properyToLightGroup, d_ptr->m_lightGroupToPropery, d_ptr->m_properyToLightCount, d_ptr->m_lightCountToPropery, d_ptr->m_properyToLightPaths, d_ptr->m_lightPathToPropery, d_ptr->m_lightPathIndex); + addGroup(FileEntryType::Polar, tr("Polars"), d_ptr->m_properyToPolarGroup, d_ptr->m_polarGroupToPropery, + d_ptr->m_properyToPolarCount, d_ptr->m_polarCountToPropery, + d_ptr->m_properyToPolarPaths, d_ptr->m_polarPathToPropery, d_ptr->m_polarPathIndex); } /*! @@ -8519,6 +8539,9 @@ void QtWorkspacePropertyManager::uninitializeProperty(QtProperty* property) { cleanupGroup(d_ptr->m_properyToLightGroup, d_ptr->m_lightGroupToPropery, d_ptr->m_properyToLightCount, d_ptr->m_lightCountToPropery, d_ptr->m_properyToLightPaths, d_ptr->m_lightPathToPropery, d_ptr->m_lightPathIndex); + cleanupGroup(d_ptr->m_properyToPolarGroup, d_ptr->m_polarGroupToPropery, + d_ptr->m_properyToPolarCount, d_ptr->m_polarCountToPropery, + d_ptr->m_properyToPolarPaths, d_ptr->m_polarPathToPropery, d_ptr->m_polarPathIndex); } #pragma endregion diff --git a/src/ui/WorkSpace/AddCurveFileDlg.ui b/src/ui/WorkSpace/AddCurveFileDlg.ui index 57d21058..a18c17d3 100644 --- a/src/ui/WorkSpace/AddCurveFileDlg.ui +++ b/src/ui/WorkSpace/AddCurveFileDlg.ui @@ -7,7 +7,7 @@ 0 0 600 - 705 + 789 @@ -22,6 +22,12 @@ + + + 0 + 25 + + File Path: @@ -29,6 +35,12 @@ + + + 0 + 25 + + true @@ -39,6 +51,12 @@ + + + 0 + 25 + + ... @@ -46,6 +64,12 @@ + + + 0 + 25 + + File Name: @@ -53,6 +77,12 @@ + + + 0 + 25 + + - @@ -60,6 +90,12 @@ + + + 0 + 25 + + File Size: @@ -67,6 +103,12 @@ + + + 0 + 25 + + - @@ -83,6 +125,12 @@ + + + 0 + 25 + + Chart Name: @@ -90,6 +138,12 @@ + + + 0 + 25 + + Chart 1 @@ -100,16 +154,35 @@ + + + 0 + 25 + + Chart Type: - + + + + 0 + 25 + + + + + + 0 + 25 + + X Axis Title: @@ -117,6 +190,12 @@ + + + 0 + 25 + + Enter X axis title... @@ -124,6 +203,12 @@ + + + 0 + 25 + + Y Axis Title: @@ -131,6 +216,12 @@ + + + 0 + 25 + + Enter Y axis title... @@ -138,13 +229,26 @@ + + + 0 + 25 + + Time: - + + + + 0 + 25 + + + @@ -157,6 +261,12 @@ + + + 0 + 25 + + -999999.000000000000000 @@ -170,6 +280,12 @@ + + + 0 + 25 + + 2 @@ -183,6 +299,12 @@ + + + 0 + 25 + + X Tick Count: @@ -190,6 +312,12 @@ + + + 0 + 25 + + -999999.000000000000000 @@ -203,6 +331,12 @@ + + + 0 + 25 + + X Min: @@ -210,6 +344,12 @@ + + + 0 + 25 + + Y Max: @@ -217,6 +357,12 @@ + + + 0 + 25 + + Y Min: @@ -224,6 +370,12 @@ + + + 0 + 25 + + 2 @@ -231,12 +383,18 @@ 50 - 6 + 9 + + + 0 + 25 + + -999999.000000000000000 @@ -250,6 +408,12 @@ + + + 0 + 25 + + -999999.000000000000000 @@ -263,6 +427,12 @@ + + + 0 + 25 + + X Max: @@ -270,6 +440,12 @@ + + + 0 + 25 + + Y Tick Count: @@ -308,6 +484,12 @@ + + + 0 + 0 + + 80 @@ -321,6 +503,12 @@ + + + 0 + 0 + + 60 @@ -358,6 +546,12 @@ + + + 0 + 25 + + Curve Name: @@ -365,6 +559,12 @@ + + + 0 + 25 + + Enter curve name... @@ -372,6 +572,12 @@ + + + 0 + 25 + + Curve Color: @@ -381,6 +587,12 @@ + + + 0 + 0 + + 100 @@ -425,6 +637,12 @@ + + + 0 + 25 + + Data Start: @@ -432,6 +650,12 @@ + + + 0 + 25 + + 1 @@ -445,6 +669,12 @@ + + + 0 + 25 + + Data Stop: @@ -452,6 +682,12 @@ + + + 0 + 25 + + 1 @@ -538,6 +774,12 @@ + + + 100 + 30 + + Add File @@ -548,6 +790,12 @@ + + + 100 + 30 + + Cancel diff --git a/src/ui/WorkSpace/AddFileDialogFactory.cpp b/src/ui/WorkSpace/AddFileDialogFactory.cpp index b9bf66bf..ffb9fc9d 100644 --- a/src/ui/WorkSpace/AddFileDialogFactory.cpp +++ b/src/ui/WorkSpace/AddFileDialogFactory.cpp @@ -5,6 +5,7 @@ #include "AddSurfaceFileDlg.h" #include "AddTableFileDlg.h" #include "AddLightFileDlg.h" +#include "AddPolarFileDlg.h" BaseAddFileDlg* AddFileDialogFactory::createDialog(FileEntryType type, QWidget* parent) { switch (type) { @@ -16,6 +17,8 @@ BaseAddFileDlg* AddFileDialogFactory::createDialog(FileEntryType type, QWidget* return new AddTableFileDlg(parent); case FileEntryType::Light: return new AddLightFileDlg(parent); + case FileEntryType::Polar: + return new AddPolarFileDlg(parent); default: return nullptr; } diff --git a/src/ui/WorkSpace/AddLightFileDlg.cpp b/src/ui/WorkSpace/AddLightFileDlg.cpp index ece774a6..85b4fb16 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.cpp +++ b/src/ui/WorkSpace/AddLightFileDlg.cpp @@ -29,6 +29,8 @@ AddLightFileDlg::AddLightFileDlg(QWidget* parent) // Update color previews updateOpenColorPreview(openColor_); updateCloseColorPreview(closeColor_); + + ui->editDataBtn->setVisible(false); } AddLightFileDlg::~AddLightFileDlg() { @@ -344,6 +346,14 @@ QString AddLightFileDlg::getDialogTitle() const { } void AddLightFileDlg::onSure() { + + QString sName = ui->ChartNameEdit->text(); + // Validate table-specific parameters + if (sName.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), tr("Please enter a Chart name.")); + return; + } + // Save current light properties if any light is selected if (currentLightIndex_ >= 0) { saveLightProperties(); @@ -364,6 +374,8 @@ void AddLightFileDlg::onSure() { // Create FileEntryLight and set properties auto lightEntry = CreateFileEntryLight(getSelectedFilePath()); if (lightEntry) { + lightEntry->SetName(sName); + // Set color properties lightEntry->SetColorProperties(colorProperties_); diff --git a/src/ui/WorkSpace/AddLightFileDlg.ui b/src/ui/WorkSpace/AddLightFileDlg.ui index 26d8e86c..c45f4c23 100644 --- a/src/ui/WorkSpace/AddLightFileDlg.ui +++ b/src/ui/WorkSpace/AddLightFileDlg.ui @@ -7,7 +7,7 @@ 0 0 600 - 516 + 607 @@ -22,6 +22,12 @@ + + + 0 + 25 + + File Path: @@ -29,6 +35,12 @@ + + + 0 + 25 + + true @@ -46,6 +58,12 @@ + + + 0 + 25 + + File Name: @@ -53,6 +71,12 @@ + + + 0 + 25 + + - @@ -60,6 +84,12 @@ + + + 0 + 25 + + File Size: @@ -75,6 +105,44 @@ + + + + true + + + Chart Properties + + + + + + + 0 + 25 + + + + Chart Names: + + + + + + + + 0 + 25 + + + + + + + + + + @@ -272,6 +340,12 @@ + + + 0 + 25 + + Light Names: @@ -279,6 +353,12 @@ + + + 0 + 25 + + Enter light names (comma separated)... @@ -286,8 +366,14 @@ + + + 0 + 25 + + - Light Data: + Light Datas: @@ -295,6 +381,12 @@ + + + 0 + 25 + + Enter data values (comma separated integers)... @@ -317,6 +409,12 @@ + + + 0 + 25 + + Row Index: @@ -354,6 +452,12 @@ + + + 100 + 30 + + Add File @@ -361,6 +465,12 @@ + + + 100 + 30 + + Cancel diff --git a/src/ui/WorkSpace/AddPolarDlg.ui b/src/ui/WorkSpace/AddPolarDlg.ui new file mode 100644 index 00000000..062e002d --- /dev/null +++ b/src/ui/WorkSpace/AddPolarDlg.ui @@ -0,0 +1,810 @@ + + + AddPolarDlg + + + + 0 + 0 + 600 + 789 + + + + Add Polar + + + + + + File Selection + + + + + + + 0 + 25 + + + + File Path: + + + + + + + + 0 + 25 + + + + true + + + Select curve data file... + + + + + + + + 0 + 25 + + + + ... + + + + + + + + 0 + 25 + + + + File Name: + + + + + + + + 0 + 25 + + + + - + + + + + + + + 0 + 25 + + + + File Size: + + + + + + + + 0 + 25 + + + + - + + + + + + + + + + Chart Properties + + + + + + + 0 + 25 + + + + Chart Name: + + + + + + + + 0 + 25 + + + + Chart 1 + + + Enter chart name... + + + + + + + + 0 + 25 + + + + Chart Type: + + + + + + + + 0 + 25 + + + + + + + + + 0 + 25 + + + + X Axis Title: + + + + + + + + 0 + 25 + + + + Enter X axis title... + + + + + + + + 0 + 25 + + + + Y Axis Title: + + + + + + + + 0 + 25 + + + + Enter Y axis title... + + + + + + + + 0 + 25 + + + + Time: + + + + + + + + 0 + 25 + + + + + + + + + + + Axis Range Settings + + + + + + + 0 + 25 + + + + -999999.000000000000000 + + + 999999.000000000000000 + + + 800.000000000000000 + + + + + + + + 0 + 25 + + + + 2 + + + 50 + + + 6 + + + + + + + + 0 + 25 + + + + X Tick Count: + + + + + + + + 0 + 25 + + + + -999999.000000000000000 + + + 999999.000000000000000 + + + 0.000000000000000 + + + + + + + + 0 + 25 + + + + X Min: + + + + + + + + 0 + 25 + + + + Y Max: + + + + + + + + 0 + 25 + + + + Y Min: + + + + + + + + 0 + 25 + + + + 2 + + + 50 + + + 9 + + + + + + + + 0 + 25 + + + + -999999.000000000000000 + + + 999999.000000000000000 + + + -800.000000000000000 + + + + + + + + 0 + 25 + + + + -999999.000000000000000 + + + 999999.000000000000000 + + + 250.000000000000000 + + + + + + + + 0 + 25 + + + + X Max: + + + + + + + + 0 + 25 + + + + Y Tick Count: + + + + + + + + + + Curve Management + + + + + + + + Curves: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 80 + 16777215 + + + + Add Curve + + + + + + + + 0 + 0 + + + + + 60 + 16777215 + + + + Remove + + + + + + + + + + 16777215 + 120 + + + + true + + + + + + + false + + + Selected Curve Properties + + + + + + + 0 + 25 + + + + Curve Name: + + + + + + + + 0 + 25 + + + + Enter curve name... + + + + + + + + 0 + 25 + + + + Curve Color: + + + + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + Select Color + + + + + + + + 50 + 25 + + + + background-color: rgb(255, 0, 0); border: 1px solid black; + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 25 + + + + Data Start: + + + + + + + + 0 + 25 + + + + 1 + + + 999999 + + + 1 + + + + + + + + 0 + 25 + + + + Data Stop: + + + + + + + + 0 + 25 + + + + 1 + + + 999999 + + + 241 + + + + + + + false + + + X Value: + + + + + + + false + + + -999999.000000000000000 + + + 999999.000000000000000 + + + 0.000000000000000 + + + + + + + false + + + Y Value: + + + + + + + false + + + -999999.000000000000000 + + + 999999.000000000000000 + + + 0.000000000000000 + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 30 + + + + Add File + + + true + + + + + + + + 100 + 30 + + + + Cancel + + + + + + + + + + diff --git a/src/ui/WorkSpace/AddPolarFileDlg.cpp b/src/ui/WorkSpace/AddPolarFileDlg.cpp new file mode 100644 index 00000000..477f46a7 --- /dev/null +++ b/src/ui/WorkSpace/AddPolarFileDlg.cpp @@ -0,0 +1,225 @@ +#include "AddPolarFileDlg.h" + +#include +#include +#include +#include +#include + +#include "workspace/WorkSpace.h" +#include "workspace/WorkSpaceManager.h" + +#include "ui_AddPolarDlg.h" + +AddPolarFileDlg::AddPolarFileDlg(QWidget* parent) + : BaseAddFileDlg(FileEntryType::Polar, parent) + , ui(new Ui::AddPolarDlg) + , currentCurveIndex_(-1) + , selectedColor_(255, 0, 0) { // Default to red color + + SetupUI(ui); + SetTitle(getDialogTitle()); + + //setupConnections(); + //updateCurvePropertiesUI(); // Initialize UI based on default chart type +} + +AddPolarFileDlg::~AddPolarFileDlg() { + delete ui; +} + + +QString AddPolarFileDlg::getFileFilter() const { + return "Data Files (*.txt *.csv *.dat);;All Files (*.*)"; +} + +QString AddPolarFileDlg::getDialogTitle() const { + return "Add Polar Data File"; +} + +bool AddPolarFileDlg::validateSpecificParams() { + // File path validation + 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(selectFilePath); + if (!fileInfo.exists()) { + QMessageBox::warning(this, tr("Validation Error"), tr("Selected file does not exist.")); + return false; + } + + // File readability validation + if (!fileInfo.isReadable()) { + QMessageBox::warning(this, tr("Validation Error"), tr("Selected file is not readable. Please check file permissions.")); + return false; + } + + // File size validation (avoid memory issues with large files) + if (fileInfo.size() > 100 * 1024 * 1024) { // 100MB limit + QMessageBox::warning(this, tr("Validation Error"), tr("File is too large (over 100MB). Please select a smaller file.")); + return false; + } + + // Curve count validation + if (curves_.isEmpty()) { + QMessageBox::warning(this, tr("Validation Error"), tr("At least one curve must be defined.")); + return false; + } + + //// Save current curve properties + //if (currentCurveIndex_ >= 0) { + // saveCurveProperties(); + //} + + //// Curve name uniqueness validation + //QStringList curveNames; + //for (int i = 0; i < curves_.size(); ++i) { + // const FileEntryCurve::CurveProperty& curve = curves_[i]; + + // if (curve.name.isEmpty()) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve %1 name cannot be empty.").arg(i + 1)); + // return false; + // } + + // if (curveNames.contains(curve.name)) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve name '%1' is duplicated. Please use different names.").arg(curve.name)); + // return false; + // } + // curveNames.append(curve.name); + + // // Curve name length validation + // if (curve.name.length() > 50) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve name '%1' is too long. Please limit to 50 characters.").arg(curve.name)); + // return false; + // } + + // // Data range validation based on chart type + // if (chartProperties_.chartType == ChartType::Wave) { + // if (curve.data.wave.start < 1 || curve.data.wave.stop < 1) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve '%1' start and stop values must be greater than 0.").arg(curve.name)); + // return false; + // } + + // if (curve.data.wave.start > curve.data.wave.stop) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve '%1' start value cannot be greater than stop value.").arg(curve.name)); + // return false; + // } + + // // Data range reasonableness validation + // if (curve.data.wave.stop - curve.data.wave.start < 1) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve '%1' data range is too small. At least 2 data points are required.").arg(curve.name)); + // return false; + // } + + // if (curve.data.wave.stop > 1000000) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve '%1' stop value is too large. Please ensure it does not exceed 1000000.").arg(curve.name)); + // return false; + // } + // } + // else { + // // Report type validation - ensure x and y values are reasonable + // if (curve.data.report.x < -1000000 || curve.data.report.x > 1000000) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve '%1' X value is out of range. Please ensure it is between -1000000 and 1000000.").arg(curve.name)); + // return false; + // } + + // if (curve.data.report.y < -1000000 || curve.data.report.y > 1000000) { + // QMessageBox::warning(this, tr("Validation Error"), + // tr("Curve '%1' Y value is out of range. Please ensure it is between -1000000 and 1000000.").arg(curve.name)); + // return false; + // } + // } + //} + + //// Chart properties validation + //if (ui->chartNameEdit->text().isEmpty()) { + // QMessageBox::warning(this, tr("Validation Error"), tr("Chart name cannot be empty.")); + // return false; + //} + + //if (ui->chartNameEdit->text().length() > 100) { + // QMessageBox::warning(this, tr("Validation Error"), tr("Chart name is too long. Please limit to 100 characters.")); + // return false; + //} + + //// Axis title validation + //if (ui->xTitleEdit->text().length() > 50) { + // QMessageBox::warning(this, tr("Validation Error"), tr("X axis title is too long. Please limit to 50 characters.")); + // return false; + //} + + //if (ui->yTitleEdit->text().length() > 50) { + // QMessageBox::warning(this, tr("Validation Error"), tr("Y axis title is too long. Please limit to 50 characters.")); + // return false; + //} + + //// Axis range validation + //double xMin = ui->xMinSpinBox->value(); + //double xMax = ui->xMaxSpinBox->value(); + //double yMin = ui->yMinSpinBox->value(); + //double yMax = ui->yMaxSpinBox->value(); + + //if (xMin >= xMax) { + // QMessageBox::warning(this, tr("Validation Error"), tr("X axis minimum value must be less than maximum value.")); + // return false; + //} + + //if (yMin >= yMax) { + // QMessageBox::warning(this, tr("Validation Error"), tr("Y axis minimum value must be less than maximum value.")); + // return false; + //} + + + //// Time parameter validation + //double timeParam = ui->timeParamSpinBox->value(); + //if (timeParam < 0) { + // QMessageBox::warning(this, tr("Validation Error"), tr("Time parameter cannot be negative.")); + // return false; + //} + + //// X axis tick count validation + //int xTickCount = ui->xCountSpinBox->value(); + //if (xTickCount < 2) { + // QMessageBox::warning(this, tr("Validation Error"), tr("X axis tick count must be at least 2.")); + // return false; + //} + + return true; +} + +void AddPolarFileDlg::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); +} \ No newline at end of file diff --git a/src/ui/WorkSpace/AddPolarFileDlg.h b/src/ui/WorkSpace/AddPolarFileDlg.h new file mode 100644 index 00000000..e12fa42a --- /dev/null +++ b/src/ui/WorkSpace/AddPolarFileDlg.h @@ -0,0 +1,42 @@ +#pragma once + +#include "BaseAddFileDlg.h" +#include "workspace/FileEntry.h" + +QT_BEGIN_NAMESPACE +class QComboBox; +class QLineEdit; +class QSpinBox; +class QDoubleSpinBox; +class QListWidget; +class QPushButton; +class QLabel; +QT_END_NAMESPACE + +namespace Ui { + class AddPolarDlg; +} + +class AddPolarFileDlg : public BaseAddFileDlg +{ + Q_OBJECT + +public: + explicit AddPolarFileDlg(QWidget* parent = nullptr); + ~AddPolarFileDlg() override; + +protected: + QString getFileFilter() const override; + QString getDialogTitle() const override; + bool validateSpecificParams() override; + void updateFileInfo(const QString& filePath) override; + +private: + Ui::AddPolarDlg* ui; + int currentCurveIndex_; + QColor selectedColor_; + + FileEntryPolar::ChartProperties chartProperties_; + FileEntryPolar::LineProperties curves_; +}; + diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.cpp b/src/ui/WorkSpace/AddSurfaceFileDlg.cpp index f86100cd..b62842e6 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.cpp +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.cpp @@ -23,19 +23,19 @@ AddSurfaceFileDlg::AddSurfaceFileDlg(QWidget *parent) setupConnections(); // Initialize chart properties with default values - chartProperties_.xCount = 100; - chartProperties_.yCount = 100; - chartProperties_.zCount = 100; + chartProperties_.xCount = 7; + chartProperties_.yCount = 0; + chartProperties_.zCount = 7; chartProperties_.xMin = 0.0; - chartProperties_.xMax = 1.0; + chartProperties_.xMax = 14000; chartProperties_.yMin = 0.0; - chartProperties_.yMax = 1.0; + chartProperties_.yMax = 0.0; chartProperties_.zMin = 0.0; - chartProperties_.zMax = 1.0; + chartProperties_.zMax = 70; chartProperties_.timeParam = 0.0; - chartProperties_.xTitle = "X Axis"; - chartProperties_.yTitle = "Y Axis"; - chartProperties_.zTitle = "Z Axis"; + chartProperties_.xTitle = "Y Axis"; + chartProperties_.yTitle = "Z Axis"; + chartProperties_.zTitle = "X Axis"; // Set default UI values ui->xCountSpinBox->setValue(chartProperties_.xCount); @@ -57,6 +57,12 @@ AddSurfaceFileDlg::AddSurfaceFileDlg(QWidget *parent) // Clear surface properties initially clearSurfaceProperties(); + + ui->dataFormatGroupBox->setVisible(false); + + ui->comboBox_x->setCurrentText("y"); + ui->comboBox_y->setCurrentText("z"); + ui->comboBox_z->setCurrentText("x"); } AddSurfaceFileDlg::~AddSurfaceFileDlg() @@ -81,6 +87,10 @@ void AddSurfaceFileDlg::setupConnections() 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); + + connect(ui->comboBox_x, QOverload::of(&QComboBox::currentTextChanged), this, &AddSurfaceFileDlg::onSurfaceDataChanged); + connect(ui->comboBox_y, QOverload::of(&QComboBox::currentTextChanged), this, &AddSurfaceFileDlg::onSurfaceDataChanged); + connect(ui->comboBox_z, QOverload::of(&QComboBox::currentTextChanged), 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; }); @@ -92,7 +102,7 @@ void AddSurfaceFileDlg::setupConnections() 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->timeParamSpinBox, QOverload::of(&QSpinBox::valueChanged), [this](int 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; }); @@ -109,7 +119,7 @@ QString AddSurfaceFileDlg::getFileFilter() const QString AddSurfaceFileDlg::getDialogTitle() const { - return tr("Select Surface Data File"); + return tr("Add Surface Dialog"); } bool AddSurfaceFileDlg::validateSpecificParams() @@ -176,10 +186,10 @@ void AddSurfaceFileDlg::onAddSurfaceClicked() 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()); + surface.stop = 0; + surface.x = ui->comboBox_x->currentText(); + surface.y = ui->comboBox_y->currentText(); + surface.z = ui->comboBox_z->currentText(); surfaces_.append(surface); addSurfaceToList(surface); @@ -249,6 +259,10 @@ void AddSurfaceFileDlg::onSurfaceDataChanged() if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) { surfaces_[currentSurfaceIndex_].start = ui->surfaceStartSpinBox->value(); surfaces_[currentSurfaceIndex_].stop = ui->surfaceStopSpinBox->value(); + + surfaces_[currentSurfaceIndex_].x = ui->comboBox_x->currentText(); + surfaces_[currentSurfaceIndex_].y = ui->comboBox_y->currentText(); + surfaces_[currentSurfaceIndex_].z = ui->comboBox_z->currentText(); } } @@ -280,6 +294,10 @@ void AddSurfaceFileDlg::updateSurfaceProperties() ui->surfaceNameLineEdit->setText(surface.name); ui->surfaceStartSpinBox->setValue(surface.start); ui->surfaceStopSpinBox->setValue(surface.stop); + + ui->comboBox_x->setCurrentText(surface.x); + ui->comboBox_y->setCurrentText(surface.y); + ui->comboBox_z->setCurrentText(surface.z); selectedColor_ = surface.color; updateColorPreview(ui->surfaceColorButton, selectedColor_); @@ -304,8 +322,8 @@ void AddSurfaceFileDlg::clearSurfaceProperties() { ui->surfaceNameLineEdit->clear(); ui->surfaceStartSpinBox->setValue(0); - ui->surfaceStopSpinBox->setValue(1000); - selectedColor_ = Qt::blue; + ui->surfaceStopSpinBox->setValue(0); + selectedColor_ = QColor(61, 38, 168); updateColorPreview(ui->surfaceColorButton, selectedColor_); ui->surfacePropertiesGroupBox->setEnabled(false); } @@ -318,7 +336,7 @@ QString AddSurfaceFileDlg::generateSurfaceName() const QColor AddSurfaceFileDlg::generateSurfaceColor() const { // Generate different colors for each surface - static const QColor colors[] = { + static const QColor colors[] = { QColor(61, 38, 168), Qt::blue, Qt::red, Qt::green, Qt::magenta, Qt::cyan, Qt::yellow, Qt::darkBlue, Qt::darkRed, Qt::darkGreen, Qt::darkMagenta, Qt::darkCyan, Qt::darkYellow }; @@ -352,6 +370,13 @@ QString AddSurfaceFileDlg::GetDescription() const void AddSurfaceFileDlg::accept() { + QString sName = ui->NameLineEdit->text(); + // Validate table-specific parameters + if (sName.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), tr("Please enter a Surface name.")); + return; + } + if (!validateSpecificParams()) { return; } @@ -366,6 +391,8 @@ void AddSurfaceFileDlg::accept() return; } + fileEntry->SetName(sName); + // Set chart properties fileEntry->SetChartProperties(chartProperties_); diff --git a/src/ui/WorkSpace/AddSurfaceFileDlg.ui b/src/ui/WorkSpace/AddSurfaceFileDlg.ui index 5a91dc25..4ed7c18d 100644 --- a/src/ui/WorkSpace/AddSurfaceFileDlg.ui +++ b/src/ui/WorkSpace/AddSurfaceFileDlg.ui @@ -6,8 +6,8 @@ 0 0 - 800 - 726 + 794 + 748 @@ -22,6 +22,12 @@ + + + 0 + 25 + + Select surface data file... @@ -29,6 +35,12 @@ + + + 0 + 0 + + Browse... @@ -42,68 +54,122 @@ Chart Properties - - + + + + + 0 + 25 + + X Axis Title: - - + + + + + 0 + 25 + + + - + + + + 0 + 25 + + Y Axis Title: - - + + + + + 0 + 25 + + + - + + + + 0 + 25 + + Z Axis Title: - - + + + + + 0 + 25 + + + - + + + + 0 + 25 + + Time Parameter: - - - - 6 - - - -999999.000000000000000 - - - 999999.000000000000000 + + + + + 0 + 25 + - + + + + 0 + 25 + + X Range: - + + + + 0 + 25 + + 6 @@ -117,6 +183,12 @@ + + + 0 + 25 + + to @@ -124,70 +196,12 @@ - - 6 + + + 0 + 25 + - - -999999.000000000000000 - - - 999999.000000000000000 - - - - - - - - - X Count: - - - - - - - 1 - - - 10000 - - - 100 - - - - - - - Y Range: - - - - - - - - - 6 - - - -999999.000000000000000 - - - 999999.000000000000000 - - - - - - - to - - - - - 6 @@ -202,14 +216,26 @@ - + + + + 0 + 25 + + - Y Count: + X Count: - + + + + 0 + 25 + + 1 @@ -222,16 +248,28 @@ - + + + + 0 + 25 + + - Z Range: + Y Range: - + - + + + + 0 + 25 + + 6 @@ -244,14 +282,26 @@ - + + + + 0 + 25 + + to - + + + + 0 + 25 + + 6 @@ -266,14 +316,129 @@ + + + + 0 + 25 + + + + Y Count: + + + + + + + + 0 + 25 + + + + 0 + + + 10000 + + + QAbstractSpinBox::DefaultStepType + + + 1 + + + + + + + + 0 + 25 + + + + Z Range: + + + + + + + + + + 0 + 25 + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + + 0 + 25 + + + + to + + + + + + + + 0 + 25 + + + + 6 + + + -999999.000000000000000 + + + 999999.000000000000000 + + + + + + + + + 0 + 25 + + Z Count: - + + + + 0 + 25 + + 1 @@ -285,6 +450,33 @@ + + + + + + + 100 + 25 + + + + Name: + + + + + + + + 0 + 25 + + + + + + @@ -298,6 +490,12 @@ + + + 0 + 0 + + Add Surface @@ -315,6 +513,12 @@ + + + 0 + 0 + + Remove @@ -327,19 +531,38 @@ Surface Properties - + + + + 0 + 25 + + Name: - + + + + 0 + 25 + + + + + + 0 + 25 + + Color: @@ -360,6 +583,12 @@ + + + 0 + 25 + + Start Point: @@ -367,6 +596,12 @@ + + + 0 + 25 + + 0 @@ -377,6 +612,12 @@ + + + 0 + 25 + + End Point: @@ -384,6 +625,12 @@ + + + 0 + 25 + + 0 @@ -392,6 +639,120 @@ + + + + + 0 + 25 + + + + X-Map: + + + + + + + + 0 + 25 + + + + + x + + + + + y + + + + + z + + + + + + + + + 0 + 25 + + + + Y-Map: + + + + + + + + 0 + 25 + + + + + x + + + + + y + + + + + z + + + + + + + + + 0 + 25 + + + + Z-Map: + + + + + + + + 0 + 25 + + + + + x + + + + + y + + + + + z + + + + @@ -575,4 +936,4 @@ - \ No newline at end of file + diff --git a/src/ui/WorkSpace/AddTableFileDlg.cpp b/src/ui/WorkSpace/AddTableFileDlg.cpp index 5ed650de..571ec371 100644 --- a/src/ui/WorkSpace/AddTableFileDlg.cpp +++ b/src/ui/WorkSpace/AddTableFileDlg.cpp @@ -17,10 +17,14 @@ AddTableFileDlg::AddTableFileDlg(QWidget* parent) : BaseAddFileDlg(FileEntryType::Table, parent) , ui(new Ui::AddTableFileDlg) , m_currentCurveIndex(-1) { - + SetupUI(ui); SetTitle(getDialogTitle()); - setupConnections(); + setupConnections(); + + ui->paramsGroupBox->setVisible(false); + ui->curvesGroupBox->setVisible(false); + ui->hasHeaderCheckBox->setVisible(false); } AddTableFileDlg::~AddTableFileDlg() { @@ -298,35 +302,38 @@ bool AddTableFileDlg::validateSpecificParams() { } // Validate curves - if (m_curves.isEmpty()) { - QMessageBox::warning(this, tr("Warning"), - tr("Please add at least one curve.")); - return false; - } + //if (m_curves.isEmpty()) { + // QMessageBox::warning(this, tr("Warning"), + // tr("Please add at least one curve.")); + // return false; + //} - // Validate each curve's data - for (int i = 0; i < m_curves.size(); ++i) { - const CurveData& curve = m_curves[i]; - - if (curve.name.isEmpty()) { - QMessageBox::warning(this, tr("Warning"), - tr("Curve %1 name cannot be empty.").arg(i + 1)); - return false; - } - - if (curve.data.isEmpty()) { - QMessageBox::warning(this, tr("Warning"), - tr("Curve '%1' data cannot be empty.").arg(curve.name)); - return false; - } - - if (curve.data.size() != headers.size()) { - QMessageBox::warning(this, tr("Warning"), - tr("Curve '%1' data count (%2) doesn't match headers count (%3).") - .arg(curve.name).arg(curve.data.size()).arg(headers.size())); - return false; - } - } + if (m_curves.size() > 0) + { + // Validate each curve's data + for (int i = 0; i < m_curves.size(); ++i) { + const CurveData& curve = m_curves[i]; + + if (curve.name.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), + tr("Curve %1 name cannot be empty.").arg(i + 1)); + return false; + } + + if (curve.data.isEmpty()) { + QMessageBox::warning(this, tr("Warning"), + tr("Curve '%1' data cannot be empty.").arg(curve.name)); + return false; + } + + if (curve.data.size() != headers.size()) { + QMessageBox::warning(this, tr("Warning"), + tr("Curve '%1' data count (%2) doesn't match headers count (%3).") + .arg(curve.name).arg(curve.data.size()).arg(headers.size())); + return false; + } + } + } return true; } @@ -345,13 +352,13 @@ QString AddTableFileDlg::getSelectedFilePath() const { void AddTableFileDlg::accept() { + QString tableName = ui->tableNameEdit->text(); // Validate table-specific parameters - if (ui->tableNameEdit->text().isEmpty()) { + if (tableName.isEmpty()) { QMessageBox::warning(this, tr("Warning"), tr("Please enter a table name.")); return; } - // Create FileEntryTable using factory function auto fileEntry = CreateFileEntryTable(getSelectedFilePath()); if (!fileEntry) { @@ -369,6 +376,8 @@ void AddTableFileDlg::accept() //fileEntry->SetTableHeaders(headers); } + fileEntry->SetName(tableName); + // Set chart properties FileEntryTable::ChartProperties chartProps; chartProps.headerString = headersText; diff --git a/src/ui/WorkSpace/AddTableFileDlg.ui b/src/ui/WorkSpace/AddTableFileDlg.ui index e1db65b6..d05c4d1e 100644 --- a/src/ui/WorkSpace/AddTableFileDlg.ui +++ b/src/ui/WorkSpace/AddTableFileDlg.ui @@ -6,8 +6,8 @@ 0 0 - 676 - 600 + 667 + 533 @@ -29,6 +29,12 @@ + + + 0 + 25 + + File Path: @@ -36,6 +42,12 @@ + + + 0 + 25 + + true @@ -46,6 +58,12 @@ + + + 0 + 25 + + ... @@ -53,6 +71,12 @@ + + + 0 + 25 + + File Name: @@ -60,6 +84,12 @@ + + + 0 + 25 + + - @@ -67,6 +97,12 @@ + + + 0 + 25 + + File Size: @@ -74,6 +110,12 @@ + + + 0 + 25 + + - @@ -88,24 +130,14 @@ Basic Information - - - - 3 - - - 0.000000000000000 - - - 999999.000000000000000 - - - 1.000000000000000 - - - + + + 0 + 25 + + Enter table name... @@ -113,6 +145,12 @@ + + + 0 + 25 + + Table Name: @@ -120,11 +158,27 @@ + + + 0 + 25 + + Time Parameter: + + + + + 0 + 25 + + + + @@ -136,6 +190,12 @@ + + + 0 + 25 + + File has header row @@ -146,6 +206,12 @@ + + + 0 + 25 + + Headers (comma-separated): @@ -153,6 +219,12 @@ + + + 0 + 25 + + e.g., Time, Value1, Value2, Value3... @@ -160,6 +232,12 @@ + + + 0 + 25 + + color: gray; font-size: 11px; @@ -431,6 +509,12 @@ + + + 100 + 30 + + Add File @@ -441,6 +525,12 @@ + + + 100 + 30 + + Cancel diff --git a/src/ui/WorkSpace/WorkSpaceDlg.ui b/src/ui/WorkSpace/WorkSpaceDlg.ui index ed2de71d..2e343f6a 100644 --- a/src/ui/WorkSpace/WorkSpaceDlg.ui +++ b/src/ui/WorkSpace/WorkSpaceDlg.ui @@ -6,7 +6,7 @@ 0 0 - 528 + 632 418 @@ -18,6 +18,12 @@ + + + 80 + 25 + + Name @@ -25,6 +31,12 @@ + + + 0 + 25 + + @@ -39,6 +51,12 @@ + + + 80 + 25 + + Path @@ -46,6 +64,12 @@ + + + 0 + 25 + + @@ -59,6 +83,12 @@ + + + 0 + 25 + + ... @@ -70,6 +100,12 @@ + + + 80 + 25 + + commond Path @@ -77,6 +113,12 @@ + + + 0 + 25 + + @@ -90,6 +132,12 @@ + + + 0 + 25 + + ... @@ -101,6 +149,12 @@ + + + 0 + 25 + + describe @@ -128,6 +182,12 @@ + + + 100 + 30 + + Sure @@ -135,6 +195,12 @@ + + + 100 + 30 + + Cancel diff --git a/src/workspace/FileEntry.cpp b/src/workspace/FileEntry.cpp index b5d39a93..fdcd7578 100644 --- a/src/workspace/FileEntry.cpp +++ b/src/workspace/FileEntry.cpp @@ -44,6 +44,8 @@ std::shared_ptr CreateFileEntry(FileEntryType type, const QString& fi return CreateFileEntryTable(filePath); case FileEntryType::Light: return CreateFileEntryLight(filePath); + case FileEntryType::Polar: + return CreateFileEntryPolar(filePath); default: LOG_ERROR("Unknown FileEntryType: {}", static_cast(type)); return nullptr; @@ -106,6 +108,20 @@ std::shared_ptr CreateFileEntryLight(const QString& filePath) { return fileEntry; } +std::shared_ptr CreateFileEntryPolar(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; +} + // Factory functions for creating empty FileEntry objects (for XML parsing) std::shared_ptr CreateEmptyFileEntry(FileEntryType type) { switch (type) { @@ -117,6 +133,8 @@ std::shared_ptr CreateEmptyFileEntry(FileEntryType type) { return CreateEmptyFileEntryTable(); case FileEntryType::Light: return CreateEmptyFileEntryLight(); + case FileEntryType::Polar: + return CreateEmptyFileEntryPolar(); default: LOG_ERROR("Unknown FileEntryType: {}", static_cast(type)); return nullptr; @@ -147,6 +165,12 @@ std::shared_ptr CreateEmptyFileEntryLight() { return fileEntry; } +std::shared_ptr CreateEmptyFileEntryPolar() { + auto fileEntry = std::make_shared(); + // Don't set path or name - these will be set during XML parsing + return fileEntry; +} + // FileEntrySurface method implementations void FileEntrySurface::SetChartProperties(const ChartProperties& properties) { chartProperties_ = properties; @@ -649,3 +673,134 @@ bool FileEntryCurve::ParseFiles(const tinyxml2::XMLElement* chartElement) { return true; } + + +FileEntryPolar* FileEntryPolar::AsPolar() { + return this; +} + +void FileEntryPolar::SetChartProperties(const ChartProperties& properties) { + chartProperties_ = properties; +} + +const FileEntryPolar::ChartProperties& FileEntryPolar::GetChartProperties() const { + return chartProperties_; +} + +void FileEntryPolar::AddLineProperty(const LineProperty& line) { + lineProperties_.append(line); +} + +void FileEntryPolar::RemoveLineProperty(int index) { + if (index >= 0 && index < lineProperties_.size()) { + lineProperties_.removeAt(index); + } +} + +void FileEntryPolar::SetLineProperty(int index, const LineProperty& line) { + if (index >= 0 && index < lineProperties_.size()) { + lineProperties_[index] = line; + } +} + +const FileEntryPolar::LineProperties& FileEntryPolar::GetLineProperties() const { + return lineProperties_; +} + +bool FileEntryPolar::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) { + if (!scene || !doc) { + LOG_ERROR("Invalid XML parameters"); + return false; + } + + // 创建 元素 + tinyxml2::XMLElement* chartElement = doc->NewElement("chart"); + scene->InsertEndChild(chartElement); + + // 设置chart属性 + chartElement->SetAttribute("name", name_.toUtf8().constData()); + chartElement->SetAttribute("path", fileName_.toUtf8().constData()); + chartElement->SetAttribute("AngularCount", chartProperties_.AngularCount); + chartElement->SetAttribute("RadialCount", chartProperties_.RadialCount); + chartElement->SetAttribute("AngularTitle", chartProperties_.AngularTitle.toUtf8().constData()); + chartElement->SetAttribute("RadialTitle", chartProperties_.RadialTitle.toUtf8().constData()); + chartElement->SetAttribute("AngularMin", chartProperties_.AngularMin); + chartElement->SetAttribute("AngularMax", chartProperties_.AngularMax); + chartElement->SetAttribute("RadialMin", chartProperties_.RadialMin); + chartElement->SetAttribute("RadialMax", chartProperties_.RadialMax); + chartElement->SetAttribute("AngularUnit", chartProperties_.AngularUnit.toUtf8().constData()); + chartElement->SetAttribute("RadialUnit", chartProperties_.RadialUnit.toUtf8().constData()); + chartElement->SetAttribute("t", chartProperties_.timeParam); + + // 为每个CurveProperty创建元素 + for (const auto& curve : lineProperties_) { + tinyxml2::XMLElement* curveElement = doc->NewElement("curve"); + chartElement->InsertEndChild(curveElement); + + curveElement->SetAttribute("name", curve.name.toUtf8().constData()); + curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData()); + curveElement->SetAttribute("Angular", curve.Angular); + curveElement->SetAttribute("Radial", curve.Radial); + } + + return true; +} + +bool FileEntryPolar::ParseFiles(const tinyxml2::XMLElement* chartElement) { + if (!chartElement) { + LOG_ERROR("Invalid XML element"); + return false; + } + + // 解析chart属性 + const char* nameAttr = chartElement->Attribute("name"); + const char* pathAttr = chartElement->Attribute("path"); + if (nameAttr) name_ = QString::fromUtf8(nameAttr); + if (pathAttr) { + QString fullPath = QString::fromUtf8(pathAttr); + QFileInfo fileInfo(fullPath); + fileName_ = fileInfo.fileName(); + path_ = fileInfo.absolutePath(); + } + + chartProperties_.AngularCount = chartElement->IntAttribute("AngularCount", 0); + chartProperties_.RadialCount = chartElement->IntAttribute("RadialCount", 0); + + const char* AngularTitleAttr = chartElement->Attribute("AngularTitle"); + const char* RadialTitleAttr = chartElement->Attribute("RadialTitle"); + if (AngularTitleAttr) chartProperties_.AngularTitle = QString::fromUtf8(AngularTitleAttr); + if (RadialTitleAttr) chartProperties_.RadialTitle = QString::fromUtf8(RadialTitleAttr); + + chartProperties_.AngularMin = chartElement->DoubleAttribute("AngularMin", 0.0); + chartProperties_.AngularMax = chartElement->DoubleAttribute("AngularMax", 0.0); + chartProperties_.RadialMin = chartElement->DoubleAttribute("RadialMin", 0.0); + chartProperties_.RadialMax = chartElement->DoubleAttribute("RadialMax", 0.0); + + const char* AngularUnitAttr = chartElement->Attribute("AngularUnit"); + const char* RadialUnitAttr = chartElement->Attribute("RadialUnit"); + if (AngularUnitAttr) chartProperties_.AngularUnit = QString::fromUtf8(AngularUnitAttr); + if (RadialUnitAttr) chartProperties_.RadialUnit = QString::fromUtf8(RadialUnitAttr); + + chartProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0); + + // 解析所有元素 + lineProperties_.clear(); + for (const tinyxml2::XMLElement* curveElement = chartElement->FirstChildElement("curve"); + curveElement != nullptr; + curveElement = curveElement->NextSiblingElement("curve")) { + + LineProperty prop; + + const char* curveNameAttr = curveElement->Attribute("name"); + const char* colorAttr = curveElement->Attribute("color"); + if (curveNameAttr) prop.name = QString::fromUtf8(curveNameAttr); + if (colorAttr) prop.color = StringToQColor(QString::fromUtf8(colorAttr)); + + prop.Angular = curveElement->IntAttribute("Angular", 0.0); + prop.Radial = curveElement->IntAttribute("Radial", 0.0); + + lineProperties_.append(prop); + } + + return true; +} \ No newline at end of file diff --git a/src/workspace/FileEntry.h b/src/workspace/FileEntry.h index 2f1efbbb..4b59b42e 100644 --- a/src/workspace/FileEntry.h +++ b/src/workspace/FileEntry.h @@ -8,7 +8,8 @@ enum class FileEntryType { Curve, Surface, Table, - Light + Light, + Polar }; enum class ChartType { @@ -37,6 +38,7 @@ inline const char* FileEntryTypeToString(FileEntryType t) { case FileEntryType::Surface: return "surface"; case FileEntryType::Table: return "table"; case FileEntryType::Light: return "light"; + case FileEntryType::Polar: return "polar"; } return "unknown"; } @@ -47,6 +49,7 @@ inline bool FileEntryTypeFromString(const char* s, FileEntryType& out) { if (0 == strcmp(s, "surface")) { out = FileEntryType::Surface; return true; } if (0 == strcmp(s, "table")) { out = FileEntryType::Table; return true; } if (0 == strcmp(s, "light")) { out = FileEntryType::Light; return true; } + if (0 == strcmp(s, "polar")) { out = FileEntryType::Polar; return true; } return false; } @@ -54,6 +57,7 @@ class FileEntryCurve; class FileEntryLight; class FileEntrySurface; class FileEntryTable; +class FileEntryPolar; class FileEntry { public: @@ -75,6 +79,7 @@ public: virtual FileEntryLight* AsLight() { return nullptr; } virtual FileEntrySurface* AsSurface() { return nullptr; } virtual FileEntryTable* AsTable() { return nullptr; } + virtual FileEntryPolar* AsPolar() { return nullptr; } virtual bool ParseFiles(const tinyxml2::XMLElement* element) { return false; } virtual bool SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) { return false; } @@ -95,6 +100,7 @@ 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 CreateFileEntryPolar(const QString& filePath); // Factory functions for creating empty FileEntry objects (for XML parsing) std::shared_ptr CreateEmptyFileEntry(FileEntryType type); @@ -102,6 +108,7 @@ std::shared_ptr CreateEmptyFileEntryCurve(); std::shared_ptr CreateEmptyFileEntrySurface(); std::shared_ptr CreateEmptyFileEntryTable(); std::shared_ptr CreateEmptyFileEntryLight(); +std::shared_ptr CreateEmptyFileEntryPolar(); class FileEntryCurve : public FileEntry { @@ -295,3 +302,52 @@ private: LightRowProperties lightProperties_; }; +class FileEntryPolar : public FileEntry { +public: + struct ChartProperties { + int AngularCount; + int RadialCount; + QString AngularTitle; + QString RadialTitle; + double AngularMin; + double AngularMax; + double RadialMin; + double RadialMax; + QString AngularUnit; + QString RadialUnit; + double timeParam; // 对应XML的t + }; + + struct LineProperty { + QString name; + QColor color; + int Angular; + int Radial; + }; + + using LineProperties = QList; + +public: + FileEntryPolar() { type_ = FileEntryType::Polar; } + + // Chart properties management + void SetChartProperties(const ChartProperties& properties); + const ChartProperties& GetChartProperties() const; + + // Line properties management + void AddLineProperty(const LineProperty& line); + void RemoveLineProperty(int index); + void SetLineProperty(int index, const LineProperty& line); + const LineProperties& GetLineProperties() const; + + // Type conversion + FileEntryPolar* AsPolar() override; + + // XML处理方法 + bool SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) override; + bool ParseFiles(const tinyxml2::XMLElement* element) override; + +private: + ChartProperties chartProperties_; + LineProperties lineProperties_; +}; \ No newline at end of file diff --git a/src/workspace/WorkSpace.cpp b/src/workspace/WorkSpace.cpp index ed65989c..9ec1825d 100644 --- a/src/workspace/WorkSpace.cpp +++ b/src/workspace/WorkSpace.cpp @@ -221,6 +221,9 @@ bool WorkSpace::SetFileEntryCount(FileEntryType type, int count) { case FileEntryType::Light: fileEntry = std::make_shared(); break; + case FileEntryType::Polar: + fileEntry = std::make_shared(); + break; default: return false; // Invalid type }