diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 8b0ce0a..062a8e0 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -142,7 +142,7 @@ void MainWindow::initMainWindow() void MainWindow::initAction() { - connect(ui->action_new_measurement_analysis, &QAction::triggered, this, [this]() { + auto new_measurement_analysis_handler = [this]() { NewMeasureAnalysisDlg new_measure_analysis_dlg; if (QDialog::Accepted == new_measure_analysis_dlg.exec()) { auto project_model = MeasureAnalysisProjectModelList::GetCurrentProjectModel(); @@ -174,7 +174,9 @@ void MainWindow::initAction() count_task->StartTask(); } } - }); + }; + + connect(ui->action_new_measurement_analysis, &QAction::triggered, this, new_measurement_analysis_handler); connect(ui->action_manage_measurement_analysis, &QAction::triggered, this->_action_central_dock_widget, &QAction::triggered); connect(ui->action_device_config_mrg, &QAction::triggered, this, []() { QDialog device_cfg_mrg_dlg; @@ -219,21 +221,34 @@ void MainWindow::initAction() } if ( !view_exist ) { ads::CDockWidget* dock_widget = new ads::CDockWidget(view->GetViewName()); + auto central_area = _dock_manager->centralWidget()->dockAreaWidget(); + CDockAreaWidget* dock_area = _dock_manager->addDockWidget(ads::DockWidgetArea::CenterDockWidgetArea, dock_widget, central_area); + dock_widget->hide(); + dock_widget->setWidget(view); dock_widget->setMinimumSizeHintMode(ads::CDockWidget::MinimumSizeHintFromContentMinimumSize); - if (view->GetAnalyzeViewType() == MeasureAnalysisView::ViewType::DataTable) { + if (view->GetAnalyzeViewType() == MeasureAnalysisViewType::DataTable) { dock_widget->setFeatures(dock_widget->features() | ads::CDockWidget::DockWidgetDeleteOnClose); _menu_view_data_table_list->addAction(dock_widget->toggleViewAction()); } else { - dock_widget->setFeatures(dock_widget->features() | ads::CDockWidget::CustomCloseHandling); + // dock_widget->setFeatures(dock_widget->features() | ads::CDockWidget::CustomCloseHandling); dock_widget->setProperty("TakeWidget", true); - connect(dock_widget, &CDockWidget::closeRequested, [dock_widget](){ - dock_widget->takeWidget(); - dock_widget->deleteDockWidget(); - }); + // connect(dock_widget, &CDockWidget::closeRequested, [dock_widget](){ + // dock_widget->takeWidget(); + // dock_widget->deleteDockWidget(); + // }); + _menu_view_analysis_view_list->addAction(dock_widget->toggleViewAction()); } - auto central_area = _dock_manager->centralWidget()->dockAreaWidget(); - _dock_manager->addDockWidget(ads::DockWidgetArea::CenterDockWidgetArea, dock_widget, central_area); + + dock_widget->show(); + central_area->update(); + central_area->updateGeometry(); + dock_area->update(); + dock_area->updateGeometry(); + dock_widget->update(); + dock_widget->updateGeometry(); + view->update(); + view->updateGeometry(); } } }); @@ -252,6 +267,8 @@ void MainWindow::initAction() } } }); + + connect(_tree_measure_analysis, &MeasureAnalysisTree::TreeWidget::newMeasureAnalysisProject, new_measurement_analysis_handler); } void MainWindow::applyStyleSheet() diff --git a/src/MeasureAnalysisActions.cpp b/src/MeasureAnalysisActions.cpp index cd8b476..da4a120 100644 --- a/src/MeasureAnalysisActions.cpp +++ b/src/MeasureAnalysisActions.cpp @@ -96,6 +96,9 @@ void MeasureAnalysisActions::SetActionsAvailable(const TreeItemType &item_type) case TreeItemType::ParticleData: _act_add_analyze_view->setEnabled(true); break; + case TreeItemType::AnalyzeDataGroup: + _act_add_analyze_view->setEnabled(true); + break; case TreeItemType::ParticleCountData: _act_add_analyze_view->setEnabled(true); break; diff --git a/src/MeasureAnalysisDataTableView.cpp b/src/MeasureAnalysisDataTableView.cpp index d9034c9..3bddfc1 100644 --- a/src/MeasureAnalysisDataTableView.cpp +++ b/src/MeasureAnalysisDataTableView.cpp @@ -10,7 +10,7 @@ MeasureAnalysisDataTableView::MeasureAnalysisDataTableView(QWidget* parent) , _block_size(100) , _buffer_size(50) { - this->setAnalyzeViewType(ViewType::DataTable); + this->setAnalyzeViewType(MeasureAnalysisViewType::DataTable); QHBoxLayout* layout = new QHBoxLayout(this); // 创建表格视图 _tableView = new VirtualTableView(this); diff --git a/src/MeasureAnalysisParticleCountPlotView.cpp b/src/MeasureAnalysisParticleCountPlotView.cpp index 11b39bf..b502195 100644 --- a/src/MeasureAnalysisParticleCountPlotView.cpp +++ b/src/MeasureAnalysisParticleCountPlotView.cpp @@ -2,31 +2,102 @@ #include "qcustomplot.h" #include "csv.h" #include +#include +#include + +QColor getDistinctColorForManyCurves(int curveIndex) +{ + // 1. 定义基础色相(覆盖不同主色系,0-360度) + const QList baseHues = { + 0, // 红色 + 30, // 橙色 + 60, // 黄色 + 90, // 黄绿色 + 120, // 绿色 + 150, // 青绿色 + 180, // 青色 + 210, // 天蓝色 + 240, // 蓝色 + 270, // 紫色 + 300, // 洋红色 + 330 // 玫红色 + }; + + // 2. 定义不同的饱和度/明度组合(避免颜色太暗/太灰) + const QList> sVCombinations = { + {85, 90}, // 高饱和、高明度 + {70, 85}, // 中高饱和、中高明度 + {85, 75}, // 高饱和、中明度 + {60, 80}, // 中饱和、中高明度 + {75, 70}, // 中高饱和、中明度 + {90, 80} // 极高饱和、中高明度 + }; + + // 3. 计算当前曲线对应的色相和饱和度/明度 + int hueIndex = curveIndex % baseHues.size(); // 循环使用基础色相 + int svIndex = (curveIndex / baseHues.size()) % sVCombinations.size(); // 循环使用饱和度/明度组合 + + // 4. 获取HSV参数(色相0-360,饱和度0-255,明度0-255) + int hue = baseHues[hueIndex]; + int saturation = sVCombinations[svIndex].first * 255 / 100; // 转换为0-255范围 + int value = sVCombinations[svIndex].second * 255 / 100; // 转换为0-255范围 + + // 5. 生成并返回颜色(HSV转RGB) + QColor color; + color.setHsv(hue, saturation, value); + + // 额外优化:避免极浅/极暗的颜色(保证曲线可见) + if (value < 50 * 255 / 100) { + value = 50 * 255 / 100; + color.setHsv(hue, saturation, value); + } + + return color; +} MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidget* parent) : MeasureAnalysisView { parent } { - this->setAnalyzeViewType(ViewType::CountSpectrum); + this->setAnalyzeViewType(MeasureAnalysisViewType::CountSpectrum); + QHBoxLayout* layout = new QHBoxLayout(this); _custom_plot = new QCustomPlot(this); - _custom_plot->setGeometry(0, 0, this->width(), this->height()); + layout->addWidget(_custom_plot); + + setupCustomPlot(); } void MeasureAnalysisParticleCountPlotView::SetAnalyzeDataFilename(const QMap &data_files_set) { for (auto it = data_files_set.begin(); it != data_files_set.end(); ++it) { - loadDataFromFile(it.value().toString()); + loadDataFromFile(it.key(), it.value().toString()); } + _custom_plot->update(); + this->update(); } void MeasureAnalysisParticleCountPlotView::setupCustomPlot() { + _custom_plot->setNotAntialiasedElements(QCP::aeAll); + _custom_plot->setNoAntialiasingOnDrag(true); + _custom_plot->xAxis->setLabel(QString(QStringLiteral(u"道址"))); + _custom_plot->xAxis->setVisible(true); _custom_plot->yAxis->setLabel(QString(QStringLiteral(u"计数"))); + _custom_plot->yAxis->setVisible(true); + + _custom_plot->xAxis2->setVisible(true); + _custom_plot->xAxis2->setTickLabels(false); + _custom_plot->xAxis2->setTickLength(0); ; + _custom_plot->yAxis2->setVisible(true); + _custom_plot->yAxis2->setTickLabels(false); + _custom_plot->yAxis2->setTickLength(0); ; + _custom_plot->legend->setVisible(true); + _custom_plot->legend->setSelectableParts(QCPLegend::spItems); } -void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filename) +void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& data_name, const QString& filename) { std::string address_str = QString(QStringLiteral(u"道址")).toStdString(); std::string count_str = QString(QStringLiteral(u"计数")).toStdString(); @@ -37,7 +108,7 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filen io::double_quote_escape<',', '"'>, io::throw_on_overflow, io::empty_line_comment - > reader(filename.toUtf8().toStdString()); + > reader(QStrToSysPath(filename)); reader.read_header(io::ignore_extra_column, address_str, count_str); int address; @@ -49,9 +120,10 @@ void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filen } auto graph = _custom_plot->addGraph(); - // graph->setPen(QPen(Qt::red)); - // graph->setBrush(QBrush(Qt::red)); + graph->setName(data_name); + graph->setPen(QPen(getDistinctColorForManyCurves(_custom_plot->graphCount()))); graph->setData(x, y, true); + graph->rescaleAxes(); _custom_plot->replot(); } diff --git a/src/MeasureAnalysisParticleCountPlotView.h b/src/MeasureAnalysisParticleCountPlotView.h index 322a190..370ca5f 100644 --- a/src/MeasureAnalysisParticleCountPlotView.h +++ b/src/MeasureAnalysisParticleCountPlotView.h @@ -17,7 +17,7 @@ public: private: void setupCustomPlot(); - void loadDataFromFile(const QString& filename); + void loadDataFromFile(const QString &data_name, const QString& filename); private: QCustomPlot* _custom_plot { nullptr }; diff --git a/src/MeasureAnalysisTree.cpp b/src/MeasureAnalysisTree.cpp index eb40780..c3f3c6d 100644 --- a/src/MeasureAnalysisTree.cpp +++ b/src/MeasureAnalysisTree.cpp @@ -121,25 +121,17 @@ void TreeWidget::SetConnectActions(MeasureAnalysisActions* const actions_analyze emit newMeasureAnalysisProject(); }); connect(actions_analyze, &MeasureAnalysisActions::rmMeasureAnalysisProject, [this]() { - removeAnalyzeItem(); + removeTreeItem(this->currentItem()); }); connect(actions_analyze, &MeasureAnalysisActions::modifyMeasureAnalysisProject, [this]() { }); connect(actions_analyze, &MeasureAnalysisActions::addAnalyzeView, [this]() { - QString project_name = QString(); - MeasureAnalysisViewType view_type = MeasureAnalysisViewType::None; - QTreeWidgetItem* current_item = this->currentItem(); - if (!current_item) { - return; - } - TreeItem* - - emit newMeasureAnalysisView(MeasureAnalysisView::GetAnalyzeViewTypeText(view_type)); + onNewMeasureAnalysisView(); }); connect(actions_analyze, &MeasureAnalysisActions::rmAnalyzeView, [this]() { - removeAnalyzeItem(); + removeTreeItem(this->currentItem()); }); connect(actions_analyze, &MeasureAnalysisActions::modifyAnalyzeView, [this]() { }); @@ -150,6 +142,41 @@ void TreeWidget::AddProjectModel(MeasureAnalysisProjectModel* model) if (model) { auto new_item = new TreeMeasureAnalysisProjectItem(model->GetProjectName(), model->GetDescriptionInfo()); if (model) { + TreeItem* tree_item_ctrl_group = new_item->GetMeasureCtrlGroupItem(); + if (tree_item_ctrl_group) { + const QString& measure_device_params_cfg_filename = model->GetMeasureDeviceParamsCfgFilename(); + QMap data_files_set; + data_files_set[QStringLiteral(u"设备参数")] = measure_device_params_cfg_filename; + TreeItem* new_item_dev_params_cfg_data = new TreeItem; + new_item_dev_params_cfg_data->SetName(QStringLiteral(u"测量设备参数")); + new_item_dev_params_cfg_data->SetType(TreeItemType::DeviceConfig); + new_item_dev_params_cfg_data->SetDescription(measure_device_params_cfg_filename); + new_item_dev_params_cfg_data->setData(0, Qt::UserRole, data_files_set); + tree_item_ctrl_group->addChild(new_item_dev_params_cfg_data); + + const QString& enery_scale_filename = model->GetEneryScaleFilename(); + data_files_set.clear(); + data_files_set[QStringLiteral(u"能量刻度")] = enery_scale_filename; + TreeItem* new_item_enery_scale = new TreeItem; + new_item_enery_scale->SetName(QStringLiteral(u"能量刻度")); + new_item_enery_scale->SetType(TreeItemType::EneryScale); + new_item_enery_scale->SetDescription(enery_scale_filename); + new_item_enery_scale->setData(0, Qt::UserRole, data_files_set); + tree_item_ctrl_group->addChild(new_item_enery_scale); + + const QString& efficiency_scale_filename = model->GetEfficiencyScaleFilename(); + data_files_set.clear(); + data_files_set[QStringLiteral(u"效率刻度")] = efficiency_scale_filename; + TreeItem* new_item_efficiency_scale = new TreeItem; + new_item_efficiency_scale->SetName(QStringLiteral(u"效率刻度")); + new_item_efficiency_scale->SetType(TreeItemType::EfficiencyScale); + new_item_efficiency_scale->SetDescription(efficiency_scale_filename); + new_item_efficiency_scale->setData(0, Qt::UserRole, data_files_set); + tree_item_ctrl_group->addChild(new_item_efficiency_scale); + + this->expandItem(tree_item_ctrl_group); + } + TreeItem* tree_item_analyze_data_group = new_item->GetAnalyzeDataGroupItem(); if (tree_item_analyze_data_group) { const QString& all_ch_particle_data_filename = model->GetAllChannelParticleDataFilename(); @@ -241,11 +268,11 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name) uint ch_num = it.key(); const QString& ch_count_filename = it.value(); QMap data_files_set; - data_files_set[QStringLiteral(u"通道%1道址计数数据").arg(ch_num)] = ch_count_filename; + data_files_set[QStringLiteral(u"通道%1").arg(ch_num)] = ch_count_filename; TreeItem* new_item_every_ch_count_data = new TreeItem; - new_item_every_ch_count_data->SetName(QStringLiteral(u"通道%1道址计数数据").arg(ch_num)); - new_item_every_ch_count_data->SetType(TreeItemType::ParticleData); + new_item_every_ch_count_data->SetName(QStringLiteral(u"通道%1道址计数").arg(ch_num)); + new_item_every_ch_count_data->SetType(TreeItemType::ParticleCountData); new_item_every_ch_count_data->SetDescription(ch_count_filename); new_item_every_ch_count_data->setData(0, Qt::UserRole, data_files_set); new_item_all_ch_count->addChild(new_item_every_ch_count_data); @@ -257,6 +284,78 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name) } } +void TreeWidget::onNewMeasureAnalysisView() +{ + TreeItem* current_item = dynamic_cast(this->currentItem()); + if (!current_item) { + return; + } + TreeMeasureAnalysisProjectItem * project_item = getProjectItem(current_item); + if (!project_item) { + return; + } + TreeItem* new_item_analyze_view = nullptr; + MeasureAnalysisViewType view_type = MeasureAnalysisViewType::None; + TreeItem* tree_item_analyze_view_group = project_item->GetAnalyzeViewGroupItem(); + if (tree_item_analyze_view_group) { + MeasureAnalysisTree::TreeItemType item_type = current_item->GetType(); + switch (item_type) { + case MeasureAnalysisTree::TreeItemType::ParticleCountData: { + new_item_analyze_view = new TreeItem; + const QString& view_name = QStringLiteral(u"%1谱图表").arg(current_item->GetName()); + new_item_analyze_view->SetName(view_name); + new_item_analyze_view->SetDescription(view_name); + new_item_analyze_view->setData(0, Qt::UserRole, current_item->data(0, Qt::UserRole)); + + const QString& view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(MeasureAnalysisViewType::CountSpectrum); + new_item_analyze_view->NewAnalyzeView(view_name, view_name, view_type_text); + } break; + case MeasureAnalysisTree::TreeItemType::AnalyzeDataGroup: { + if ( current_item->childCount() ) { + TreeItem* child_item = dynamic_cast(current_item->child(0)); + if ( child_item ) { + if ( MeasureAnalysisTree::TreeItemType::ParticleCountData == child_item->GetType() ) { + new_item_analyze_view = new TreeItem; + const QString& view_name = QStringLiteral(u"道址计数谱图表"); + new_item_analyze_view->SetName(view_name); + new_item_analyze_view->SetDescription(QStringLiteral(u"32通道的道址计数谱图表")); + + auto project_model = MeasureAnalysisProjectModelList::GetProjectModel(project_item->GetName()); + QMap data_files_set; + const QMap& count_data_list = project_model->GetChannelParticleCountDataFilenameList(); + for (auto it = count_data_list.begin(); it != count_data_list.end(); ++it) { + uint ch_num = it.key(); + const QString& ch_count_filename = it.value(); + data_files_set[QStringLiteral(u"通道%1").arg(ch_num)] = ch_count_filename; + } + new_item_analyze_view->setData(0, Qt::UserRole, data_files_set); + + const QString& view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(MeasureAnalysisViewType::CountSpectrum); + new_item_analyze_view->NewAnalyzeView(view_name, view_name, view_type_text); + } + } + } + } break; + default: + break; + } + } + if ( new_item_analyze_view ) { + new_item_analyze_view->SetType(TreeItemType::AnalyzeView); + MeasureAnalysisView* view = new_item_analyze_view->GetAnalyzeView(); + if (view) { + emit currentItemViewWidget(view); + } + tree_item_analyze_view_group->addChild(new_item_analyze_view); + this->expandItem(tree_item_analyze_view_group); + } else { + const QString& view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(view_type); + if ( !view_type_text.isEmpty() ) { + + } + } +} + void TreeWidget::setCurrentItemHighlight() { // 清除之前的高亮 @@ -279,60 +378,48 @@ void TreeWidget::setCurrentItemHighlight() } } -void TreeWidget::removeAnalyzeItem() +void TreeWidget::removeTreeItem(QTreeWidgetItem* const item) { - auto current_item = this->currentItem(); - if (current_item) { - const QString& text_title = QStringLiteral(u"删除确认"); - const QString& text_msg = QStringLiteral(u"是否确定删除\"%1\"?").arg(current_item->text(0)); - if (QMessageBox::Yes == QMessageBox::question(nullptr, text_title, text_msg)) { - TreeItem* tree_item = dynamic_cast(this->currentItem()); - if (tree_item) { - TreeItemType item_type = tree_item->GetType(); - if (TreeItemType::MeasureAnalysisProject == item_type) { - - } else if (TreeItemType::ParticleData == item_type) { - - } else if (TreeItemType::AnalyzeDataGroup == item_type) { - } - MeasureAnalysisView* view = tree_item->GetAnalyzeView(); + if (!item) { + return; + } + int count = item->childCount(); + if (count > 0) { + for (int i = 0; i < count; i++) { + TreeItem* child_item = dynamic_cast(item->child(0)); + if (child_item) { + MeasureAnalysisView* view = child_item->GetAnalyzeView(); if (view) { emit removeItemViewFromStack(view); } } - this->removeTreeItem(current_item); + removeTreeItem(child_item); } } -} - -void TreeWidget::removeTreeItem(QTreeWidgetItem* const item) -{ - int count = item->childCount(); - if (count > 0) { - for (int i = 0; i < count; i++) { - QTreeWidgetItem* childItem = item->child(0); - removeTreeItem(childItem); + TreeItem* tree_item = dynamic_cast(item); + if (tree_item) { + MeasureAnalysisView* view = tree_item->GetAnalyzeView(); + if (view) { + emit removeItemViewFromStack(view); } } delete item; } -} - MeasureAnalysisTree::TreeMeasureAnalysisProjectItem *MeasureAnalysisTree::TreeWidget::getProjectItem(TreeItem *item) { if (item) { TreeItemType item_type = item->GetType(); if (TreeItemType::MeasureAnalysisProject == item_type) { return dynamic_cast(item); - } - } else { - item = dynamic_cast(item->parent()); - if (item) { - return getProjectItem(item); + } else { + item = dynamic_cast(item->parent()); + if (item) { + return getProjectItem(item); + } } } return nullptr; } -// namespace MeasureAnalysisTree +} // namespace MeasureAnalysisTree diff --git a/src/MeasureAnalysisTree.h b/src/MeasureAnalysisTree.h index 3af035b..3480e80 100644 --- a/src/MeasureAnalysisTree.h +++ b/src/MeasureAnalysisTree.h @@ -31,17 +31,16 @@ private slots: // void onFinishedSeparateEveryChannelParticleData(const QString& project_name); void onFinishedParticleSortData(const QString& project_name); void onFinishedParticleCountData(const QString& project_name); + void onNewMeasureAnalysisView(); + signals: void currentItemViewWidget(MeasureAnalysisView* view); void removeItemViewFromStack(MeasureAnalysisView* view); - void newMeasureAnalysisProject(); - void newMeasureAnalysisView(const QString& project_name, const QString& view_type); private: void setCurrentItemHighlight(); - void removeAnalyzeItem(); void removeTreeItem(QTreeWidgetItem* const item); }; diff --git a/src/MeasureAnalysisView.cpp b/src/MeasureAnalysisView.cpp index f4799c0..4a5380e 100644 --- a/src/MeasureAnalysisView.cpp +++ b/src/MeasureAnalysisView.cpp @@ -1,6 +1,7 @@ #include "MeasureAnalysisView.h" #include #include "MeasureAnalysisDataTableView.h" +#include "MeasureAnalysisParticleCountPlotView.h" QMap MeasureAnalysisView::_s_analyze_view_type_list { { QStringLiteral(u"数据表视图"), @@ -37,7 +38,7 @@ MeasureAnalysisView *MeasureAnalysisView::NewAnalyzeView(const QString& view_typ new_view = new MeasureAnalysisDataTableView; } break; case MeasureAnalysisViewType::CountSpectrum: { - new_view = new MeasureAnalysisDataTableView; + new_view = new MeasureAnalysisParticleCountPlotView; } break; case MeasureAnalysisViewType::CoincidenceEnergySpectrum3D: { new_view = new MeasureAnalysisDataTableView;