DYTSrouce/src/ui/WorkSpace/AddCurveFileDlg.cpp

538 lines
20 KiB
C++
Raw Normal View History

2025-10-22 17:40:44 +00:00
#include "AddCurveFileDlg.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
2025-10-23 00:21:45 +00:00
#include <QColorDialog>
#include <QListWidget>
2025-10-22 17:40:44 +00:00
2025-10-26 07:55:41 +00:00
#include "workspace/WorkSpace.h"
#include "workspace/WorkSpaceManager.h"
2025-10-22 17:40:44 +00:00
#include "ui_AddCurveFileDlg.h"
AddCurveFileDlg::AddCurveFileDlg(QWidget* parent)
: BaseAddFileDlg(FileEntryType::Curve, parent)
2025-10-23 00:21:45 +00:00
, ui(new Ui::AddCurveFileDlg)
, currentCurveIndex_(-1)
, selectedColor_(255, 0, 0) { // Default to red color
2025-10-22 17:40:44 +00:00
2025-10-23 00:21:45 +00:00
SetupUI(ui);
2025-10-22 17:40:44 +00:00
SetTitle(getDialogTitle());
2025-10-23 00:21:45 +00:00
setupConnections();
2025-10-22 17:40:44 +00:00
}
AddCurveFileDlg::~AddCurveFileDlg() {
delete ui;
}
void AddCurveFileDlg::setupConnections() {
2025-10-23 00:21:45 +00:00
// File selection connections
2025-10-26 07:55:41 +00:00
connect(ui->selectFileBtn, &QToolButton::clicked, this, &AddCurveFileDlg::OnSelectFile);
2025-10-23 00:21:45 +00:00
// Curve management connections
connect(ui->addCurveBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onAddCurveClicked);
connect(ui->removeCurveBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onRemoveCurveClicked);
connect(ui->curveListWidget, &QListWidget::currentRowChanged, this, &AddCurveFileDlg::onCurveSelectionChanged);
2025-10-26 07:55:41 +00:00
connect(ui->curveListWidget, &QListWidget::itemClicked, this, &AddCurveFileDlg::onCurveListWidgetItemClicked);
2025-10-23 00:21:45 +00:00
// Curve properties connections
connect(ui->colorButton, &QPushButton::clicked, this, &AddCurveFileDlg::onColorButtonClicked);
connect(ui->curveNameEdit, &QLineEdit::textChanged, this, &AddCurveFileDlg::onCurveNameChanged);
connect(ui->dataStartSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
connect(ui->dataStopSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
// Dialog buttons
connect(ui->addBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onSure);
2025-10-22 17:40:44 +00:00
connect(ui->cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
}
2025-10-23 00:21:45 +00:00
void AddCurveFileDlg::updateFileInfo(const QString& filePath) {
QFileInfo fileInfo(filePath);
if (fileInfo.exists()) {
ui->fileNameValue->setText(fileInfo.fileName());
2025-10-26 07:55:41 +00:00
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);
2025-10-23 00:21:45 +00:00
} else {
ui->fileNameValue->setText("-");
ui->fileSizeValue->setText("-");
}
2025-10-26 07:55:41 +00:00
ui->filePathEdit->setText(filePath);
2025-10-22 17:40:44 +00:00
}
2025-10-23 00:21:45 +00:00
void AddCurveFileDlg::onAddCurveClicked() {
// Save current curve properties if any curve is selected
if (currentCurveIndex_ >= 0) {
saveCurveProperties();
}
// Create new curve with default properties
2025-10-26 07:55:41 +00:00
FileEntryCurve::CurveProperty newCurve;
2025-10-23 00:21:45 +00:00
newCurve.name = generateCurveName();
newCurve.color = generateCurveColor();
newCurve.start = 1;
newCurve.stop = 241;
// Add to curves list and UI
curves_.append(newCurve);
2025-10-26 07:55:41 +00:00
// Add to UI list widget
QListWidgetItem* item = new QListWidgetItem(QString("%1 [%2,%3] (%4,%5,%6)")
.arg(newCurve.name)
.arg(newCurve.start)
.arg(newCurve.stop)
.arg(newCurve.color.red())
.arg(newCurve.color.green())
.arg(newCurve.color.blue()));
ui->curveListWidget->addItem(item);
++currentCurveIndex_;
2025-10-23 00:21:45 +00:00
// Select the new curve
ui->curveListWidget->setCurrentRow(curves_.size() - 1);
}
void AddCurveFileDlg::onRemoveCurveClicked() {
int currentRow = ui->curveListWidget->currentRow();
if (currentRow < 0 || currentRow >= curves_.size()) {
return;
}
// Don't allow removing the last curve
2025-10-26 07:55:41 +00:00
if (curves_.size() <= 0) {
2025-10-23 00:21:45 +00:00
QMessageBox::information(this, "Information", "At least one curve must remain.");
return;
}
// Remove from curves list and UI
curves_.removeAt(currentRow);
delete ui->curveListWidget->takeItem(currentRow);
// Update current index
if (currentRow >= curves_.size()) {
currentRow = curves_.size() - 1;
}
if (currentRow >= 0) {
ui->curveListWidget->setCurrentRow(currentRow);
} else {
currentCurveIndex_ = -1;
clearCurveProperties();
enableCurveProperties(false);
}
}
2025-10-26 07:55:41 +00:00
void AddCurveFileDlg::onCurveListWidgetItemClicked(QListWidgetItem* item) {
if (!item) {
return;
}
// 获取点击项的索引
int clickedIndex = ui->curveListWidget->row(item);
// 如果点击的是当前选中项,可以进入编辑模式
if (clickedIndex == currentCurveIndex_) {
ui->curveNameEdit->setText(curves_[currentCurveIndex_].name);
ui->dataStartSpinBox->setValue(curves_[currentCurveIndex_].start);
ui->dataStopSpinBox->setValue(curves_[currentCurveIndex_].stop);
updateColorPreview(curves_[currentCurveIndex_].color);
// 启用曲线属性编辑
enableCurveProperties(true);
// 将焦点设置到曲线名称编辑框,方便用户直接编辑
ui->curveNameEdit->setFocus();
ui->curveNameEdit->selectAll();
} else {
// 如果点击的是不同的项,更新选择
onCurveSelectionChanged();
}
}
2025-10-23 00:21:45 +00:00
void AddCurveFileDlg::onCurveSelectionChanged() {
int currentRow = ui->curveListWidget->currentRow();
// Save previous curve properties
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
saveCurveProperties();
}
currentCurveIndex_ = currentRow;
if (currentRow >= 0 && currentRow < curves_.size()) {
// Load selected curve properties
updateCurveProperties();
enableCurveProperties(true);
} else {
clearCurveProperties();
enableCurveProperties(false);
}
}
void AddCurveFileDlg::onCurveNameChanged() {
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
QString newName = ui->curveNameEdit->text();
curves_[currentCurveIndex_].name = newName;
// Update list item text
QListWidgetItem* item = ui->curveListWidget->item(currentCurveIndex_);
if (item) {
item->setText(QString("%1 [%2,%3] (%4,%5,%6)")
.arg(newName)
.arg(curves_[currentCurveIndex_].start)
.arg(curves_[currentCurveIndex_].stop)
.arg(curves_[currentCurveIndex_].color.red())
.arg(curves_[currentCurveIndex_].color.green())
.arg(curves_[currentCurveIndex_].color.blue()));
}
}
}
void AddCurveFileDlg::onCurveDataChanged() {
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
curves_[currentCurveIndex_].start = ui->dataStartSpinBox->value();
curves_[currentCurveIndex_].stop = ui->dataStopSpinBox->value();
// Update list item text
QListWidgetItem* item = ui->curveListWidget->item(currentCurveIndex_);
if (item) {
item->setText(QString("%1 [%2,%3] (%4,%5,%6)")
.arg(curves_[currentCurveIndex_].name)
.arg(curves_[currentCurveIndex_].start)
.arg(curves_[currentCurveIndex_].stop)
.arg(curves_[currentCurveIndex_].color.red())
.arg(curves_[currentCurveIndex_].color.green())
.arg(curves_[currentCurveIndex_].color.blue()));
}
}
}
void AddCurveFileDlg::onColorButtonClicked() {
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
QColor color = QColorDialog::getColor(curves_[currentCurveIndex_].color, this, "Select Curve Color");
if (color.isValid()) {
curves_[currentCurveIndex_].color = color;
selectedColor_ = color;
updateColorPreview(color);
// Update list item text
QListWidgetItem* item = ui->curveListWidget->item(currentCurveIndex_);
if (item) {
item->setText(QString("%1 [%2,%3] (%4,%5,%6)")
.arg(curves_[currentCurveIndex_].name)
.arg(curves_[currentCurveIndex_].start)
.arg(curves_[currentCurveIndex_].stop)
.arg(color.red())
.arg(color.green())
.arg(color.blue()));
}
}
}
}
2025-10-26 07:55:41 +00:00
void AddCurveFileDlg::addCurveToList(const FileEntryCurve::CurveProperty& curve) {
2025-10-23 00:21:45 +00:00
QString itemText = QString("%1 [%2,%3] (%4,%5,%6)")
.arg(curve.name)
.arg(curve.start)
.arg(curve.stop)
.arg(curve.color.red())
.arg(curve.color.green())
.arg(curve.color.blue());
ui->curveListWidget->addItem(itemText);
}
void AddCurveFileDlg::updateCurveProperties() {
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
2025-10-26 07:55:41 +00:00
const FileEntryCurve::CurveProperty& curve = curves_[currentCurveIndex_];
2025-10-23 00:21:45 +00:00
ui->curveNameEdit->setText(curve.name);
ui->dataStartSpinBox->setValue(curve.start);
ui->dataStopSpinBox->setValue(curve.stop);
selectedColor_ = curve.color;
updateColorPreview(curve.color);
}
}
void AddCurveFileDlg::saveCurveProperties() {
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
curves_[currentCurveIndex_].name = ui->curveNameEdit->text();
curves_[currentCurveIndex_].start = ui->dataStartSpinBox->value();
curves_[currentCurveIndex_].stop = ui->dataStopSpinBox->value();
curves_[currentCurveIndex_].color = selectedColor_;
}
}
void AddCurveFileDlg::clearCurveProperties() {
ui->curveNameEdit->clear();
ui->dataStartSpinBox->setValue(1);
ui->dataStopSpinBox->setValue(241);
selectedColor_ = QColor(255, 0, 0);
updateColorPreview(selectedColor_);
}
void AddCurveFileDlg::enableCurveProperties(bool enabled) {
ui->curvePropertiesGroupBox->setEnabled(enabled);
}
QString AddCurveFileDlg::generateCurveName() {
return tr("Curve %1").arg(curves_.size() + 1);
}
QColor AddCurveFileDlg::generateCurveColor() const {
// Generate different colors for each curve
static const QColor colors[] = {
QColor(255, 0, 0), // Red
QColor(0, 255, 0), // Green
QColor(0, 0, 255), // Blue
QColor(255, 255, 0), // Yellow
QColor(255, 0, 255), // Magenta
QColor(0, 255, 255), // Cyan
QColor(255, 128, 0), // Orange
QColor(128, 0, 255), // Purple
};
int colorIndex = curves_.size() % (sizeof(colors) / sizeof(colors[0]));
return colors[colorIndex];
}
void AddCurveFileDlg::updateColorPreview(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->colorPreview->setStyleSheet(styleSheet);
}
2025-10-22 17:40:44 +00:00
bool AddCurveFileDlg::validateSpecificParams() {
2025-10-23 00:21:45 +00:00
// File path validation
2025-10-26 07:55:41 +00:00
const QString& selectFilePath = getSelectedFilePath();
if (selectFilePath.isEmpty()) {
2025-10-23 00:21:45 +00:00
QMessageBox::warning(this, tr("Validation Error"), tr("Please select a data file."));
2025-10-22 17:40:44 +00:00
return false;
}
2025-10-23 00:21:45 +00:00
// File existence validation
2025-10-26 07:55:41 +00:00
QFileInfo fileInfo(selectFilePath);
2025-10-22 17:40:44 +00:00
if (!fileInfo.exists()) {
2025-10-23 00:21:45 +00:00
QMessageBox::warning(this, tr("Validation Error"), tr("Selected file does not exist."));
2025-10-22 17:40:44 +00:00
return false;
}
2025-10-23 00:21:45 +00:00
// 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) {
2025-10-26 07:55:41 +00:00
const FileEntryCurve::CurveProperty& curve = curves_[i];
2025-10-23 00:21:45 +00:00
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
if (curve.start < 1 || curve.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.start > curve.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.stop - curve.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.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;
}
}
// 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;
}
2025-10-27 00:35:04 +00:00
2025-10-23 00:21:45 +00:00
// 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;
}
2025-10-27 00:35:04 +00:00
2025-10-22 17:40:44 +00:00
return true;
}
QString AddCurveFileDlg::getFileFilter() const {
2025-10-23 00:21:45 +00:00
return "Data Files (*.txt *.csv *.dat);;All Files (*.*)";
2025-10-22 17:40:44 +00:00
}
QString AddCurveFileDlg::getDialogTitle() const {
2025-10-23 00:21:45 +00:00
return "Add Curve Data File";
2025-10-22 17:40:44 +00:00
}
2025-10-23 00:21:45 +00:00
void AddCurveFileDlg::onSure() {
if (validateSpecificParams()) {
2025-10-26 07:55:41 +00:00
// Create FileEntryCurve object using factory function
auto fileEntryCurve = CreateFileEntryCurve(getSelectedFilePath());
if (!fileEntryCurve) {
QMessageBox::warning(this, tr("Error"), tr("Failed to create file entry"));
return;
}
// Set curve properties
fileEntryCurve->SetName(ui->chartNameEdit->text());
// Set chart properties
FileEntryCurve::ChartProperties chartProps;
chartProps.xCount = ui->xCountSpinBox->value();
2025-10-27 00:35:04 +00:00
chartProps.yCount = ui->yCountSpinBox->value();
2025-10-26 07:55:41 +00:00
chartProps.xTitle = ui->xTitleEdit->text();
chartProps.yTitle = ui->yTitleEdit->text();
chartProps.xMin = ui->xMinSpinBox->value();
chartProps.xMax = ui->xMaxSpinBox->value();
chartProps.yMin = ui->yMinSpinBox->value();
chartProps.yMax = ui->yMaxSpinBox->value();
chartProps.timeParam = ui->timeParamSpinBox->value();
fileEntryCurve->SetChartProperties(chartProps);
// Add curve properties
for (const auto& curve : curves_) {
fileEntryCurve->AddCurveProperty(curve);
}
// Get current workspace
WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent();
if (!workspace) {
QMessageBox::warning(this, tr("Error"), tr("Unable to get current workspace"));
return;
}
// Add FileEntryCurve to workspace using new SetFileEntry method
auto result = workspace->SetFileEntry(fileEntryCurve);
if (result != WorkSpace::FileEntryResult::Ok) {
QString errorMsg;
switch (result) {
case WorkSpace::FileEntryResult::LimitExceeded:
errorMsg = tr("Curve file count has reached the limit (9 files)");
break;
case WorkSpace::FileEntryResult::Duplicate:
errorMsg = tr("File already exists");
break;
case WorkSpace::FileEntryResult::CopyFailed:
errorMsg = tr("File copy failed");
break;
case WorkSpace::FileEntryResult::InvalidFile:
errorMsg = tr("Invalid file");
break;
default:
errorMsg = tr("Failed to add file");
break;
}
QMessageBox::warning(this, tr("Error"), errorMsg);
return;
}
2025-10-23 00:21:45 +00:00
accept();
}
2025-10-26 07:55:41 +00:00
}