EnergySpectrumAnalyer/src/MeasureAnalysisParticleCountPlotView/FindPeaksResultDialog.cpp
2026-03-24 10:30:26 +08:00

293 lines
14 KiB
C++

#include "FindPeaksResultDialog.h"
#include "GlobalDefine.h"
#include <QHBoxLayout>
#include <QHeaderView>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QTableWidget>
#include <QPushButton>
#include "csv.h"
#include <fstream>
#include <QFileInfo>
FindPeaksResultDialog::FindPeaksResultDialog(QWidget *parent)
: QDialog(parent)
{
this->setWindowTitle(QString(QStringLiteral(u"寻峰结果")));
this->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
this->setWindowModality(Qt::WindowModal);
this->setModal(false);
QPushButton* btn_all_select = new QPushButton(QString(QStringLiteral(u"全选")));
QPushButton* btn_reserve_select = new QPushButton(QString(QStringLiteral(u"反选")));
QLabel* filter_channel_label = new QLabel(QString(QStringLiteral(u"筛选通道:")));
_filter_channel_combo_box = new QComboBox();
_filter_channel_combo_box->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
_filter_channel_combo_box->setMinimumWidth(75);
_filter_channel_combo_box->addItem(QString(QStringLiteral(u"所有通道")));
_filter_channel_combo_box->setMaxVisibleItems(10);
_filter_channel_combo_box->view()->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QPushButton* btn_save = new QPushButton(QString(QStringLiteral(u"保存")));
QHBoxLayout* top_layout = new QHBoxLayout();
top_layout->addWidget(btn_all_select);
top_layout->addWidget(btn_reserve_select);
top_layout->addSpacing(10);
top_layout->addWidget(filter_channel_label);
top_layout->addWidget(_filter_channel_combo_box);
top_layout->addStretch();
top_layout->addWidget(btn_save);
const QString& channel_col_name = QString(QStringLiteral(u"通道"));
const QString& peak_pos_col_name = QString(QStringLiteral(u"峰位"));
const QString& left_bound_col_name = QString(QStringLiteral(u"左边界"));
const QString& right_bound_col_name = QString(QStringLiteral(u"右边界"));
const QString& peak_width_col_name = QString(QStringLiteral(u"峰宽"));
const QString& peak_height_col_name = QString(QStringLiteral(u"峰高"));
const QString& peak_fwhm_col_name = QString(QStringLiteral(u"FWHM"));
const QString& peak_area_col_name = QString(QStringLiteral(u"峰面积"));
const QString& operation_col_name = QString(QStringLiteral(u"操作"));
_peaks_result_table = new QTableWidget();
_peaks_result_table->setObjectName("peaks_result_table");
_peaks_result_table->setColumnCount(9);
_peaks_result_table->setHorizontalHeaderLabels({ channel_col_name, peak_pos_col_name, left_bound_col_name, right_bound_col_name,
peak_width_col_name, peak_height_col_name, peak_fwhm_col_name, peak_area_col_name, operation_col_name });
_peaks_result_table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
_peaks_result_table->horizontalHeader()->setSectionResizeMode(_peaks_result_table->columnCount() - 1, QHeaderView::ResizeToContents);
_peaks_result_table->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
_peaks_result_table->setSelectionBehavior(QAbstractItemView::SelectRows);
_peaks_result_table->setSelectionMode(QAbstractItemView::SingleSelection);
_peaks_result_table->setEditTriggers(QTableWidget::NoEditTriggers);
connect(_filter_channel_combo_box, &QComboBox::currentTextChanged, [this](const QString& text) {
_peaks_result_table->setCurrentItem(nullptr);
auto row_count = _peaks_result_table->rowCount();
if (text == QString(QStringLiteral(u"所有通道"))) {
for (int i = 0; i < row_count - 1; i++) {
_peaks_result_table->setRowHidden(i, false);
}
} else {
for (int i = row_count - 1; i >= 0; i--) {
const QString& channel = _peaks_result_table->item(i, 0)->text();
bool is_hidden = text == channel ? false : true;
_peaks_result_table->setRowHidden(i, is_hidden);
}
}
});
connect(btn_all_select, &QPushButton::clicked, [this]() {
_peaks_result_table->setCurrentItem(nullptr);
auto row_count = _peaks_result_table->rowCount();
for (int i = 0; i < row_count; i++) {
if (_peaks_result_table->isRowHidden(i)) {
continue;
}
auto item = _peaks_result_table->item(i, 0);
if (item) {
item->setCheckState(Qt::Checked);
}
}
});
connect(btn_reserve_select, &QPushButton::clicked, [this]() {
_peaks_result_table->setCurrentItem(nullptr);
auto row_count = _peaks_result_table->rowCount();
for (int i = 0; i < row_count; i++) {
if (_peaks_result_table->isRowHidden(i)) {
continue;
}
auto item = _peaks_result_table->item(i, 0);
if (item) {
Qt::CheckState check_state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
item->setCheckState(check_state);
}
}
});
connect(btn_save, &QPushButton::clicked, [this]() {
saveCurrentPeakResult();
});
connect(_peaks_result_table, &QTableWidget::itemChanged, [this](QTableWidgetItem* item) {
bool is_watch_item_changed = _peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed && bool(item->column() == 0)) {
bool b_show_peak = (item->checkState() == Qt::Checked);
emit peakInfoChanged(peakInfo(item, b_show_peak, false));
}
});
connect(_peaks_result_table, &QTableWidget::currentItemChanged, [this](QTableWidgetItem* current, QTableWidgetItem* previous) {
bool is_watch_item_changed = _peaks_result_table->property("WatchItemChanged").toBool();
if (is_watch_item_changed) {
int previous_row = -1;
if (previous ) {
previous_row = previous->row();
}
int current_row = -1;
if (current) {
current_row = current->row();
}
if ((previous_row >= 0) && (previous_row != current_row) ) {
emit peakInfoChanged(peakInfo(previous, false, false));
}
if (current_row >= 0) {
emit peakInfoChanged(peakInfo(current, true, true));
}
}
});
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addLayout(top_layout);
layout->addWidget(_peaks_result_table);
}
FindPeaksResultDialog::~FindPeaksResultDialog()
{
qDebug() << "~FindPeaksResultDialog";
}
void FindPeaksResultDialog::SetPeakResultDataFilename(const QString &data_filename)
{
this->_peaks_result_data_filename = data_filename;
}
void FindPeaksResultDialog::SetChannelNameList(const QStringList &ch_name_list)
{
_filter_channel_combo_box->clear();
_filter_channel_combo_box->addItem(QString(QStringLiteral(u"所有通道")));
_filter_channel_combo_box->addItems(ch_name_list);
}
void FindPeaksResultDialog::UpdatePeakResult()
{
if (!QFileInfo(_peaks_result_data_filename).exists())
return;
_peaks_result_table->setCurrentItem(nullptr);
_peaks_result_table->setProperty("WatchItemChanged", false);
auto row_count = _peaks_result_table->rowCount();
for (int i = row_count - 1; i >= 0; i--) {
_peaks_result_table->removeRow(i);
}
const QString& channel_col_name = QString(QStringLiteral(u"通道"));
const QString& peak_pos_col_name = QString(QStringLiteral(u"峰位"));
const QString& left_bound_col_name = QString(QStringLiteral(u"左边界"));
const QString& right_bound_col_name = QString(QStringLiteral(u"右边界"));
const QString& peak_width_col_name = QString(QStringLiteral(u"峰宽"));
const QString& peak_height_col_name = QString(QStringLiteral(u"峰高"));
const QString& peak_fwhm_col_name = QString(QStringLiteral(u"FWHM"));
const QString& peak_area_col_name = QString(QStringLiteral(u"峰面积"));
io::CSVReader<
8,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment>
reader(QStrToSysPath(_peaks_result_data_filename));
reader.read_header(
io::ignore_extra_column,
channel_col_name.toStdString(),
peak_pos_col_name.toStdString(),
left_bound_col_name.toStdString(),
right_bound_col_name.toStdString(),
peak_width_col_name.toStdString(),
peak_height_col_name.toStdString(),
peak_fwhm_col_name.toStdString(),
peak_area_col_name.toStdString());
std::string ch_name;
int peak_pos;
int left_bound, right_bound, peak_width, peak_height, peak_fwhm;
double peak_area;
while (reader.read_row(ch_name, peak_pos, left_bound, right_bound, peak_width, peak_height, peak_fwhm, peak_area)) {
if (!ch_name.empty()) {
int row = _peaks_result_table->rowCount();
_peaks_result_table->insertRow(row);
_peaks_result_table->setItem(row, 0, new QTableWidgetItem(QString::fromStdString(ch_name)));
_peaks_result_table->item(row, 0)->setCheckState(Qt::Unchecked);
_peaks_result_table->setItem(row, 1, new QTableWidgetItem(QString::number(peak_pos)));
_peaks_result_table->setItem(row, 2, new QTableWidgetItem(QString::number(left_bound)));
_peaks_result_table->setItem(row, 3, new QTableWidgetItem(QString::number(right_bound)));
_peaks_result_table->setItem(row, 4, new QTableWidgetItem(QString::number(peak_width)));
_peaks_result_table->setItem(row, 5, new QTableWidgetItem(QString::number(peak_height)));
_peaks_result_table->setItem(row, 6, new QTableWidgetItem(QString::number(peak_fwhm)));
_peaks_result_table->setItem(row, 7, new QTableWidgetItem(QString::number(peak_area)));
QTableWidgetItem* item = new QTableWidgetItem;
_peaks_result_table->setItem(row, 8, item);
QPushButton* btn_remove_row = new QPushButton(QStringLiteral(u"删除"));
btn_remove_row->setMaximumWidth(35);
connect(btn_remove_row, &QPushButton::clicked, [this, item, btn_remove_row]() {
int remove_row = item->row();
this->_peaks_result_table->item(remove_row, 0)->setCheckState(Qt::Unchecked);
emit peakInfoChanged(peakInfo(item, false, false));
this->_peaks_result_table->removeRow(remove_row);
btn_remove_row->deleteLater();
});
_peaks_result_table->setCellWidget(row, 8, btn_remove_row);
}
}
_peaks_result_table->setProperty("WatchItemChanged", true);
}
QAbstractTableModel* FindPeaksResultDialog::GetPeakResultDataModel() const
{
QAbstractTableModel* peaks_result_model = dynamic_cast<QAbstractTableModel*>(_peaks_result_table->model());
return peaks_result_model;
}
void FindPeaksResultDialog::saveCurrentPeakResult()
{
std::ofstream out_file(QStrToSysPath(_peaks_result_data_filename));
std::string channel_str = QString(QStringLiteral(u"通道")).toStdString();
std::string addr_str = QString(QStringLiteral(u"峰位")).toStdString();
std::string left_addr_str = QString(QStringLiteral(u"左边界")).toStdString();
std::string lright_addr_str = QString(QStringLiteral(u"右边界")).toStdString();
std::string width_str = QString(QStringLiteral(u"峰宽")).toStdString();
std::string height_str = QString(QStringLiteral(u"峰高")).toStdString();
std::string fwhm_str = QString(QStringLiteral(u"FWHM")).toStdString();
std::string area_str = QString(QStringLiteral(u"峰面积")).toStdString();
out_file << channel_str << "," << addr_str << "," << left_addr_str << ","
<< lright_addr_str << "," << width_str << "," << height_str << ","
<< fwhm_str << "," << area_str << "\n";
auto row_count = _peaks_result_table->rowCount();
for (int i = 0; i < row_count; i++) {
std::string channel = _peaks_result_table->item(i, 0)->text().toStdString();
int peak_pos = _peaks_result_table->item(i, 1)->text().toInt();
int left_bound = _peaks_result_table->item(i, 2)->text().toInt();
int right_bound = _peaks_result_table->item(i, 3)->text().toInt();
int peak_width = _peaks_result_table->item(i, 4)->text().toInt();
int peak_height = _peaks_result_table->item(i, 5)->text().toInt();
int peak_fwhm = _peaks_result_table->item(i, 6)->text().toInt();
double peak_area = _peaks_result_table->item(i, 7)->text().toDouble();
out_file << channel << "," << peak_pos << "," << left_bound << "," << right_bound << ","
<< peak_width << "," << peak_height << "," << peak_fwhm<< "," << peak_area << "\n";
}
LOG_INFO(QStringLiteral(u"保存峰信息完成."));
}
QVariantMap FindPeaksResultDialog::peakInfo(QTableWidgetItem *item, bool show_peak, bool show_peak_area)
{
QVariantMap peak_infos;
if (!item) {
return peak_infos;
}
int row = item->row();
bool is_checked = bool(_peaks_result_table->item(row, 0)->checkState() == Qt::Checked);
const QString& channel = _peaks_result_table->item(row, 0)->text();
int peak_pos = _peaks_result_table->item(row, 1)->text().toInt();
int left_bound = _peaks_result_table->item(row, 2)->text().toInt();
int right_bound = _peaks_result_table->item(row, 3)->text().toInt();
int peak_width = _peaks_result_table->item(row, 4)->text().toInt();
int peak_height = _peaks_result_table->item(row, 5)->text().toInt();
int peak_fwhm = _peaks_result_table->item(row, 6)->text().toInt();
double peak_area = _peaks_result_table->item(row, 7)->text().toDouble();
peak_infos["channel"] = channel;
peak_infos["peak_pos"] = peak_pos;
peak_infos["left_bound"] = left_bound;
peak_infos["right_bound"] = right_bound;
peak_infos["peak_width"] = peak_width;
peak_infos["peak_height"] = peak_height;
peak_infos["peak_fwhm"] = peak_fwhm;
peak_infos["peak_area"] = peak_area;
peak_infos["checked"] = is_checked || show_peak;
peak_infos["show_peak_area"] = show_peak_area && show_peak;
return peak_infos;
}