Conflicts:
	src/EnergyCountPeakFitView/EnergyCountPeakFitView.cpp
This commit is contained in:
anxinglong 2026-05-09 17:00:49 +08:00
commit 15d37e279e
42 changed files with 1313 additions and 2339 deletions

Binary file not shown.

View File

@ -0,0 +1,158 @@
#include "AntiConformEnergySpectrumView.h"
#include <QVBoxLayout>
#include <QwtPlotCurve>
#include <QwtPlotCanvas>
#include <QwtText>
#include "CustomQwtPlot.h"
#include <GlobalDefine.h>
#include "csv.h"
#include <QFileInfo>
#include <QThread>
#include "BusyIndicator.h"
#include <map>
#include <vector>
#include <algorithm>
#include <cstdint>
#include <QPen>
struct SpectrumData
{
int board_id;
int channel_id;
double energy;
uint64_t timestamp;
};
AntiConformEnergySpectrumView::AntiConformEnergySpectrumView(QWidget *parent) :
MeasureAnalysisView(parent)
{
this->setViewType(PlotFrame);
_plot = new CustomQwtPlot();
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(_plot);
_plot->setCanvasBackground(Qt::white);
QwtPlotCanvas* canvas = qobject_cast<QwtPlotCanvas*>(_plot->canvas());
canvas->setFrameStyle(QFrame::NoFrame);
QFont font = this->font();
font.setBold(false);
QwtText x_label = QStringLiteral(u"能量(KeV)");
QwtText y_label = QStringLiteral(u"反符合事件次数");
x_label.setFont(font);
y_label.setFont(font);
_plot->setAxisTitle(QwtPlot::xBottom, x_label);
_plot->setAxisTitle(QwtPlot::yLeft, y_label);
_plot->setAxisAutoScale(QwtPlot::xBottom, true);
_plot->setAxisAutoScale(QwtPlot::yLeft, true);
_plot->enableAxis(QwtPlot::xBottom);
_plot->enableAxis(QwtPlot::yLeft);
_plot->SetAxisDragScale(QwtPlot::xBottom, true);
_curve = new QwtPlotCurve();
_curve->setStyle(QwtPlotCurve::Lines);
_curve->setPen(QPen(QColor(23, 229, 238), 2));
_plot->AddCurve(_curve);
_busy_indicator = new BusyIndicator(this);
}
AntiConformEnergySpectrumView::~AntiConformEnergySpectrumView()
{
}
void AntiConformEnergySpectrumView::InitViewWorkspace(const QString &project_name)
{
Q_UNUSED(project_name);
}
void AntiConformEnergySpectrumView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
{
const QString& data_filename = data_files_set.first().toString();
if (!data_filename.isEmpty() && QFileInfo(data_filename).exists()) {
this->_data_filename = data_filename;
this->loadAndProcess();
}
}
void AntiConformEnergySpectrumView::loadAndProcess()
{
auto functionToRun = [this]() {
if (_data_filename.isEmpty()) return;
_busy_indicator->Start();
std::vector<SpectrumData> rawData;
io::CSVReader<4> in(QStrToSysPath(_data_filename));
in.read_header(io::ignore_extra_column,
QString(QStringLiteral(u"板卡号")).toStdString(),
QString(QStringLiteral(u"通道号")).toStdString(),
QString(QStringLiteral(u"能量(KeV)")).toStdString(),
QString(QStringLiteral(u"时间计数")).toStdString());
int board, channel;
double energy;
unsigned long long time_count;
while (in.read_row(board, channel, energy, time_count)) {
SpectrumData sd;
sd.board_id = board;
sd.channel_id = channel;
sd.energy = energy;
sd.timestamp = time_count;
rawData.push_back(sd);
}
if (rawData.empty()) {
_busy_indicator->Stop();
return;
}
const int STEP = 1;
std::map<int, double> hist;
for (const auto& spdt : rawData) {
int idx = static_cast<int>(spdt.energy) / STEP;
hist[idx] += 1.0;
}
QVector<double> vx, vy;
for (const auto& pair : hist) {
vx.push_back(pair.first * STEP);
vy.push_back(pair.second);
}
if (vx.isEmpty()) {
_busy_indicator->Stop();
return;
}
double dmaxx = *std::max_element(vx.begin(), vx.end());
double dmaxy = *std::max_element(vy.begin(), vy.end());
QMetaObject::invokeMethod(this, [this, vx, vy, dmaxx, dmaxy]() {
_curve->setSamples(vx, vy);
_plot->setAxisScale(QwtPlot::xBottom, 0, dmaxx);
_plot->setAxisScale(QwtPlot::yLeft, 0, dmaxy * 1.1);
_plot->replot();
_busy_indicator->Stop();
}, Qt::QueuedConnection);
};
QThread* load_thread = QThread::create(functionToRun);
load_thread->start();
}
void AntiConformEnergySpectrumView::showEvent(QShowEvent *e)
{
Q_UNUSED(e);
if (_busy_indicator) {
_busy_indicator->setGeometry(this->rect());
this->update();
}
}

View File

@ -0,0 +1,34 @@
#ifndef ANTICONFORMENERGYSPECTRUMVIEW_H
#define ANTICONFORMENERGYSPECTRUMVIEW_H
#include "MeasureAnalysisView.h"
class CustomQwtPlot;
class QwtPlotCurve;
class BusyIndicator;
class AntiConformEnergySpectrumView : public MeasureAnalysisView
{
Q_OBJECT
public:
explicit AntiConformEnergySpectrumView(QWidget *parent = nullptr);
virtual ~AntiConformEnergySpectrumView();
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set) override;
protected:
virtual void showEvent(QShowEvent* e) override final;
private:
void loadAndProcess(); // 读取CSV执行符合处理绘制能谱折线图
private:
BusyIndicator* _busy_indicator = nullptr;
CustomQwtPlot* _plot = nullptr;
QwtPlotCurve* _curve = nullptr;
QString _data_filename;
};
#endif // ANTICONFORMENERGYSPECTRUMVIEW_H

View File

@ -106,9 +106,6 @@ private:
};
QColor getDistinctColorForManyCurves(int curve_index);
#endif // CUSTOMQWTPLOT_H

View File

@ -1,13 +1,14 @@
#ifndef ADAPTIVESIMPSONINTEGRATE_H
#define ADAPTIVESIMPSONINTEGRATE_H
namespace AdaptiveSimpsonIntegrate {
#include <armadillo>
#include <cmath>
#include <iostream>
//#include <iomanip>
namespace AdaptiveSimpsonIntegrate {
// 定义被积函数y = A*exp(-(x-P)²/(2*delt²)) + H/(1+exp((x-P)/W)) + C
struct FitFunction {
// 拟合公式的参数
@ -55,7 +56,7 @@ double adaptive_simpson(double a, double b, double eps, const Func& f,
double right = simpson(c, b, f);
// 精度判断:满足则返回,不满足则递归细分
if (::std::abs(left + right - whole) <= 15 * eps) {
if (std::abs(left + right - whole) <= 15 * eps) {
return left + right + (left + right - whole) / 15.0;
}

View File

@ -178,6 +178,7 @@ void SortDataByTimestamp(std::vector<SpectrumData>& data)
bool ProcessCoincidence(
std::vector<SpectrumData>& data,
std::vector<CoincidenceEvent>& events,
std::vector<AntiCoincidenceEvent>& anti_coincidence_events,
unsigned int time_window,
int min_order,
int max_order
@ -187,8 +188,13 @@ bool ProcessCoincidence(
if (n < min_order) {
return false;
}
if (min_order < 2 || max_order < min_order)
return false;
std::vector<bool> is_used(n, false);
// 使用滑动窗口寻找符合事件
for (int i = 0; i < n; ++i) {
if (is_used[i])
continue;
std::vector<SpectrumData> current_coincidence;
current_coincidence.push_back(data[i]);
// 寻找时间窗口内的其他事件
@ -206,6 +212,10 @@ bool ProcessCoincidence(
// 保存符合条件的事件
int coincidence_order = current_coincidence.size();
if (coincidence_order >= min_order && coincidence_order <= max_order) {
// 标记这些事件已被使用
for (int k = 0; k < coincidence_order; ++k) {
is_used[i + k] = true;
}
CoincidenceEvent result;
result.coincidence_order = coincidence_order;
result.events = current_coincidence;
@ -213,6 +223,31 @@ bool ProcessCoincidence(
events.push_back(result);
}
}
for (int i = 0; i < n; ++i) {
if (is_used[i])
continue;
bool is_anti = true;
// 检查前向时间窗口内是否有其他事件
if (i > 0) {
unsigned long long diff_prev = data[i].timestamp - data[i-1].timestamp;
if (diff_prev <= time_window)
is_anti = false;
}
// 检查后向时间窗口内是否有其他事件
if (i < n-1 && is_anti) {
unsigned long long diff_next = data[i+1].timestamp - data[i].timestamp;
if (diff_next <= time_window)
is_anti = false;
}
// 满足反符合条件
if (is_anti) {
AntiCoincidenceEvent res;
res.event = data[i];
res.time_window = time_window;
anti_coincidence_events.push_back(res);
}
}
return true;
}

View File

@ -28,6 +28,11 @@ namespace F2t9Order {
std::vector<SpectrumData> events; // 符合的事件集合
unsigned int time_window; // 使用的时间窗口(秒)
};
// 反符合事件结构体(只包含未参与任何符合的独立事件)
struct AntiCoincidenceEvent {
SpectrumData event; // 反符合单事件
unsigned int time_window; // 时间窗口
};
// 读取CSV数据文件
std::vector<SpectrumData> ReadCsv(const std::string& filename);
@ -39,6 +44,7 @@ namespace F2t9Order {
bool ProcessCoincidence(
std::vector<SpectrumData> &data,
std::vector<CoincidenceEvent> &events,
std::vector<AntiCoincidenceEvent>& anti_coincidence_events,
unsigned int time_window, // 时间窗口(纳秒)
int min_order = 2, // 最小符合次数
int max_order = 9 // 最大符合次数

View File

@ -6,7 +6,7 @@ LIBS += -L$$PWD/armadillo/lib -llibblas
LIBS += -L$$PWD/armadillo/lib -lliblapack
SOURCES += \
$$PWD/CoincidenceSpectrum.cpp \
$$PWD/CoincidenceSpectrumProcess.cpp \
$$PWD/EnergyEfficiencyFit.cpp \
$$PWD/Poly2FindPeaks.cpp \
$$PWD/FindPeaksBySvd.cpp \

View File

@ -466,6 +466,7 @@ bool CoincidenceEventAnalysisTask::processTask()
if (particle_data_filename.isEmpty()) {
return false;
}
std::string time_win_str = QString(QStringLiteral(u"时间窗口")).toStdString();
std::string event_id_str = QString(QStringLiteral(u"事件ID")).toStdString();
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
@ -490,8 +491,9 @@ bool CoincidenceEventAnalysisTask::processTask()
spec_data_item.timestamp)) {
spec_data.push_back(spec_data_item);
}
std::vector<CoincidenceEvent> events;
if (!ProcessCoincidence(spec_data, events, project_model->GetConformTimeWin())) {
std::vector<CoincidenceEvent> coincidence_events;
std::vector<AntiCoincidenceEvent> anti_coincidence_events;
if (!ProcessCoincidence(spec_data, coincidence_events, anti_coincidence_events, project_model->GetConformTimeWin())) {
LOG_WARN(QStringLiteral(u"粒子符合数据处理异常!"));
}
const QString& coincidence_data_dir_name = QStringLiteral(u"粒子符合数据");
@ -500,7 +502,7 @@ bool CoincidenceEventAnalysisTask::processTask()
const QString& coincidence_data_dir_path = project_dir.filePath(coincidence_data_dir_name);
QMap<int, std::shared_ptr<std::ofstream> > coincidence_data_out_stream_map;
unsigned long long event_id = 0;
for (const CoincidenceEvent& event : events) {
for (const CoincidenceEvent& event : coincidence_events) {
++ event_id;
const QString& event_data_filename = QDir(coincidence_data_dir_path).filePath(QStringLiteral(u"[%1ns]%2个粒子符合事件[未刻度].csv").arg(project_model->GetConformTimeWin()).arg(event.coincidence_order));
if ( !coincidence_data_out_stream_map.contains(event.coincidence_order) ) {
@ -514,6 +516,13 @@ bool CoincidenceEventAnalysisTask::processTask()
}
project_model->SetTimeWinConformParticleData(project_model->GetConformTimeWin(), event.coincidence_order, event_data_filename);
}
const QString& anti_event_data_filename = QDir(coincidence_data_dir_path).filePath(QStringLiteral(u"反符合事件[未刻度].csv"));
std::ofstream anti_event_data_out_stream(QStrToSysPath(anti_event_data_filename));
anti_event_data_out_stream << time_win_str << "," << board_id_str << "," << channel_id_str << "," << addr_str << "," << time_str << std::endl;
for (const AntiCoincidenceEvent& anti_event : anti_coincidence_events) {
anti_event_data_out_stream << anti_event.time_window << "," << anti_event.event.board_id << "," << anti_event.event.channel_id << "," << anti_event.event.energy << "," << anti_event.event.timestamp << std::endl;
}
project_model->SetAntiConformParticleData(project_model->GetConformTimeWin(), anti_event_data_filename);
} catch (const std::exception& e) {
const QString& e_what = QString::fromUtf8(e.what());
LOG_WARN(QStringLiteral(u"粒子符合数据处理异常:%1").arg(e_what));
@ -931,7 +940,83 @@ bool EnergyScaleCoincidenceDataTask::processTask()
conformParticleDataEnergyScale(time_win, coincidence_order, conform_particle_data_filename);
}
}
const QString& info = QStringLiteral(u"符合能谱数据处理完成.");
LOG_INFO(info);
return true;
}
bool EnergyScaleaAntiCoincidenceDataTask::processTask()
{
const QString& project_name = GetProjectName();
MeasureAnalysisProjectModel* project_model = ProjectList::Instance()->GetProjectModel(project_name);
if (project_model == nullptr) {
return false;
}
EnergyScaleDataModel energy_scale_data_model(project_model->GetEnergyScaleFilename());
if (!energy_scale_data_model.LoadData()) {
return false;
}
if (!energy_scale_data_model.IsValid()) {
return false;
}
const QString& coincidence_data_dir_name = QStringLiteral(u"符合能谱数据");
QDir project_dir(project_model->GetProjectDir());
project_dir.mkpath(coincidence_data_dir_name);
const QString& coincidence_data_dir_path = project_dir.filePath(coincidence_data_dir_name);
std::string time_win_str = QString(QStringLiteral(u"时间窗口")).toStdString();
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
std::string addr_str = QString(QStringLiteral(u"道址")).toStdString();
std::string energy_str = QString(QStringLiteral(u"能量(KeV)")).toStdString();
std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString();
const auto& anti_conform_particle_data = project_model->GetAntiConformParticleData();
for (const auto& time_win : anti_conform_particle_data.keys()) {
const auto&anti_conform_particle_data_filename = anti_conform_particle_data.value(time_win);
try {
io::CSVReader<
5,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment>
reader(QStrToSysPath(anti_conform_particle_data_filename));
reader.read_header(io::ignore_extra_column, time_win_str, board_id_str, channel_id_str, addr_str, time_str);
const QString& anti_coincidence_energy_data_filename = QDir(coincidence_data_dir_path).filePath(QStringLiteral(u"反符合粒子事件.csv"));
std::ofstream out_stream(QStrToSysPath(anti_coincidence_energy_data_filename));
out_stream << time_win_str << "," << board_id_str << "," << channel_id_str << "," << energy_str << "," << time_str << "\n" ;
using namespace CoincidenceSpectrum::F2t9Order;
unsigned int time_window;
SpectrumData data_item;
while (reader.read_row(
time_window,
data_item.board_id,
data_item.channel_id,
data_item.energy,
data_item.timestamp)) {
int channel_num = (data_item.board_id) * 4 + (data_item.channel_id + 1);
const QString& channel_name = QStringLiteral(u"通道%1").arg(channel_num);
auto coeffs = energy_scale_data_model.GetEnergyFitResultCoeffs(channel_name);
if (!coeffs.empty()) {
data_item.energy = GaussPolyCoe::Predict(coeffs, data_item.energy);
out_stream << time_window << "," << data_item.board_id << "," << data_item.channel_id << "," << data_item.energy << "," << data_item.timestamp << "\n" ;
} else {
LOG_WARN(QStringLiteral(u"符合能谱数据处理异常:%1能量刻度拟合参数为空!").arg(channel_name));
}
}
out_stream.close();
project_model->SetAntiConformEnergyData(time_win, anti_coincidence_energy_data_filename);
} catch (const std::exception& e) {
const QString& e_what = QString::fromStdString(e.what());
LOG_WARN(QStringLiteral(u"反符合能谱数据处理异常:%1").arg(e_what));
return false;
}
}
const QString& info = QStringLiteral(u"反符合能谱数据处理完成.");
LOG_INFO(info);
return true;
}

View File

@ -143,6 +143,12 @@ namespace DataProcessWorkPool
private:
virtual bool processTask() override;
};
class EnergyScaleaAntiCoincidenceDataTask : public DataProcessTask
{
private:
virtual bool processTask() override;
};
}
#endif // DATAPROCESSWORKPOOL_H

View File

@ -1,463 +0,0 @@
#include "DeviceConfigView.h"
#include "DeviceParameterProxy.h"
#include <QTableView>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QPushButton>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include <QDialogButtonBox>
#include <QLabel>
#include <QScrollArea>
#include <QCheckBox>
#include <QFileDialog>
#include <QStyleOptionButton>
#include <GlobalDefine.h>
#include <QObject>
#include <QDebug>
class DeviceConfigViewModel: public QStandardItemModel
{
public:
DeviceConfigViewModel(QObject *parent = nullptr) : QStandardItemModel(parent){}
virtual Qt::ItemFlags flags(const QModelIndex &index) const {
Qt::ItemFlags f = QStandardItemModel::flags(index);
if ( index.column() == 0 ) {
f = f & Qt::ItemIsUserCheckable;
}
return f;
}
};
DeviceConfigView::DeviceConfigView(QWidget *parent)
: MeasureAnalysisView(parent)
, m_tableView(nullptr)
, m_model(nullptr)
{
initTableView();
}
DeviceConfigView::~DeviceConfigView()
{
}
void DeviceConfigView::initTableView()
{
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
m_tableView = new QTableView(this);
layout->addWidget(m_tableView);
// 设置表头
QStringList headList;
headList << tr("数据传输模式") << tr("硬件增益") << tr("硬件增益选择索引")
<< tr("软件增益") << tr("时间常数") << tr("成形时间") << tr("快通道触发阈值")
<< tr("多道分辨率") << tr("控制功能") << tr("幅度提前延迟") << tr("积分长度")
<< tr("dcfd缩放倍数") << tr("dcfd延迟") << tr("直流偏移") << tr("最大能量范围")
<< tr("Am 峰面积寻峰法的面积比例") << tr("K40与 Am241的峰位校正系数") << tr("高压关断阈值")
<< tr("获取能谱周期") << tr("总测量时间") << tr("总测量次数") << tr("滤波参数")
<< tr("上升时间") << tr("平顶时间") << tr("ICR 校正使能") << tr("CRZA 值")
<< tr("ZA 使能值") << tr("操作");
m_model = new DeviceConfigViewModel(this);
m_model->setColumnCount(headList.size());
m_model->setHorizontalHeaderLabels(headList);
m_model->setRowCount(32);
for (int i = 0; i < 32; ++i) {
QString rowName = tr("通道%1").arg(i + 1);
m_model->setHeaderData(i, Qt::Vertical, rowName, Qt::DisplayRole);
}
// 操作列最后一列不可编辑
int actionCol = headList.size() - 1;
for (int row = 0; row < 32; ++row) {
QStandardItem *item = new QStandardItem(QString());
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
m_model->setItem(row, actionCol, item);
}
m_tableView->setModel(m_model);
m_tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Interactive);
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
m_tableView->setEditTriggers(QAbstractItemView::DoubleClicked);
// 设置代理
DeviceParameterProxy *proxy = new DeviceParameterProxy(this);
m_tableView->setItemDelegate(proxy);
setupActionColumnButtons();
}
void DeviceConfigView::setupActionColumnButtons()
{
int actionCol = m_model->columnCount() - 1;
for (int row = 0; row < m_model->rowCount(); ++row) {
QModelIndex idx_0 = m_model->index(row, 0);
QModelIndex idx = m_model->index(row, actionCol);
QPushButton *btn = new QPushButton(tr("应用"), m_tableView);
btn->setProperty("row", row);
connect(btn, &QPushButton::clicked, this, &DeviceConfigView::onActionButtonClicked);
m_tableView->setIndexWidget(idx, btn);
}
}
void DeviceConfigView::onActionButtonClicked()
{
QPushButton *btn = qobject_cast<QPushButton*>(sender());
if (!btn) return;
int srcRow = btn->property("row").toInt();
int srcChannel = srcRow + 1;
QList<int> targetChannels = selectTargetChannels(srcChannel);
if (targetChannels.isEmpty()) return;
int paramColCount = m_model->columnCount() - 1;
m_model->blockSignals(true);
for (int ch : targetChannels) {
int dstRow = ch - 1;
if (dstRow == srcRow) continue;
for (int col = 0; col < paramColCount; ++col) {
QVariant srcData = m_model->data(m_model->index(srcRow, col));
m_model->setData(m_model->index(dstRow, col), srcData);
}
}
m_model->blockSignals(false);
emit m_model->dataChanged(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, paramColCount - 1));
QMessageBox::information(this, tr("提示"),
tr("已成功将通道%1的参数应用到 %2 个通道").arg(srcChannel).arg(targetChannels.size()));
}
QList<int> DeviceConfigView::selectTargetChannels(int currentChannel) const
{
QDialog dlg(const_cast<DeviceConfigView*>(this));
dlg.setWindowTitle(tr("选择目标通道"));
dlg.resize(300, 400);
QVBoxLayout *layout = new QVBoxLayout(&dlg);
QLabel *label = new QLabel(tr("请选择要应用参数的目标通道(可多选):"));
layout->addWidget(label);
QListWidget *listWidget = new QListWidget(&dlg);
for (int i = 1; i <= 32; ++i) {
QString itemText = tr("通道 %1").arg(i);
if (i == currentChannel) itemText += tr(" (源通道)");
QListWidgetItem *item = new QListWidgetItem(itemText, listWidget);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Unchecked);
item->setData(Qt::UserRole, i);
if (i == currentChannel) {
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
}
}
layout->addWidget(listWidget);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dlg);
layout->addWidget(buttonBox);
connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
QList<int> selected;
if (dlg.exec() == QDialog::Accepted) {
for (int i = 0; i < listWidget->count(); ++i) {
QListWidgetItem *item = listWidget->item(i);
if (item->checkState() == Qt::Checked) {
int ch = item->data(Qt::UserRole).toInt();
if (ch != currentChannel) selected.append(ch);
}
}
}
return selected;
}
bool DeviceConfigView::loadJson(const QString &filePath)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "无法打开文件:" << file.errorString();
return false;
}
QByteArray jsonData = file.readAll();
file.close();
return parseJsonImpl(jsonData);
}
bool DeviceConfigView::parseJsonImpl(const QByteArray &data)
{
QJsonParseError parseError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "JSON 解析错误:" << parseError.errorString();
return false;
}
if (!jsonDoc.isObject()) {
qWarning() << "JSON 文档不是对象";
return false;
}
QJsonObject rootObj = jsonDoc.object();
QJsonArray channelsArray = rootObj["channels"].toArray();
m_model->blockSignals(true);
// 清空现有数据
for (int row = 0; row < m_model->rowCount(); ++row) {
for (int col = 0; col < m_model->columnCount(); ++col) {
m_model->setData(m_model->index(row, col), QVariant());
}
}
int count = qMin(channelsArray.size(), m_model->rowCount());
for (int i = 0; i < count; ++i) {
QJsonValue channelValue = channelsArray[i];
if (!channelValue.isObject()) continue;
QJsonObject channelObj = channelValue.toObject();
for (int col = 0; col < m_model->columnCount(); ++col) {
QString header = m_model->headerData(col, Qt::Horizontal).toString();
QString jsonKey = m_columnToJsonKey.value(header);
if (jsonKey.isEmpty()) continue;
QJsonValue value = channelObj[jsonKey];
if (value.isUndefined()) continue;
if (value.isString())
m_model->setData(m_model->index(i, col), value.toString());
else if (value.isDouble())
m_model->setData(m_model->index(i, col), value.toDouble());
else if (value.isBool())
m_model->setData(m_model->index(i, col), value.toBool());
}
}
emit m_model->dataChanged(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, m_model->columnCount() - 1));
emit dataChanged();
m_tableView->viewport()->update();
m_tableView->horizontalHeader()->update();
m_tableView->verticalHeader()->update();
return true;
}
bool DeviceConfigView::saveJson(const QString &filePath)
{
QJsonObject rootObj;
rootObj["command"] = "SET";
QJsonArray channelsArray;
for (int row = 0; row < m_model->rowCount(); ++row) {
QJsonObject channelObj;
for (int col = 0; col < m_model->columnCount(); ++col) {
QString header = m_model->headerData(col, Qt::Horizontal).toString();
QString jsonKey = m_columnToJsonKey.value(header);
if (jsonKey.isEmpty()) continue;
QVariant value = m_model->index(row, col).data(Qt::EditRole);
if (!value.isValid() || value.isNull()) continue;
channelObj[jsonKey] = QJsonValue::fromVariant(value);
}
channelsArray.append(channelObj);
}
rootObj["channels"] = channelsArray;
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qWarning() << "无法创建文件:" << file.errorString();
return false;
}
QJsonDocument doc(rootObj);
file.write(doc.toJson());
file.close();
return true;
}
QStandardItemModel* DeviceConfigView::getModel() const
{
return m_model;
}
void DeviceConfigView::showColumnControlDialog()
{
int colCount = m_model->columnCount();
if (colCount == 0) return;
QDialog dlg(this);
dlg.setWindowTitle(tr("列显示控制"));
dlg.resize(800, 400);
dlg.setWindowModality(Qt::WindowModal);
QVBoxLayout *mainLayout = new QVBoxLayout(&dlg);
// 工具栏
QHBoxLayout *row1Layout = new QHBoxLayout();
QPushButton *btnSelectAll = new QPushButton(tr("全选"));
QPushButton *btnInvert = new QPushButton(tr("反选"));
QPushButton *btnSave = new QPushButton(tr("保存配置"));
QPushButton *btnLoad = new QPushButton(tr("加载配置"));
row1Layout->addWidget(btnSelectAll);
row1Layout->addWidget(btnInvert);
row1Layout->addWidget(btnSave);
row1Layout->addWidget(btnLoad);
row1Layout->addStretch();
mainLayout->addLayout(row1Layout);
QScrollArea *scrollArea = new QScrollArea();
scrollArea->setWidgetResizable(true);
QWidget *scrollWidget = new QWidget();
QGridLayout *gridLayout = new QGridLayout(scrollWidget);
scrollArea->setWidget(scrollWidget);
mainLayout->addWidget(scrollArea);
int gridCols = std::sqrt(colCount);
if (gridCols < 1) gridCols = 1;
QMap<int, QCheckBox*> colCheckBoxMap;
for (int col = 0; col < colCount; ++col) {
QString header = m_model->headerData(col, Qt::Horizontal).toString();
QCheckBox *cb = new QCheckBox(header);
cb->setChecked(!m_tableView->isColumnHidden(col));
connect(cb, &QCheckBox::toggled, this, [this, col](bool checked) {
m_tableView->setColumnHidden(col, !checked);
});
int row = col / gridCols;
int colInGrid = col % gridCols;
gridLayout->addWidget(cb, row, colInGrid);
colCheckBoxMap[col] = cb;
}
connect(btnSelectAll, &QPushButton::clicked, this, [colCheckBoxMap, this]() {
// 先断开所有复选框的信号
for (QCheckBox *cb : colCheckBoxMap) {
cb->blockSignals(true);
cb->setChecked(true);
cb->blockSignals(false);
}
// 一次性更新所有列的隐藏状态
for (int col : colCheckBoxMap.keys()) {
m_tableView->setColumnHidden(col, !colCheckBoxMap[col]->isChecked());
}
});
connect(btnInvert, &QPushButton::clicked, this, [colCheckBoxMap, this]() {
for (QCheckBox *cb : colCheckBoxMap) {
cb->blockSignals(true);
cb->setChecked(!cb->isChecked());
cb->blockSignals(false);
}
for (int col : colCheckBoxMap.keys()) {
m_tableView->setColumnHidden(col, !colCheckBoxMap[col]->isChecked());
}
});
connect(btnSave, &QPushButton::clicked, this, [this, &dlg, colCheckBoxMap]() {
QString saveDir = QDir::currentPath() + "/columnConfigs";
QDir().mkpath(saveDir);
QString fileName = QFileDialog::getSaveFileName(&dlg, tr("保存列配置"),
saveDir + "/untitled.json",
"JSON Files (*.json)");
if (fileName.isEmpty()) return;
QJsonObject root;
for (int col = 0; col < m_model->columnCount(); ++col) {
QString header = m_model->headerData(col, Qt::Horizontal).toString();
bool checked = colCheckBoxMap[col]->isChecked();
root[header] = checked;
}
QJsonDocument doc(root);
QFile file(fileName);
if (file.open(QIODevice::WriteOnly)) {
file.write(doc.toJson());
file.close();
QMessageBox::information(&dlg, tr("成功"), tr("列配置已保存"));
} else {
QMessageBox::warning(&dlg, tr("错误"), tr("无法保存文件:%1").arg(file.errorString()));
}
});
connect(btnLoad, &QPushButton::clicked, this, [this, &dlg, colCheckBoxMap]() {
QString loadDir = QDir::currentPath() + "/columnConfigs";
QString fileName = QFileDialog::getOpenFileName(&dlg, tr("加载列配置"),
loadDir, "JSON Files (*.json)");
if (fileName.isEmpty()) return;
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::warning(&dlg, tr("错误"), tr("无法打开文件:%1").arg(file.errorString()));
return;
}
QByteArray data = file.readAll();
file.close();
QJsonParseError err;
QJsonDocument doc = QJsonDocument::fromJson(data, &err);
if (err.error != QJsonParseError::NoError || !doc.isObject()) {
QMessageBox::warning(&dlg, tr("错误"), tr("JSON解析失败"));
return;
}
QJsonObject root = doc.object();
for (int col = 0; col < m_model->columnCount(); ++col) {
QString header = m_model->headerData(col, Qt::Horizontal).toString();
if (root.contains(header)) {
colCheckBoxMap[col]->blockSignals(true);
colCheckBoxMap[col]->setChecked(root[header].toBool(false));
colCheckBoxMap[col]->blockSignals(false);
}
}
// 一次性更新列隐藏
for (int col : colCheckBoxMap.keys()) {
m_tableView->setColumnHidden(col, !colCheckBoxMap[col]->isChecked());
}
});
dlg.exec();
}
void DeviceConfigView::reset()
{
m_model->blockSignals(true);
for (int row = 0; row < m_model->rowCount(); ++row) {
for (int col = 0; col < m_model->columnCount(); ++col) {
m_model->setData(m_model->index(row, col), QVariant());
}
}
m_model->blockSignals(false);
emit m_model->dataChanged(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, m_model->columnCount() - 1));
}
void DeviceConfigView::setColumnMapping(const QHash<QString, QString> &mapping)
{
m_columnToJsonKey = mapping;
// 构建反向映射(可选)
m_jsonKeyToColumn.clear();
for (auto it = m_columnToJsonKey.constBegin(); it != m_columnToJsonKey.constEnd(); ++it) {
m_jsonKeyToColumn[it.value()] = m_model->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString().indexOf(it.key());
}
}
void DeviceConfigView::InitViewWorkspace(const QString &project_name)
{
}
void DeviceConfigView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
{
if (data_files_set.isEmpty()) {
LOG_WARN("文件集合为空");
return;
}
QString filePath = data_files_set.first().toString();
LOG_INFO("读取文件: " + filePath);
}

View File

@ -1,62 +0,0 @@
#ifndef DEVICECONFIGVIEW_H
#define DEVICECONFIGVIEW_H
#include <QWidget>
#include <QHash>
#include "MeasureAnalysisView.h"
class QTableView;
class QStandardItemModel;
class QPushButton;
class DeviceConfigView : public MeasureAnalysisView
{
Q_OBJECT
public:
explicit DeviceConfigView(QWidget *parent = nullptr);
~DeviceConfigView();
bool loadJson(const QString &filePath);
bool saveJson(const QString &filePath);
QStandardItemModel* getModel() const;
void showColumnControlDialog();
void reset();
void setColumnMapping(const QHash<QString, QString> &mapping);
virtual void InitViewWorkspace(const QString& project_name) override final;
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set);
QList<int> getCheckedRows() const;
signals:
void dataChanged();
private slots:
void onActionButtonClicked();
private:
void initTableView();
void setupActionColumnButtons();
bool parseJsonImpl(const QByteArray &data);
QList<int> selectTargetChannels(int currentChannel) const;
QTableView *m_tableView;
QStandardItemModel *m_model;
QHash<QString, QString> m_columnToJsonKey; // 列头 -> JSON键名
QHash<QString, int> m_jsonKeyToColumn; // 反向映射,用于快速查找列索引
};
#endif // DEVICECONFIGVIEW_H

View File

@ -1,333 +0,0 @@
#include "DeviceParameterConfig.h"
#include "DeviceParameterConfigList.h"
#include "DeviceConfigView.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include <QCheckBox>
#include <QPushButton>
#include <QFile>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDir>
#include <QDebug>
DeviceParameterConfig::DeviceParameterConfig(QWidget *parent)
: QWidget(parent)
, m_configList(nullptr)
, m_configView(nullptr)
, m_lineEditFileName(nullptr)
, m_textEditRemark(nullptr)
, m_checkBoxSaveToDevice(nullptr)
, m_btnSave(nullptr)
, m_btnSetColumn(nullptr)
{
setupUi();
initColumnMapping(); // 设置默认映射
m_configView->setColumnMapping(m_columnToJsonKey);
m_configList->loadConfigsFromFolder(); // 加载默认目录下的配置文件
}
DeviceParameterConfig::~DeviceParameterConfig()
{
}
void DeviceParameterConfig::setupUi()
{
// 主布局:左右分栏
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(10);
// 左侧:配置列表
m_configList = new DeviceParameterConfigList(this);
mainLayout->addWidget(m_configList, 1);
// 右侧:垂直布局
QVBoxLayout *rightLayout = new QVBoxLayout();
mainLayout->addLayout(rightLayout, 9);
// 右侧上部:文件名、保存按钮、备注说明
QHBoxLayout *topLayout = new QHBoxLayout();
QLabel *labelName = new QLabel(QStringLiteral(u"配置命名:"), this);
m_lineEditFileName = new QLineEdit(this);
m_btnSave = new QPushButton(QStringLiteral(u"保存到测量分析"), this);
m_checkBoxSaveToDevice = new QCheckBox(QStringLiteral(u"保存到设备参数配置管理"), this);
topLayout->addWidget(labelName);
topLayout->addWidget(m_lineEditFileName, 1);
topLayout->addWidget(m_btnSave);
topLayout->addWidget(m_checkBoxSaveToDevice);
rightLayout->addLayout(topLayout);
QHBoxLayout *remarkLayout = new QHBoxLayout();
QLabel *labelRemark = new QLabel(QStringLiteral(u"备注说明:"), this);
m_textEditRemark = new QTextEdit(this);
m_textEditRemark->setMaximumHeight(80);
remarkLayout->addWidget(labelRemark);
remarkLayout->addWidget(m_textEditRemark, 1);
rightLayout->addLayout(remarkLayout);
// 右侧中部:设置列按钮
QHBoxLayout *buttonLayout = new QHBoxLayout();
m_btnSetColumn = new QPushButton(QStringLiteral(u"设置列"), this);
buttonLayout->addWidget(m_btnSetColumn);
buttonLayout->addStretch();
rightLayout->addLayout(buttonLayout);
// 右侧下部:参数表格视图
m_configView = new DeviceConfigView(this);
rightLayout->addWidget(m_configView, 1);
// 连接信号槽
connect(m_configList, &DeviceParameterConfigList::configSelected,
this, &DeviceParameterConfig::onConfigSelected);
connect(m_configList, &DeviceParameterConfigList::configDeleted,
this, &DeviceParameterConfig::onConfigDeleted);
connect(m_btnSave, &QPushButton::clicked,
this, &DeviceParameterConfig::onSaveButtonClicked);
connect(m_btnSetColumn, &QPushButton::clicked,
this, &DeviceParameterConfig::onSetColumnButtonClicked);
connect(m_configList, &DeviceParameterConfigList::createNewConfigRequested,
this, &DeviceParameterConfig::onCreateNewConfigRequested);
connect(m_configView, &DeviceConfigView::dataChanged,
this, [this]() {
// 数据改变时,在文件名后添加星号表示未保存
if (!m_lineEditFileName->text().isEmpty() && !m_lineEditFileName->text().endsWith(" *")) {
m_lineEditFileName->setText(m_lineEditFileName->text() + " *");
}
});
}
void DeviceParameterConfig::initColumnMapping()
{
// 与原 EquipmentParameterSettingManagement 完全相同的映射
m_columnToJsonKey.clear();
m_columnToJsonKey[QStringLiteral(u"数据传输模式")] = "eTransferModel";
m_columnToJsonKey[QStringLiteral(u"硬件增益")] = "iDeviceGain";
m_columnToJsonKey[QStringLiteral(u"硬件增益选择索引")] = "iDeviceGainSelectIndex";
m_columnToJsonKey[QStringLiteral(u"软件增益")] = "iSoftGain";
m_columnToJsonKey[QStringLiteral(u"时间常数")] = "dConstTime";
m_columnToJsonKey[QStringLiteral(u"成形时间")] = "iFormTime";
m_columnToJsonKey[QStringLiteral(u"快通道触发阈值")] = "iFastChannelTrigerValue";
m_columnToJsonKey[QStringLiteral(u"多道分辨率")] = "iChannelNum";
m_columnToJsonKey[QStringLiteral(u"控制功能")] = "";
m_columnToJsonKey[QStringLiteral(u"幅度提前延迟")] = "";
m_columnToJsonKey[QStringLiteral(u"积分长度")] = "";
m_columnToJsonKey[QStringLiteral(u"dcfd缩放倍数")] = "";
m_columnToJsonKey[QStringLiteral(u"dcfd延迟")] = "";
m_columnToJsonKey[QStringLiteral(u"直流偏移")] = "iCurrentOffset";
m_columnToJsonKey[QStringLiteral(u"最大能量范围")] = "iMaxEnergy";
m_columnToJsonKey[QStringLiteral(u"Am 峰面积寻峰法的面积比例")] = "iAMPeakDiv";
m_columnToJsonKey[QStringLiteral(u"K40与 Am241的峰位校正系数")] = "iHVDelt";
m_columnToJsonKey[QStringLiteral(u"高压关断阈值")] = "iHVDelt";
m_columnToJsonKey[QStringLiteral(u"获取能谱周期")] = "iGetSpecturmPeirod";
m_columnToJsonKey[QStringLiteral(u"总测量时间")] = "iTotalMeasureTime";
m_columnToJsonKey[QStringLiteral(u"总测量次数")] = "iTotalMeasureCount";
m_columnToJsonKey[QStringLiteral(u"滤波参数")] = "iTrapeTopShitBit";
m_columnToJsonKey[QStringLiteral(u"上升时间")] = "iRiseTime";
m_columnToJsonKey[QStringLiteral(u"平顶时间")] = "iTopTime";
m_columnToJsonKey[QStringLiteral(u"ICR 校正使能")] = "bICRCorrect";
m_columnToJsonKey[QStringLiteral(u"CRZA 值")] = "iCRZAValue";
m_columnToJsonKey[QStringLiteral(u"ZA 使能值")] = "iZAEnable";
}
void DeviceParameterConfig::setColumnMapping(const QHash<QString, QString> &mapping)
{
m_columnToJsonKey = mapping;
m_configView->setColumnMapping(mapping);
}
bool DeviceParameterConfig::loadConfig(const QString &filePath)
{
if (!m_configView->loadJson(filePath))
return false;
m_currentFilePath = filePath;
QFileInfo info(filePath);
m_lineEditFileName->setText(info.fileName());
// 读取 JSON 中的备注字段
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (doc.isObject()) {
QJsonObject obj = doc.object();
if (obj.contains("remark")) {
m_textEditRemark->setPlainText(obj["remark"].toString());
} else {
m_textEditRemark->clear();
}
}
}
emit configLoaded(filePath); // 此信号未在头文件中声明,可添加;若不需要可移除
return true;
}
bool DeviceParameterConfig::saveCurrentConfig()
{
if (m_currentFilePath.isEmpty()) {
QMessageBox::warning(this, QStringLiteral(u"错误"), QStringLiteral(u"没有选中的配置文件"));
return false;
}
// 保存表格数据
if (!m_configView->saveJson(m_currentFilePath))
return false;
// 保存备注到 JSON
QFile file(m_currentFilePath);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "无法打开文件读取备注:" << file.errorString();
return false;
}
QByteArray data = file.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (!doc.isObject()) {
qWarning() << "JSON 不是对象";
return false;
}
QJsonObject root = doc.object();
root["remark"] = m_textEditRemark->toPlainText();
if (!file.open(QIODevice::WriteOnly)) {
qWarning() << "无法写入文件:" << file.errorString();
return false;
}
file.write(QJsonDocument(root).toJson());
file.close();
// 移除文件名后的星号
QString fileName = m_lineEditFileName->text();
if (fileName.endsWith(" *"))
fileName.chop(2);
m_lineEditFileName->setText(fileName);
return true;
}
QString DeviceParameterConfig::getCurrentFileName() const
{
return QFileInfo(m_currentFilePath).fileName();
}
QString DeviceParameterConfig::getRemark() const
{
return m_textEditRemark->toPlainText();
}
void DeviceParameterConfig::setRemark(const QString &remark)
{
m_textEditRemark->setPlainText(remark);
}
void DeviceParameterConfig::onConfigSelected(const QString &filePath)
{
loadConfig(filePath);
}
void DeviceParameterConfig::onConfigDeleted(const QString &fileName)
{
if (m_lineEditFileName->text() == fileName) {
m_lineEditFileName->clear();
m_textEditRemark->clear();
m_configView->reset();
m_currentFilePath.clear();
}
}
void DeviceParameterConfig::onCreateNewConfigRequested(const QString &fileName)
{
QString filePath = QDir::currentPath() + "/parameterConfig/" + fileName;
if (createDefaultConfigFile(filePath)) {
// 刷新列表
m_configList->refresh();
// 选中新建的文件
m_configList->setCurrentFile(fileName);
// 自动加载该配置(可选)
loadConfig(filePath);
} else {
QMessageBox::warning(this, QStringLiteral(u"错误"), QStringLiteral(u"无法创建配置文件:%1").arg(filePath));
}
}
void DeviceParameterConfig::onSaveButtonClicked()
{
if (!saveCurrentConfig()) {
QMessageBox::warning(this, QStringLiteral(u"错误"), QStringLiteral(u"保存配置文件失败"));
return;
}
// 如果勾选了“保存到设备参数配置管理”,刷新左侧列表
if (m_checkBoxSaveToDevice->isChecked()) {
m_configList->refresh();
}
// 发出信号,供外部处理(例如将参数发送到测量分析模块)
emit saveToMeasurementRequested(m_currentFilePath);
}
void DeviceParameterConfig::onSetColumnButtonClicked()
{
m_configView->showColumnControlDialog();
}
bool DeviceParameterConfig::createDefaultConfigFile(const QString &filePath)
{
// 创建默认配置文件(含 32 个通道)
QJsonObject rootObj;
rootObj["command"] = "SET";
QJsonArray channelsArray;
QJsonObject defaultChannel;
defaultChannel["eTransferModel"] = "eSpecturmMode";
defaultChannel["iDeviceGain"] = 1;
defaultChannel["iDeviceGainSelectIndex"] = 1;
defaultChannel["iSoftGain"] = 3000;
defaultChannel["dConstTime"] = 45.0;
defaultChannel["iFormTime"] = 3;
defaultChannel["iFastChannelTrigerValue"] = 10.0;
defaultChannel["iChannelNum"] = 1024;
defaultChannel["iHighVoltage"] = 0;
defaultChannel["iInputVoltageDesc"] = 0;
defaultChannel["iCRDivMode"] = 0;
defaultChannel["iInputSignalPostive"] = 0;
defaultChannel["iCurrentOffset"] = 0;
defaultChannel["iMaxEnergy"] = 0;
defaultChannel["iAMPeakDiv"] = 0;
defaultChannel["iHVDelt"] = 0;
defaultChannel["iHVCtrl"] = 0;
defaultChannel["iGetSpecturmPeirod"] = 1;
defaultChannel["iTotalMeasureTime"] = 10;
defaultChannel["iTotalMeasureCount"] = 1;
defaultChannel["iTrapeTopShitBit"] = 0;
defaultChannel["iRiseTime"] = 2;
defaultChannel["iTopTime"] = 2;
defaultChannel["bICRCorrect"] = false;
defaultChannel["iCRZAValue"] = 0;
defaultChannel["iZAEnable"] = 30;
defaultChannel["reserve"] = QJsonArray();
defaultChannel["pUserConfigInfo"] = QJsonObject();
for (int i = 0; i < 32; ++i) {
channelsArray.append(defaultChannel);
}
rootObj["channels"] = channelsArray;
rootObj["remark"] = "";
QJsonDocument doc(rootObj);
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly))
return false;
file.write(doc.toJson());
file.close();
return true;
}

View File

@ -1,73 +0,0 @@
#ifndef DEVICEPARAMETERCONFIG_H
#define DEVICEPARAMETERCONFIG_H
#include <QWidget>
#include <QHash>
class DeviceParameterConfigList;
class DeviceConfigView;
class QLineEdit;
class QTextEdit;
class QCheckBox;
class QPushButton;
class DeviceParameterConfig : public QWidget
{
Q_OBJECT
public:
explicit DeviceParameterConfig(QWidget *parent = nullptr);
~DeviceParameterConfig();
void setColumnMapping(const QHash<QString, QString> &mapping);
bool loadConfig(const QString &filePath);
bool saveCurrentConfig();
QString getCurrentFileName() const;
QString getRemark() const;
void setRemark(const QString &remark);
signals:
void saveToMeasurementRequested(const QString &filePath);
void configLoaded(QString );
private slots:
void onConfigSelected(const QString &filePath);
void onConfigDeleted(const QString &fileName);
void onCreateNewConfigRequested(const QString &fileName);
void onSaveButtonClicked();
void onSetColumnButtonClicked();
private:
void setupUi();
bool createDefaultConfigFile(const QString &filePath);
void initColumnMapping(); // 初始化默认映射(若外部未调用则使用默认)
// 子控件
DeviceParameterConfigList *m_configList;
DeviceConfigView *m_configView;
// 周边控件
QLineEdit *m_lineEditFileName;
QTextEdit *m_textEditRemark;
QCheckBox *m_checkBoxSaveToDevice;
QPushButton *m_btnSave;
QPushButton *m_btnSetColumn;
QString m_currentFilePath;
QHash<QString, QString> m_columnToJsonKey; // 列头->JSON键映射
};
#endif // DEVICEPARAMETERCONFIG_H

View File

@ -1,214 +0,0 @@
#include "DeviceParameterConfigList.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include <QPushButton>
#include <QDir>
#include <QFile>
#include <QInputDialog>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
#include <QDateTime>
#include <QLabel>
DeviceParameterConfigList::DeviceParameterConfigList(QWidget *parent)
: QWidget(parent)
, m_listWidget(nullptr)
, m_btnAdd(nullptr)
, m_btnDelete(nullptr)
{
setupUi();
}
DeviceParameterConfigList::~DeviceParameterConfigList()
{
}
void DeviceParameterConfigList::setupUi()
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
QLabel *ListWidgetName = new QLabel(QStringLiteral(u"设备参数配置列表"));
mainLayout->addWidget(ListWidgetName);
m_listWidget = new QListWidget(this);
mainLayout->addWidget(m_listWidget);
QHBoxLayout *btnLayout = new QHBoxLayout();
m_btnAdd = new QPushButton(QStringLiteral(u"添加"), this);
m_btnDelete = new QPushButton(QStringLiteral(u"删除"), this);
btnLayout->addWidget(m_btnAdd);
btnLayout->addWidget(m_btnDelete);
btnLayout->addStretch();
mainLayout->addLayout(btnLayout);
connect(m_listWidget, &QListWidget::itemClicked, this, &DeviceParameterConfigList::onItemClicked);
connect(m_btnAdd, &QPushButton::clicked, this, &DeviceParameterConfigList::onAddClicked);
connect(m_btnDelete, &QPushButton::clicked, this, &DeviceParameterConfigList::onDeleteClicked);
}
void DeviceParameterConfigList::loadConfigsFromFolder(const QString &folderPath)
{
if (folderPath.isEmpty()) {
m_folderPath = QDir::currentPath() + "/parameterConfig";
} else {
m_folderPath = folderPath;
}
QDir dir(m_folderPath);
if (!dir.exists()) {
dir.mkpath(m_folderPath);
}
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
QStringList files = dir.entryList();
updateList(files);
}
void DeviceParameterConfigList::updateList(const QStringList &fileList)
{
m_listWidget->clear();
for (const QString &file : fileList) {
if (file.endsWith(".json", Qt::CaseInsensitive)) {
m_listWidget->addItem(file);
}
}
}
QString DeviceParameterConfigList::getCurrentFilePath() const
{
QListWidgetItem *item = m_listWidget->currentItem();
if (!item) return QString();
return m_folderPath + "/" + item->text();
}
QString DeviceParameterConfigList::getCurrentFileName() const
{
QListWidgetItem *item = m_listWidget->currentItem();
return item ? item->text() : QString();
}
void DeviceParameterConfigList::setCurrentFile(const QString &fileName)
{
QList<QListWidgetItem*> items = m_listWidget->findItems(fileName, Qt::MatchExactly);
if (!items.isEmpty()) {
m_listWidget->setCurrentItem(items.first());
emit configSelected(getCurrentFilePath());
}
}
void DeviceParameterConfigList::refresh()
{
loadConfigsFromFolder(m_folderPath);
}
void DeviceParameterConfigList::onItemClicked(QListWidgetItem *item)
{
if (item) {
emit configSelected(m_folderPath + "/" + item->text());
}
}
void DeviceParameterConfigList::onAddClicked()
{
bool ok;
QString fileName = QInputDialog::getText(this, QStringLiteral(u"新建配置"),
QStringLiteral(u"请输入配置文件名(无需后缀):"),
QLineEdit::Normal,
QString("NewConfig_%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")),
&ok);
if (!ok || fileName.isEmpty()) return;
if (!fileName.endsWith(".json", Qt::CaseInsensitive))
fileName += ".json";
QString filePath = m_folderPath + "/" + fileName;
if (QFile::exists(filePath)) {
QMessageBox::warning(this, QStringLiteral(u"错误"), QStringLiteral(u"文件已存在,请使用其他名称。"));
return;
}
// 发出创建请求,由外部(主窗口)决定默认内容
emit createNewConfigRequested(fileName);
}
void DeviceParameterConfigList::onDeleteClicked()
{
QListWidgetItem *currentItem = m_listWidget->currentItem();
if (!currentItem) {
QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"请先选择要删除的配置文件。"));
return;
}
QString fileName = currentItem->text();
QString filePath = m_folderPath + "/" + fileName;
int ret = QMessageBox::question(this, QStringLiteral(u"确认删除"),
QStringLiteral(u"确定要删除文件 \"%1\" 吗?").arg(fileName),
QMessageBox::Yes | QMessageBox::No);
if (ret != QMessageBox::Yes) return;
QFile file(filePath);
if (file.remove()) {
delete currentItem;
emit configDeleted(fileName);
QMessageBox::information(this, QStringLiteral(u"成功"), QStringLiteral(u"文件已删除。"));
} else {
QMessageBox::warning(this, QStringLiteral(u"错误"), QStringLiteral(u"无法删除文件:%1").arg(file.errorString()));
}
}
bool DeviceParameterConfigList::createDefaultConfigFile(const QString &filePath)
{
// 默认配置内容(与原来保持一致)
QJsonObject rootObj;
rootObj["command"] = "SET";
QJsonArray channelsArray;
QJsonObject defaultChannel;
defaultChannel["eTransferModel"] = "eSpecturmMode";
defaultChannel["iDeviceGain"] = 1;
defaultChannel["iDeviceGainSelectIndex"] = 1;
defaultChannel["iSoftGain"] = 3000;
defaultChannel["dConstTime"] = 45.0;
defaultChannel["iFormTime"] = 3;
defaultChannel["iFastChannelTrigerValue"] = 10.0;
defaultChannel["iChannelNum"] = 1024;
defaultChannel["iHighVoltage"] = 0;
defaultChannel["iInputVoltageDesc"] = 0;
defaultChannel["iCRDivMode"] = 0;
defaultChannel["iInputSignalPostive"] = 0;
defaultChannel["iCurrentOffset"] = 0;
defaultChannel["iMaxEnergy"] = 0;
defaultChannel["iAMPeakDiv"] = 0;
defaultChannel["iHVDelt"] = 0;
defaultChannel["iHVCtrl"] = 0;
defaultChannel["iGetSpecturmPeirod"] = 1;
defaultChannel["iTotalMeasureTime"] = 10;
defaultChannel["iTotalMeasureCount"] = 1;
defaultChannel["iTrapeTopShitBit"] = 0;
defaultChannel["iRiseTime"] = 2;
defaultChannel["iTopTime"] = 2;
defaultChannel["bICRCorrect"] = false;
defaultChannel["iCRZAValue"] = 0;
defaultChannel["iZAEnable"] = 30;
defaultChannel["reserve"] = QJsonArray();
defaultChannel["pUserConfigInfo"] = QJsonObject();
for (int i = 0; i < 32; ++i) {
channelsArray.append(defaultChannel);
}
rootObj["channels"] = channelsArray;
QJsonDocument doc(rootObj);
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly)) {
return false;
}
file.write(doc.toJson());
file.close();
return true;
}

View File

@ -1,56 +0,0 @@
#ifndef DEVICEPARAMETERCONFIGLIST_H
#define DEVICEPARAMETERCONFIGLIST_H
#include <QWidget>
#include <QListWidgetItem>
class QListWidget;
class QPushButton;
class DeviceParameterConfigList : public QWidget
{
Q_OBJECT
public:
explicit DeviceParameterConfigList(QWidget *parent = nullptr);
~DeviceParameterConfigList();
void loadConfigsFromFolder(const QString &folderPath = QString());
QString getCurrentFilePath() const;
QString getCurrentFileName() const;
void setCurrentFile(const QString &fileName);
void refresh();
signals:
void configSelected(const QString &filePath);
void configDeleted(const QString &fileName);
void createNewConfigRequested(const QString &fileName);
private slots:
void onItemClicked(QListWidgetItem *item);
void onAddClicked();
void onDeleteClicked();
private:
void setupUi();
void updateList(const QStringList &fileList);
bool createDefaultConfigFile(const QString &filePath);
QListWidget *m_listWidget;
QPushButton *m_btnAdd;
QPushButton *m_btnDelete;
QString m_folderPath;
};
#endif // DEVICEPARAMETERCONFIGLIST_H

View File

@ -1,384 +0,0 @@
#include "DeviceParameterProxy.h"
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include <QLineEdit>
#include <QToolTip>
#include <QTimer>
#include <QKeyEvent>
#include <QMessageBox>
#include <QRegularExpressionValidator>
#include <QDebug>
DeviceParameterProxy::DeviceParameterProxy(QObject *parent) : QStyledItemDelegate(parent)
{
}
QWidget* DeviceParameterProxy::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
int col = index.column();
switch (col)
{
case 0: // 数据传输模式(枚举)
{
QComboBox *combo = new QComboBox(parent);
combo->addItems(QStringList() << QStringLiteral(u"谱线模式") << QStringLiteral(u"波形模式") << QStringLiteral(u"ADC模式") << QStringLiteral(u"列表模式") << QStringLiteral(u"α/β模式"));
return combo;
}
case 1: // 硬件增益(档位)
{
QComboBox *combo = new QComboBox(parent);
combo->addItems(QStringList() << QStringLiteral(u"1") << QStringLiteral(u"2") << QStringLiteral(u"4") << QStringLiteral(u"8") << QStringLiteral(u"16"));
return combo;
}
case 2: // 硬件增益选择索引
{
QComboBox *combo = new QComboBox(parent);
combo->addItems(QStringList() << QStringLiteral(u"1") << QStringLiteral(u"2") << QStringLiteral(u"3") << QStringLiteral(u"4") << QStringLiteral(u"5"));
return combo;
}
case 3: // 软件增益32位无符号
{
QLineEdit *edit = new QLineEdit(parent);
edit->setValidator(new UInt32Validator(edit));
edit->setProperty("rangeHint", "0 ~ 4294967295");
edit->installEventFilter(const_cast<DeviceParameterProxy*>(this));
return edit;
}
case 4: // 时间常数double μs
{
QDoubleSpinBox *spin = new QDoubleSpinBox(parent);
spin->setRange(0.0, 1000.0);
spin->setSingleStep(1.0);
spin->setDecimals(2);
return spin;
}
case 5: // 成形时间int μs
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(1, 10);
return spin;
}
case 6: // 快通道触发阈值double 0.1mV
{
QDoubleSpinBox *spin = new QDoubleSpinBox(parent);
spin->setRange(0.0, 10000.0);
spin->setSingleStep(0.1);
spin->setDecimals(1);
return spin;
}
case 7: // 多道分辨率2的幂
{
QComboBox *combo = new QComboBox(parent);
combo->addItems(QStringList() << QStringLiteral(u"256") << QStringLiteral(u"512") << QStringLiteral(u"1024") << QStringLiteral(u"2048") << QStringLiteral(u"4096") << QStringLiteral(u"8192") << QStringLiteral(u"16384"));
return combo;
}
case 8: // 控制功能(位掩码,暂用十进制输入)
{
QLineEdit *edit = new QLineEdit(parent);
// 允许输入十进制数字,不设范围限制(业务层处理)
return edit;
}
case 9: // 幅度提前延迟unsigned char
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 255);
return spin;
}
case 10: // 积分长度unsigned char
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 255);
return spin;
}
case 11: // dcfd缩放倍数unsigned char
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 255);
return spin;
}
case 12: // dcfd延迟unsigned char
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 255);
return spin;
}
case 13: // 直流偏移mV
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(-1000, 1000);
return spin;
}
case 14: // 最大能量范围keV
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 99999);
return spin;
}
case 15: // Am峰面积寻峰法的面积比例%
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 100);
return spin;
}
case 16: // K40与Am241的峰位校正系数short
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(-32768, 32767);
return spin;
}
case 17: // 高压关断阈值short
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(-32768, 32767);
return spin;
}
case 18: // 获取能谱周期(秒)
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 86400); // 一天
return spin;
}
case 19: // 总测量时间__int6464位
{
QLineEdit *edit = new QLineEdit(parent);
edit->setValidator(new Int64Validator(edit));
edit->setProperty("rangeHint", "0 ~ 9223372036854775807");
edit->installEventFilter(const_cast<DeviceParameterProxy*>(this));
return edit;
}
case 20: // 总测量次数
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 1000000); // 可调大
return spin;
}
case 21: // 滤波参数
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 3);
return spin;
}
case 22: // 上升时间μs
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(1, 255);
return spin;
}
case 23: // 平顶时间μs
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(1, 255);
return spin;
}
case 24: // ICR校正使能布尔
{
QComboBox *combo = new QComboBox(parent);
combo->addItems(QStringList() << QStringLiteral(u"关闭") << QStringLiteral(u"启用"));
return combo;
}
case 25: // CRZA值
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 1000000); // 合理范围
return spin;
}
case 26: // ZA使能值
{
QSpinBox *spin = new QSpinBox(parent);
spin->setRange(0, 100);
return spin;
}
default:
return new QLineEdit(parent);
}
}
void DeviceParameterProxy::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QVariant value = index.data(Qt::EditRole);
int col = index.column();
switch (col)
{
case 0: // QComboBox
case 1:
case 2:
case 7:
case 24:
{
QComboBox *combo = qobject_cast<QComboBox*>(editor);
if (combo) {
int idx = combo->findText(value.toString());
if (idx >= 0) combo->setCurrentIndex(idx);
}
break;
}
case 3: // QLineEdit软件增益
case 8: // QLineEdit控制功能
case 19: // QLineEdit总测量时间
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
if (edit) edit->setText(value.toString());
break;
}
case 4: // QDoubleSpinBox
case 6:
{
QDoubleSpinBox *spin = qobject_cast<QDoubleSpinBox*>(editor);
if (spin) spin->setValue(value.toDouble());
break;
}
case 5: // QSpinBox
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 20:
case 21:
case 22:
case 23:
case 25:
case 26:
{
QSpinBox *spin = qobject_cast<QSpinBox*>(editor);
if (spin) spin->setValue(value.toInt());
break;
}
default:
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
if (edit) edit->setText(value.toString());
break;
}
}
}
void DeviceParameterProxy::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
int col = index.column();
switch (col)
{
case 0:
case 1:
case 2:
case 7:
case 24:
{
QComboBox *combo = qobject_cast<QComboBox*>(editor);
if (combo) model->setData(index, combo->currentText());
break;
}
case 3: // 软件增益字符串存储因为可能超出int范围
case 8: // 控制功能(字符串存储)
case 19: // 总测量时间(字符串存储)
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
// if (edit) model->setData(index, edit->text());
if (edit) {
// 提交前再次验证(防止通过回车提交无效数据)
QString text = edit->text();
int pos = 0;
if (edit->validator() && edit->validator()->validate(text, pos) == QValidator::Acceptable) {
model->setData(index, text);
} else {
// 无效数据不写入模型,并显示提示
QString rangeHint = edit->property("rangeHint").toString();
QPoint pos = edit->mapToGlobal(edit->rect().topRight());
QToolTip::showText(pos, QString("取值范围: %1").arg(rangeHint), edit);
// 焦点留在编辑器(但此时编辑器即将销毁,所以需要延迟重新打开?)
// 实际上 setModelData 被调用时编辑器即将销毁,我们无法阻止。
// 因此更好的方法是在事件过滤器中拦截回车,避免走到这里。
}
}
break;
}
case 4:
case 6:
{
QDoubleSpinBox *spin = qobject_cast<QDoubleSpinBox*>(editor);
if (spin) model->setData(index, spin->value());
break;
}
case 5:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 20:
case 21:
case 22:
case 23:
case 25:
case 26:
{
QSpinBox *spin = qobject_cast<QSpinBox*>(editor);
if (spin) model->setData(index, spin->value());
break;
}
default:
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
if (edit) model->setData(index, edit->text());
break;
}
}
}
void DeviceParameterProxy::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
bool DeviceParameterProxy::eventFilter(QObject *obj, QEvent *event)
{
QLineEdit *edit = qobject_cast<QLineEdit*>(obj);
if (!edit || !edit->validator())
return QStyledItemDelegate::eventFilter(obj, event);
if (event->type() == QEvent::FocusOut) {
QString text = edit->text();
int pos = 0;
if (edit->validator()->validate(text, pos) != QValidator::Acceptable) {
QString rangeHint = edit->property("rangeHint").toString();
QPoint pos = edit->mapToGlobal(edit->rect().topRight());
QToolTip::showText(pos, QStringLiteral(u"取值范围: %1").arg(rangeHint), edit);
// 延迟重新获得焦点
QTimer::singleShot(0, edit, SLOT(setFocus()));
return true; // 阻止焦点离开
} else {
QToolTip::hideText();
}
}
else if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
QString text = edit->text();
int pos = 0;
if (edit->validator()->validate(text, pos) != QValidator::Acceptable) {
QString rangeHint = edit->property("rangeHint").toString();
QPoint pos = edit->mapToGlobal(edit->rect().topRight());
QToolTip::showText(pos, QStringLiteral(u"取值范围: %1").arg(rangeHint), edit);
return true; // 拦截回车,不提交
} else {
QToolTip::hideText();
// 允许回车提交Qt 会正常处理
}
}
}
return QStyledItemDelegate::eventFilter(obj, event);
}

View File

@ -1,119 +0,0 @@
#ifndef DEVICEPARAMETERPROXY_H
#define DEVICEPARAMETERPROXY_H
#include <QStyledItemDelegate>
#include <QIntValidator>
#include <QLineEdit>
// ==================== 自定义验证器 ====================
/**
* @brief 32 0 ~ 4294967295
*/
class UInt32Validator : public QValidator
{
public:
UInt32Validator(QObject *parent = nullptr) : QValidator(parent) {}
State validate(QString &input, int &pos) const override
{
if (input.isEmpty())
return Intermediate;
bool ok;
quint64 value = input.toULongLong(&ok);
if (!ok)
return Invalid;
if (value <= 4294967295ULL)
return Acceptable;
return Invalid;
}
void fixup(QString &input) const override
{
input.clear();
}
};
/**
* @brief 64 0 ~ 9223372036854775807
* __int64
*/
class Int64Validator : public QValidator
{
public:
Int64Validator(QObject *parent = nullptr) : QValidator(parent) {}
State validate(QString &input, int &pos) const override
{
if (input.isEmpty())
return Intermediate;
bool ok;
qint64 value = input.toLongLong(&ok);
if (!ok)
return Invalid;
if (value >= 0 && value <= 9223372036854775807LL)
return Acceptable;
return Invalid;
}
void fixup(QString &input) const override
{
input.clear();
}
};
/**
* @brief
*
*
*/
class DeviceParameterProxy : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit DeviceParameterProxy(QObject *parent = nullptr);
/**
* @brief
* @param parent
* @param option
* @param index
* @return
*/
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
/**
* @brief
* @param editor
* @param index
*/
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
/**
* @brief
* @param editor
* @param model
* @param index
*/
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
/**
* @brief
* @param editor
* @param option
* @param index
*/
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
protected:
bool eventFilter(QObject *obj, QEvent *event) override; // 事件过滤器,用于验证输入和显示提示
};
#endif // DEVICEPARAMETERPROXY_H

View File

@ -1,18 +1,21 @@
#define NOMINMAX
//#include <locale>
#include <vector>
#include <algorithm>
#include "EnergyCountPeakFitView.h"
#include "CustomQwtPlot.h"
#include "PlotRectItem.h"
#include "csv.h"
#include <GlobalDefine.h>
#include <QCheckBox>
#include <QDebug>
#include <QDialog>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QMenu>
#include <QPushButton>
#include <QwtLegend>
#include <QwtPlotCanvas>
#include <QwtPlotCurve>
#include <QwtPlotMarker>
#include <QwtScaleDiv>
#include <QwtScaleMap>
#include <QwtText>
#include <QDialog>
@ -27,8 +30,9 @@
#include <QMessageBox>
#include <QListWidget>
#include <QDateTime>
#include <QJsonDocument>
#include <QDir>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDir>
#include <QTableView>
@ -37,6 +41,7 @@
#include "MeasureAnalysisProjectModel.h"
#include "BusyIndicator.h"
QJsonObject PeakFitHistoryItem::toJson() const
{
QJsonObject obj;
@ -106,7 +111,7 @@ PeakFitHistoryItem PeakFitHistoryItem::fromJson(const QJsonObject& obj)
return item;
}
EnergyCountPeakFitView::EnergyCountPeakFitView(QWidget *parent)
EnergyCountPeakFitView::EnergyCountPeakFitView(QWidget* parent)
: MeasureAnalysisView { parent }
{
this->setViewType(PlotFrame);
@ -123,29 +128,31 @@ EnergyCountPeakFitView::~EnergyCountPeakFitView()
{
LOG_DEBUG(QStringLiteral(u"%1析构.").arg(this->GetViewName()));
delete _rubberBand;
clearAllSelectionRects();
clearFitCurves();
clearAllSelectionRects();
clearFitCurves();
}
void EnergyCountPeakFitView::InitViewWorkspace(const QString &project_name)
void EnergyCountPeakFitView::InitViewWorkspace(const QString& project_name)
{
Q_UNUSED(project_name);
if (project_name.isEmpty()) return;
auto project_model = ProjectList::Instance()->GetProjectModel(project_name);
if (!project_model) return;
if (project_name.isEmpty())
return;
auto project_model = ProjectList::Instance()->GetProjectModel(project_name);
if (!project_model)
return;
QDir project_dir(project_model->GetProjectDir());
_workspace = project_dir.filePath(this->GetViewName());
if (!QDir(_workspace).exists())
project_dir.mkpath(_workspace);
QDir project_dir(project_model->GetProjectDir());
_workspace = project_dir.filePath(this->GetViewName());
if (!QDir(_workspace).exists())
project_dir.mkpath(_workspace);
_historyFilePath = QDir(_workspace).filePath("peak_fit_history.json");
loadHistoryFromFile();
_historyFilePath = QDir(_workspace).filePath("peak_fit_history.json");
loadHistoryFromFile();
}
void EnergyCountPeakFitView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
void EnergyCountPeakFitView::SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set)
{
if ( !data_files_set.isEmpty() ) {
if (!data_files_set.isEmpty()) {
const QString& data_name = data_files_set.firstKey();
const QString& data_filename = data_files_set.first().toString();
if (QFileInfo(data_filename).exists()) {
@ -203,9 +210,6 @@ void EnergyCountPeakFitView::setupPlot()
// 启用鼠标追踪,并安装事件过滤器
_plot->canvas()->setMouseTracking(true);
_plot->canvas()->installEventFilter(this);
}
void EnergyCountPeakFitView::setupMenu()
@ -238,11 +242,12 @@ void EnergyCountPeakFitView::setupMenu()
//删除当前悬停的框选区域
QAction* action_delete_hovered_rect = this->_menu->addAction(QStringLiteral(u"删除当前框选区域"));
connect(action_delete_hovered_rect, &QAction::triggered, this, &EnergyCountPeakFitView::onActionDeleteHoveredRect);
QAction* action_hint = this->_menu->addAction(QStringLiteral(u"框选提示:按住 Ctrl 键并拖动左键"));
action_hint->setEnabled(false);
}
void EnergyCountPeakFitView::loadDataFromFile(const QString &data_name, const QString &filename)
void EnergyCountPeakFitView::loadDataFromFile(const QString& data_name, const QString& filename)
{
//加载新数据前清空旧数据
_currentFitRecords.clear();
@ -274,6 +279,7 @@ void EnergyCountPeakFitView::loadDataFromFile(const QString &data_name, const QS
curve->setSamples(x, y);
_plot->AddCurve(curve,false);
}
void EnergyCountPeakFitView::onActionCurveShowSetting()
@ -298,7 +304,7 @@ void EnergyCountPeakFitView::onActionCurveShowSetting()
QVBoxLayout* checkbox_layout = new QVBoxLayout();
QHBoxLayout* checkbox_column_layout = new QHBoxLayout();
QMap<QwtPlotCurve*, QCheckBox*> curve_checkbox_map;
auto addCurveToLayout = [&](const QString& curve_name){
auto addCurveToLayout = [&](const QString& curve_name) {
QwtPlotCurve* curve = this->_plot->GetCurve(curve_name);
QCheckBox* check_box = new QCheckBox(curve->title().text());
check_box->setChecked(curve->isVisible());
@ -354,21 +360,18 @@ void EnergyCountPeakFitView::onActionCurveShowSetting()
void EnergyCountPeakFitView::onActionPlotConfigure()
{
}
void EnergyCountPeakFitView::clearAllSelectionRects()
{
for (PlotRectItem* item : _selectionRectItems) {
if (item) {
item->detach();
delete item;
}
}
_selectionRectItems.clear();
_plot->replot();
if (item) {
item->detach();
delete item;
}
}
_selectionRectItems.clear();
_plot->replot();
}
bool EnergyCountPeakFitView::eventFilter(QObject* watched, QEvent* event)
@ -421,18 +424,20 @@ void EnergyCountPeakFitView::startSelection(const QPoint& pos)
void EnergyCountPeakFitView::updateSelection(const QPoint& pos)
{
if (!_rubberBand) return;
int canvasHeight = _plot->canvas()->height();
int x1 = _selectionStart.x();
int x2 = pos.x();
int left = qMin(x1, x2);
int width = qAbs(x1 - x2);
_rubberBand->setGeometry(QRect(left, 0, width, canvasHeight));
if (!_rubberBand)
return;
int canvasHeight = _plot->canvas()->height();
int x1 = _selectionStart.x();
int x2 = pos.x();
int left = qMin(x1, x2);
int width = qAbs(x1 - x2);
_rubberBand->setGeometry(QRect(left, 0, width, canvasHeight));
}
void EnergyCountPeakFitView::finishSelection()
{
if (_rubberBand)
{
QRect finalRect = _rubberBand->geometry();
_rubberBand->hide();
@ -440,13 +445,17 @@ void EnergyCountPeakFitView::finishSelection()
const QwtScaleMap xMap = _plot->canvasMap(QwtPlot::xBottom);
double xMin = xMap.invTransform(finalRect.left());
double xMax = xMap.invTransform(finalRect.right());
if (xMin > xMax) std::swap(xMin, xMax);
double yMin = _plot->axisScaleDiv(QwtPlot::yLeft).lowerBound();
double yMax = _plot->axisScaleDiv(QwtPlot::yLeft).upperBound();
QRectF plotRect(xMin, yMin, xMax - xMin, yMax - yMin);
// addSelectionRect(plotRect);
// 获取曲线数据
QList<QwtPlotCurve*> curves = _plot->GetCurveList();
if (!curves.isEmpty()) {
@ -482,6 +491,7 @@ void EnergyCountPeakFitView::finishSelection()
for (int i = 0; i < roiX.size(); ++i) {
armaRoiX(i) = roiX[i];
armaRoiY(i) = roiY[i];
}
// 3. 执行拟合(曲线自动添加到主图)
QList<PeakFitResult> results = performPeakFitting(roiX, roiY/*, &userP0*/);
@ -510,29 +520,28 @@ void EnergyCountPeakFitView::finishSelection()
_isSelecting = false;
}
void EnergyCountPeakFitView::addSelectionRect(const QRectF &plotRect)
void EnergyCountPeakFitView::addSelectionRect(const QRectF& plotRect)
{
PlotRectItem* rectItem = new PlotRectItem("Selection");
rectItem->setAxes(QwtPlot::xBottom, QwtPlot::yLeft);
rectItem->setRect(plotRect);
// 设置填充为透明(无填充)
rectItem->setBrush(QBrush(Qt::transparent)); // 或 Qt::NoBrush
// 设置边框颜色为红色线宽2
rectItem->setPen(QPen(Qt::red, 2));
rectItem->setSelectionType("current");
rectItem->setSelectionIndex(_selectionRectItems.size());
rectItem->attach(_plot);
_selectionRectItems.append(rectItem);
_plot->replot();
rectItem->setAxes(QwtPlot::xBottom, QwtPlot::yLeft);
rectItem->setRect(plotRect);
// 设置填充为透明(无填充)
rectItem->setBrush(QBrush(Qt::transparent)); // 或 Qt::NoBrush
// 设置边框颜色为红色线宽2
rectItem->setPen(QPen(Qt::red, 2));
rectItem->setSelectionType("current");
rectItem->setSelectionIndex(_selectionRectItems.size());
rectItem->attach(_plot);
_selectionRectItems.append(rectItem);
_plot->replot();
}
void EnergyCountPeakFitView::fadeSelectionRectBorders()
{
for (PlotRectItem* item : _selectionRectItems) {
if (item) {
QPen fadedPen(Qt::red, 1, Qt::DashLine); // 可根据原样式调整
QPen fadedPen(Qt::red, 1, Qt::DashLine); // 可根据原样式调整
item->setPen(fadedPen);
}
}
@ -618,7 +627,7 @@ QList<PeakFitResult> EnergyCountPeakFitView::performPeakFitting(const QVector<do
return results;
}
QwtPlotCurve *EnergyCountPeakFitView::createFitCurve(const PeakFitResult &result, double xMin, double xMax, const QString &name)
QwtPlotCurve* EnergyCountPeakFitView::createFitCurve(const PeakFitResult& result, double xMin, double xMax, const QString& name)
{
const int numPoints = 200;
QVector<double> xs, ys,ysTw;
@ -1129,7 +1138,7 @@ void EnergyCountPeakFitView::onActionDeleteHoveredRect()
return;
}
// 【修改】使用新接口获取类型和索引
//使用新接口获取类型和索引
QString rectType = _hoveredRectItem->selectionType();
int rectIndex = _hoveredRectItem->selectionIndex();

View File

@ -10,7 +10,7 @@
// 转换Qt字符串路径为系统编码的C字符串解决中文路径问题
static const char* QStrToSysPath(const QString& qstr_path)
{
static std::string sys_path; // 静态变量避免内存释放
std::string sys_path; // 静态变量避免内存释放
#ifdef Q_OS_WIN
// Windows转为GBK编码
QTextCodec* gbkCodec = QTextCodec::codecForName("GBK");

View File

@ -21,13 +21,13 @@
#include "EnergyScaleForm.h"
#include "MeasureAnalysisHistoryForm.h"
#include "MeasureAnalysisProjectModel.h"
#include "MeasureDeviceParamsCfgForm.h"
#include "NewMeasureAnalysisDlg.h"
#include "MeasureAnalysisView.h"
#include "MeasureAnalysisTreeView.h"
#include "GlobalDefine.h"
#include "DeviceParameterConfig.h"
#include "DeviceParamsManagerDlg.h"
#include "NuclideLib.h"
using namespace ads;
MainWindow* MainWindow::_s_main_win = nullptr;
@ -220,18 +220,11 @@ void MainWindow::initAction()
}
}
});
connect(ui->action_manage_measurement_analysis, &QAction::triggered, this->_action_central_dock_widget, &QAction::triggered);
connect(ui->action_manage_measurement_analysis, &QAction::triggered, [this](){
this->_action_central_dock_widget->triggered(true);
});
connect(ui->action_device_config_mrg, &QAction::triggered, []() {
QDialog device_cfg_mrg_dlg;
device_cfg_mrg_dlg.setObjectName("MeasureDeviceParamsCfgFormDlg");
device_cfg_mrg_dlg.setWindowTitle(QStringLiteral(u"测量设备参数配置管理"));
device_cfg_mrg_dlg.setWindowFlags(device_cfg_mrg_dlg.windowFlags() | Qt::WindowMaximizeButtonHint);
// MeasureDeviceParamsCfgForm* measure_dev_params_cfg_form = new MeasureDeviceParamsCfgForm(&device_cfg_mrg_dlg);
DeviceParameterConfig * measure_dev_params_cfg_form = new DeviceParameterConfig(&device_cfg_mrg_dlg);
QHBoxLayout* hlayout = new QHBoxLayout;
hlayout->addWidget(measure_dev_params_cfg_form);
device_cfg_mrg_dlg.setLayout(hlayout);
device_cfg_mrg_dlg.exec();
DeviceParamsManagerDlg().exec();
});
connect(ui->action_energy_scale_mrg, &QAction::triggered, []() {
QDialog energy_scale_mrg_dlg;

View File

@ -46,7 +46,7 @@ void MeasureAnalysisHistoryForm::loadHistoryInfo(const QString &history_name)
if (!projects_dir.exists()) {
return;
}
QList<QString> project_dirs = projects_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Time);
QList<QString> project_dirs = projects_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks, QDir::Time);
for (const QString& project_dir : project_dirs) {
QDir project_dir_path(projects_dir.filePath(project_dir));
if (project_dir_path.exists()) {
@ -147,7 +147,7 @@ void MeasureAnalysisHistoryForm::onRemoveSelectedProject()
}
}
if (selected_project_list.isEmpty()) {
QMessageBox::information(this, QStringLiteral(u"确认"), QStringLiteral(u"请选择想要删除的测量分析项目!"));
QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"请选择想要删除的测量分析项目!"));
return;
}
if (QMessageBox::No == QMessageBox::question(this, QStringLiteral(u"确认"), QStringLiteral(u"是否删除选择的测量分析项目?"))) {

View File

@ -113,6 +113,16 @@ void MeasureAnalysisProjectModel::SetTimeWinConformEnergyData(uint time_win, uin
this->_time_win_conform_energy_data[time_win][conform_particle_count] = filename;
}
void MeasureAnalysisProjectModel::SetAntiConformParticleData(uint time_win, const QString &filename)
{
this->_anti_conform_particle_data[time_win] = filename;
}
void MeasureAnalysisProjectModel::SetAntiConformEnergyData(uint time_win, const QString &filename)
{
this->_anti_conform_energy_data[time_win] = filename;
}
void MeasureAnalysisProjectModel::SetAnalysisCustomData(AnalysisType analysis_type, const QString &data_item_name, const QString &data_filename)
{
this->_analysis_custom_data_set[analysis_type][data_item_name] = data_filename;
@ -259,6 +269,26 @@ const QMap<uint, QString> MeasureAnalysisProjectModel::GetTimeWinConformEnergyDa
return conform_energy_data;
}
const QMap<uint, QString> &MeasureAnalysisProjectModel::GetAntiConformParticleData()
{
return _anti_conform_particle_data;
}
const QString &MeasureAnalysisProjectModel::GetAntiConformParticleData(uint time_win)
{
return _anti_conform_particle_data.value(time_win);
}
const QMap<uint, QString> &MeasureAnalysisProjectModel::GetAntiConformEnergyData()
{
return _anti_conform_energy_data;
}
const QString &MeasureAnalysisProjectModel::GetAntiConformEnergyData(uint time_win)
{
return _anti_conform_energy_data.value(time_win);
}
const QString MeasureAnalysisProjectModel::GetAnalysisCustomData(AnalysisType analysis_type, const QString &data_item_name)
{
return this->_analysis_custom_data_set.value(analysis_type).value(data_item_name);
@ -403,6 +433,16 @@ bool MeasureAnalysisProjectModel::LoadProjectModel(const QString& project_filena
this->_time_win_conform_energy_data[time_win] = conform_energy_data;
}
const auto& anti_conform_particle_data = model_data["AntiConformParticleData"].toMap();
for (auto it = anti_conform_particle_data.constBegin(); it!=anti_conform_particle_data.constEnd(); ++it) {
this->_anti_conform_particle_data[it.key().toUInt()] = ProjectAbsFilename(it.value().toString());
}
const auto& anti_conform_energy_data = model_data["AntiConformEnergyData"].toMap();
for (auto it = anti_conform_energy_data.constBegin(); it!=anti_conform_energy_data.constEnd(); ++it) {
this->_anti_conform_energy_data[it.key().toUInt()] = ProjectAbsFilename(it.value().toString());
}
return true;
}
@ -473,6 +513,18 @@ bool MeasureAnalysisProjectModel::SaveProjectModel()
}
project_json_obj_map["TimeWinConformEnergyData"] = time_win_conform_energy_data;
QVariantMap anti_conform_particle_data;
for (auto it = this->_anti_conform_particle_data.constBegin(); it != this->_anti_conform_particle_data.constEnd(); ++it) {
anti_conform_particle_data[QString::number(it.key())] = ProjectRelativeFilename(it.value());
}
project_json_obj_map["AntiConformParticleData"] = anti_conform_particle_data;
QVariantMap anti_conform_energy_data;
for (auto it = this->_anti_conform_energy_data.constBegin(); it != this->_anti_conform_energy_data.constEnd(); ++it) {
anti_conform_energy_data[QString::number(it.key())] = ProjectRelativeFilename(it.value());
}
project_json_obj_map["AntiConformEnergyData"] = anti_conform_energy_data;
// 将项目模型保存到json文件
QJsonDocument json_doc = QJsonDocument::fromVariant(project_json_obj_map);
QFile json_file(this->_project_filename);
@ -548,6 +600,7 @@ bool MeasureAnalysisProjectModelList::RmProjectModel(const QString& project_name
return false;
}
}
emit removedProjectModel(project_name);
if (_project_models.contains(project_name)) {
delete _project_models[project_name];
_project_models.remove(project_name);
@ -557,7 +610,6 @@ bool MeasureAnalysisProjectModelList::RmProjectModel(const QString& project_name
const QString& project_name = project_model->GetProjectName();
SetCurrentProjectModel(project_name);
}
emit removedProjectModel(project_name);
return true;
}
@ -743,6 +795,10 @@ void MeasureAnalysisProjectModelList::ApplyEnergyScale(const QString &project_na
auto coincidence_process_task = new DataProcessWorkPool::EnergyScaleCoincidenceDataTask;
coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleCoincidenceDataFinished", project_name);
coincidence_process_task->StartTask();
auto anti_coincidence_process_task = new DataProcessWorkPool::EnergyScaleaAntiCoincidenceDataTask;
anti_coincidence_process_task->SetFinishedNotifier(this, "onEnergyScaleAntiCoincidenceDataFinished", project_name);
anti_coincidence_process_task->StartTask();
}
}
}
@ -954,11 +1010,6 @@ void MeasureAnalysisProjectModelList::onEnergyScaleCoincidenceDataFinished(bool
auto energy_total_count_spec_item = node_map[item_name];
this->SetNodeStatus(energy_total_count_spec_item, status, status_ok);
}
item_name = QStringLiteral(u"反符合能谱[%1ns]").arg(conform_time_win);
if (node_map.contains(item_name)) {
auto energy_total_count_spec_item = node_map[item_name];
this->SetNodeStatus(energy_total_count_spec_item, status, status_ok);
}
item_name = QStringLiteral(u"二维符合能谱[%1ns]").arg(conform_time_win);
if (node_map.contains(item_name)) {
auto energy_total_count_spec_item = node_map[item_name];
@ -977,6 +1028,33 @@ void MeasureAnalysisProjectModelList::onEnergyScaleCoincidenceDataFinished(bool
}
}
void MeasureAnalysisProjectModelList::onEnergyScaleAntiCoincidenceDataFinished(bool ok, const QString &project_name, const QVariant &data)
{
Q_UNUSED(data);
if ( !ok )
return;
if (this->_project_models.contains(project_name)) {
auto pro_model = this->_project_models[project_name];
auto& node_map = this->_project_node_items[project_name];
const auto& anti_conform_energy_data = pro_model->GetAntiConformEnergyData();
for (const auto& time_win : anti_conform_energy_data.keys()) {
bool status_ok = false;
QString status = QStringLiteral(u"无效");
const QString& data_filename = anti_conform_energy_data.value(time_win);
if ( (!data_filename.isEmpty()) && QFile::exists(data_filename) ) {
status_ok = true;
status = QStringLiteral(u"有效");
}
QString item_name = QStringLiteral(u"反符合能谱[%1ns]").arg(time_win);
if (node_map.contains(item_name)) {
auto anti_conform_erergy_spec_item = node_map[item_name];
this->SetNodeStatus(anti_conform_erergy_spec_item, status, status_ok);
}
}
pro_model->SaveProjectModel();
}
}
void MeasureAnalysisProjectModelList::intiProjectNodeStruce(MeasureAnalysisProjectModel* pro_model)
{
if (!pro_model) {

View File

@ -39,6 +39,8 @@ public:
void SetParticleEnergyDataFilename(const QString& filename);
void SetTimeWinConformParticleData(uint time_win, uint conform_particle_count, const QString& filename);
void SetTimeWinConformEnergyData(uint time_win, uint conform_particle_count, const QString& filename);
void SetAntiConformParticleData(uint time_win, const QString& filename);
void SetAntiConformEnergyData(uint time_win, const QString& filename);
void SetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name, const QString& data_filename);
const QString& GetProjectDir() const;
@ -63,6 +65,10 @@ public:
const QMap<uint, QString> GetTimeWinConformParticleDataFilenameList(uint time_win) const;
const QMap<uint, QMap<uint, QString> > GetConformParticleEnergyDataFilenameList() const;
const QMap<uint, QString> GetTimeWinConformEnergyDataFilenameList(uint time_win) const;
const QMap<uint, QString>& GetAntiConformParticleData();
const QString& GetAntiConformParticleData(uint time_win);
const QMap<uint, QString>& GetAntiConformEnergyData();
const QString& GetAntiConformEnergyData(uint time_win);
const QString GetAnalysisCustomData(AnalysisType analysis_type, const QString& data_item_name);
void SetDeviceGuid(const QString& device_guid);
@ -96,6 +102,9 @@ private:
QString _particle_energy_data_filename;
QMap<uint, QMap<uint, QString> > _time_win_conform_particle_data;
QMap<uint, QMap<uint, QString> > _time_win_conform_energy_data;
QMap<uint, QString> _anti_conform_particle_data;
QMap<uint, QString> _anti_conform_energy_data;
QMap<AnalysisType, QMap<QString, QString> > _analysis_custom_data_set;
QString _device_guid;
@ -160,6 +169,7 @@ private slots:
void onEnergyCountProcessFinished(bool ok, const QString& project_name, const QVariant& data);
void onCoincidenceProcessFinished(bool ok, const QString& project_name, const QVariant& data);
void onEnergyScaleCoincidenceDataFinished(bool ok, const QString& project_name, const QVariant& data);
void onEnergyScaleAntiCoincidenceDataFinished(bool ok, const QString& project_name, const QVariant& data);
signals:
void removedProjectModel(const QString& project_name);

View File

@ -269,6 +269,13 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
}
}
} break;
case AnalysisType::AntiCoincidenceSpectrumView: {
MeasureAnalysisProjectModel* project_model = _model->GetProjectModel(project_name);
if (project_model) {
auto file_name = project_model->GetAntiConformEnergyData(project_model->GetConformTimeWin());
data_files_set[QStringLiteral(u"反符合粒子数据")] = file_name;
}
} break;
default:
break;
}

View File

@ -10,6 +10,7 @@
#include "ParticleTimeDifferenceView.h"
#include "TwoDSpectralCompliance.h"
#include "ConformToTheEnergySpectrum.h"
#include "AntiConformEnergySpectrumView.h"
#include <QMap>
MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
@ -101,8 +102,8 @@ MeasureAnalysisView* MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
new_view->setDeleteOnClose(false);
} break;
case AnalysisType::AntiCoincidenceSpectrumView: {
// new_view = new MeasureAnalysisDataTableView;
// new_view->setDeleteOnClose(false);
new_view = new AntiConformEnergySpectrumView;
new_view->setDeleteOnClose(false);
} break;
default:
break;

View File

@ -1,14 +0,0 @@
#include "MeasureDeviceParamsCfgForm.h"
#include "ui_MeasureDeviceParamsCfgForm.h"
MeasureDeviceParamsCfgForm::MeasureDeviceParamsCfgForm(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MeasureDeviceParamsCfgForm)
{
ui->setupUi(this);
}
MeasureDeviceParamsCfgForm::~MeasureDeviceParamsCfgForm()
{
delete ui;
}

View File

@ -1,22 +0,0 @@
#ifndef MEASUREDEVICEPARAMSCFGFORM_H
#define MEASUREDEVICEPARAMSCFGFORM_H
#include <QWidget>
namespace Ui {
class MeasureDeviceParamsCfgForm;
}
class MeasureDeviceParamsCfgForm : public QWidget
{
Q_OBJECT
public:
explicit MeasureDeviceParamsCfgForm(QWidget *parent = nullptr);
~MeasureDeviceParamsCfgForm();
private:
Ui::MeasureDeviceParamsCfgForm *ui;
};
#endif // MEASUREDEVICEPARAMSCFGFORM_H

View File

@ -1,317 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MeasureDeviceParamsCfgForm</class>
<widget class="QWidget" name="MeasureDeviceParamsCfgForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1453</width>
<height>806</height>
</rect>
</property>
<property name="windowTitle">
<string>测量设备参数配置</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>设备参数配置列表</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QListWidget" name="listw_device_cfg">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="btn_add_cfg_list_item">
<property name="text">
<string>添加</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_remove_cfg_list_item">
<property name="text">
<string>删除</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>配置命名:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_cfg_name"/>
</item>
<item>
<widget class="QPushButton" name="btn_save_to_project">
<property name="text">
<string>保存到测量分析</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_save_to_sys">
<property name="text">
<string>保存到设备参数配置管理</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>备注说明:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="plainTextEdit_description">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTableWidget" name="tablew_params_cfg">
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<row>
<property name="text">
<string>通道1</string>
</property>
</row>
<row>
<property name="text">
<string>通道2</string>
</property>
</row>
<row>
<property name="text">
<string>通道3</string>
</property>
</row>
<row>
<property name="text">
<string>通道4</string>
</property>
</row>
<row>
<property name="text">
<string>通道5</string>
</property>
</row>
<row>
<property name="text">
<string>通道6</string>
</property>
</row>
<row>
<property name="text">
<string>通道7</string>
</property>
</row>
<row>
<property name="text">
<string>通道8</string>
</property>
</row>
<row>
<property name="text">
<string>通道9</string>
</property>
</row>
<row>
<property name="text">
<string>通道10</string>
</property>
</row>
<row>
<property name="text">
<string>通道11</string>
</property>
</row>
<row>
<property name="text">
<string>通道12</string>
</property>
</row>
<row>
<property name="text">
<string>通道13</string>
</property>
</row>
<row>
<property name="text">
<string>通道14</string>
</property>
</row>
<row>
<property name="text">
<string>通道15</string>
</property>
</row>
<row>
<property name="text">
<string>通道16</string>
</property>
</row>
<row>
<property name="text">
<string>通道17</string>
</property>
</row>
<row>
<property name="text">
<string>通道18</string>
</property>
</row>
<row>
<property name="text">
<string>通道19</string>
</property>
</row>
<row>
<property name="text">
<string>通道20</string>
</property>
</row>
<row>
<property name="text">
<string>通道21</string>
</property>
</row>
<row>
<property name="text">
<string>通道22</string>
</property>
</row>
<column>
<property name="text">
<string>时间常数</string>
</property>
</column>
<column>
<property name="text">
<string>上升时间</string>
</property>
</column>
<column>
<property name="text">
<string>平顶时间</string>
</property>
</column>
<column>
<property name="text">
<string>触发阈值</string>
</property>
</column>
<column>
<property name="text">
<string>直流偏移</string>
</property>
</column>
<column>
<property name="text">
<string>恢复速度</string>
</property>
</column>
<column>
<property name="text">
<string>滤波参数</string>
</property>
</column>
<column>
<property name="text">
<string>输入信号正负</string>
</property>
</column>
<column>
<property name="text">
<string>LFR</string>
</property>
</column>
<column>
<property name="text">
<string>保护时间</string>
</property>
</column>
<column>
<property name="text">
<string>硬件增益</string>
</property>
</column>
<column>
<property name="text">
<string>软件增益</string>
</property>
</column>
<column>
<property name="text">
<string>谱线道数</string>
</property>
</column>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,143 @@
#include "DeviceParamsManagerDlg.h"
#include "ui_DeviceParamsManagerDlg.h"
#include <QDir>
#include "GlobalDefine.h"
#include "DeviceParamsSaveToSysDlg.h"
#include <QMessageBox>
DeviceParamsManagerDlg::DeviceParamsManagerDlg(QWidget *parent)
: QDialog(parent)
, ui(new Ui::DeviceParamsManagerDlg)
{
ui->setupUi(this);
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
this->setWindowFlags(this->windowFlags() | Qt::WindowMinMaxButtonsHint);
scanParamsCfgFiles();
connect(ui->listw_cfg_list, &QListWidget::currentItemChanged, this, &DeviceParamsManagerDlg::onCfgListCurrentItemChanged);
connect(ui->btn_new, &QPushButton::clicked, this, &DeviceParamsManagerDlg::onBtnNew);
connect(ui->btn_delete, &QPushButton::clicked, this, &DeviceParamsManagerDlg::onBtnDelete);
connect(ui->btn_save, &QPushButton::clicked, this, &DeviceParamsManagerDlg::onBtnSave);
}
DeviceParamsManagerDlg::~DeviceParamsManagerDlg()
{
delete ui;
}
void DeviceParamsManagerDlg::scanParamsCfgFiles()
{
ui->params_table_form->SetButtonEnable(false);
ui->listw_cfg_list->clear();
// 遍历可执行文件目录下Projects目录下的所有文件夹找出所有项目文件夹下的.msproject文件
const QString& device_params_dir_path = QDir(qApp->applicationDirPath()).filePath("configure/DeviceParams");
QDir device_params_dir(device_params_dir_path);
if (!device_params_dir.exists(device_params_dir_path)) {
LOG_WARN(QStringLiteral(u"系统测量参数配置管理目录不存在:%1").arg(device_params_dir_path));
return;
}
QList<QString> ms_cfg_basenames = device_params_dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks, QDir::Time);
for (const QString& ms_cfg_basename : ms_cfg_basenames) {
const QString& ms_cfg_filename = device_params_dir.filePath(ms_cfg_basename);
QFileInfo ms_cfg_file_info(ms_cfg_filename);
if ("mscfg" == ms_cfg_file_info.suffix()) {
QListWidgetItem* item = new QListWidgetItem(ms_cfg_file_info.baseName());
item->setData(Qt::UserRole, ms_cfg_filename);
ui->listw_cfg_list->addItem(item);
}
}
const QString cfg_name = ui->linedit_cfg_name->text();
if (!cfg_name.isEmpty()) {
QList<QListWidgetItem*> items = ui->listw_cfg_list->findItems(cfg_name, Qt::MatchExactly);
QListWidgetItem* current_item = items.first();
if (current_item) {
ui->listw_cfg_list->setCurrentItem(current_item);
}
}
}
void DeviceParamsManagerDlg::onBtnNew()
{
DeviceParamsSaveToSysDlg params_save_to_sys_dlg;
if (QDialog::Accepted == params_save_to_sys_dlg.exec()) {
const QString& device_params_dir_path = QDir(qApp->applicationDirPath()).filePath("configure/DeviceParams");
const QString cfg_name = params_save_to_sys_dlg.GetCfgName();
const QString cfg_description = params_save_to_sys_dlg.GetCfgDescription();
const QString params_cfg_filename = QDir(device_params_dir_path).filePath(cfg_name) + ".mscfg";
if (ui->params_table_form->SaveSelectedChannelConfig(params_cfg_filename, cfg_name, cfg_description)) {
QListWidgetItem* item = new QListWidgetItem(cfg_name);
item->setData(Qt::UserRole, params_cfg_filename);
ui->listw_cfg_list->addItem(item);
ui->listw_cfg_list->setCurrentItem(item);
}
}
}
void DeviceParamsManagerDlg::onBtnDelete()
{
QListWidgetItem *current = ui->listw_cfg_list->currentItem();
if (current) {
const QString& ms_cfg_filename = current->data(Qt::UserRole).toString();
if (!ms_cfg_filename.isEmpty()) {
if (QMessageBox::No == QMessageBox::question(this, QStringLiteral(u"确认"), QStringLiteral(u"是否删除选择的测量参数配置?"))) {
return;
}
QFile ms_cfg_file(ms_cfg_filename);
if (!ms_cfg_file.remove()) {
LOG_WARN(QStringLiteral(u"删除设备测量参数配置[%1]失败: %2").arg(current->text()).arg(ms_cfg_file.errorString()));
} else {
ui->listw_cfg_list->removeItemWidget(current);
ui->linedit_cfg_name->clear();
ui->pte_description->clear();
ui->params_table_form->ClearParamsTable();
}
}
}
}
void DeviceParamsManagerDlg::onBtnSave()
{
const QString& device_params_dir_path = QDir(qApp->applicationDirPath()).filePath("configure/DeviceParams");
const QString cfg_name = ui->linedit_cfg_name->text();
if (cfg_name.isEmpty()) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"测量参数配置名称不能为空!"));
return;
}
const QString cfg_description = ui->pte_description->toPlainText();
const QString cfg_filename = QDir(device_params_dir_path).filePath(cfg_name) + ".mscfg";
if (QFile::exists(cfg_filename)) {
QListWidgetItem *current = ui->listw_cfg_list->currentItem();
if (current) {
const QString& ms_cfg_filename = current->data(Qt::UserRole).toString();
if (!ms_cfg_filename.isEmpty()) {
QFile ms_cfg_file(ms_cfg_filename);
if (!ms_cfg_file.remove()) {
LOG_WARN(QStringLiteral(u"删除设备测量参数配置[%1]失败: %2").arg(current->text()).arg(ms_cfg_file.errorString()));
}
}
}
}
if (ui->params_table_form->SaveSelectedChannelConfig(cfg_filename, cfg_name, cfg_description)) {
QListWidgetItem* current = ui->listw_cfg_list->currentItem();
if (current) {
current->setText(cfg_name);
current->setData(Qt::UserRole, cfg_filename);
}
}
this->scanParamsCfgFiles();
}
void DeviceParamsManagerDlg::onCfgListCurrentItemChanged(QListWidgetItem *current)
{
if (current) {
const QString& ms_cfg_filename = current->data(Qt::UserRole).toString();
if (!ms_cfg_filename.isEmpty()) {
ui->params_table_form->SetConfigFilename(ms_cfg_filename);
ui->linedit_cfg_name->clear();
ui->pte_description->clear();
ui->linedit_cfg_name->setText(ui->params_table_form->GetConfigName());
ui->pte_description->setPlainText(ui->params_table_form->GetConfigDescription());
}
}
}

View File

@ -0,0 +1,33 @@
#ifndef DEVICEPARAMSMANAGERDLG_H
#define DEVICEPARAMSMANAGERDLG_H
#include <QDialog>
namespace Ui {
class DeviceParamsManagerDlg;
}
class QListWidgetItem;
class DeviceParamsManagerDlg : public QDialog
{
Q_OBJECT
public:
explicit DeviceParamsManagerDlg(QWidget *parent = nullptr);
~DeviceParamsManagerDlg();
private:
void scanParamsCfgFiles();
private slots:
void onBtnNew();
void onBtnDelete();
void onBtnSave();
void onCfgListCurrentItemChanged(QListWidgetItem *current);
private:
Ui::DeviceParamsManagerDlg *ui;
};
#endif // DEVICEPARAMSMANAGERDLG_H

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DeviceParamsManagerDlg</class>
<widget class="QDialog" name="DeviceParamsManagerDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1075</width>
<height>712</height>
</rect>
</property>
<property name="windowTitle">
<string>设备测量参数管理</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>设备测量参数配置列表</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listw_cfg_list">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btn_new">
<property name="text">
<string>新建配置</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_delete">
<property name="text">
<string>删除配置</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>测量参数配置名称:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="linedit_cfg_name"/>
</item>
<item>
<widget class="QPushButton" name="btn_save">
<property name="text">
<string>保存</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>测量参数配置说明:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="pte_description">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="DeviceParamsTableForm" name="params_table_form" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>DeviceParamsTableForm</class>
<extends>QWidget</extends>
<header>DeviceParamsTableForm.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,46 @@
#include "DeviceParamsSaveToSysDlg.h"
#include "ui_DeviceParamsSaveToSysDlg.h"
#include <QMessageBox>
#include <QDir>
DeviceParamsSaveToSysDlg::DeviceParamsSaveToSysDlg(QWidget *parent)
: QDialog(parent)
, ui(new Ui::DeviceParamsSaveToSysDlg)
{
ui->setupUi(this);
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
connect(ui->btn_cancel, &QPushButton::clicked, this, &DeviceParamsSaveToSysDlg::reject);
connect(ui->btn_ok, &QPushButton::clicked, this, &DeviceParamsSaveToSysDlg::onBtnOkClicked);
}
DeviceParamsSaveToSysDlg::~DeviceParamsSaveToSysDlg()
{
delete ui;
}
QString DeviceParamsSaveToSysDlg::GetCfgName()
{
return ui->linedit_name->text();
}
QString DeviceParamsSaveToSysDlg::GetCfgDescription()
{
return ui->pte_description->toPlainText();
}
void DeviceParamsSaveToSysDlg::onBtnOkClicked()
{
const QString& cfg_name = ui->linedit_name->text();
if (cfg_name.isEmpty()) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"测量参数配置名称不能为空!"));
return;
}
const QString& device_params_dir_path = QDir(qApp->applicationDirPath()).filePath("configure/DeviceParams");
const QString ms_cfg_name = cfg_name + QString(".mscfg");
if (QDir(device_params_dir_path).exists(ms_cfg_name)) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"测量参数配置名称\"%1\"已存在!").arg(cfg_name));
return;
}
this->accept();
}

View File

@ -0,0 +1,28 @@
#ifndef DEVICEPARAMSSAVETOSYSDLG_H
#define DEVICEPARAMSSAVETOSYSDLG_H
#include <QDialog>
namespace Ui {
class DeviceParamsSaveToSysDlg;
}
class DeviceParamsSaveToSysDlg : public QDialog
{
Q_OBJECT
public:
explicit DeviceParamsSaveToSysDlg(QWidget *parent = nullptr);
~DeviceParamsSaveToSysDlg();
QString GetCfgName();
QString GetCfgDescription();
private slots:
void onBtnOkClicked();
private:
Ui::DeviceParamsSaveToSysDlg *ui;
};
#endif // DEVICEPARAMSSAVETOSYSDLG_H

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DeviceParamsSaveToSysDlg</class>
<widget class="QDialog" name="DeviceParamsSaveToSysDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>512</width>
<height>229</height>
</rect>
</property>
<property name="windowTitle">
<string>测量设备参数信息</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>测量参数配置名称:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="linedit_name"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>测量参数配置说明:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="pte_description"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btn_ok">
<property name="text">
<string>保存到系统</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_cancel">
<property name="text">
<string>取消</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -9,6 +9,17 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QDoubleSpinBox>
#include <QDir>
#include "DeviceParamsSaveToSysDlg.h"
static QStringList s_addr_count_list { "256", "512", "1024", "2048", "4096", "8192", "16384" };
static QMap<int, QString> s_transfer_mode_list {
{ 1, QStringLiteral(u"波形模式") },
{ 2, QStringLiteral(u"ADC模式") },
{ 3, QStringLiteral(u"粒子模式") }
};
static QStringList s_device_gain_list { "1", "2", "4", "8", "16" };
DeviceParamsItemDelegate::DeviceParamsItemDelegate(QObject* parent)
: QStyledItemDelegate(parent)
@ -21,52 +32,66 @@ QWidget* DeviceParamsItemDelegate::createEditor(QWidget* parent, const QStyleOpt
int col = index.column();
switch (col) {
case 1: { // 多道分辨率
QStringList value_list { "256", "512", "1024", "2048", "4096", "8192", "16384" };
QComboBox *combobox = new QComboBox(parent);
for (int index = 0; index < value_list.size(); ++index) {
QString value = value_list.at(index);
for (int index = 0; index < s_addr_count_list.size(); ++index) {
QString value = s_addr_count_list.at(index);
combobox->addItem(value);
}
editor = combobox;
} break;
case 2: { // 硬件增益
QStringList value_list { "1", "2", "4", "8", "16" };
case 2: { // 数据模式
QComboBox *combobox = new QComboBox(parent);
for (int index = 0; index < value_list.size(); ++index) {
QString value = value_list.at(index);
QList<int> transfer_mode_list = s_transfer_mode_list.keys();
qSort(transfer_mode_list.rbegin(), transfer_mode_list.rend());
foreach (int transfer_mode, transfer_mode_list) {
combobox->addItem(s_transfer_mode_list.value(transfer_mode), transfer_mode);
}
editor = combobox;
} break;
case 3: { // 硬件增益
QComboBox *combobox = new QComboBox(parent);
for (int index = 0; index < s_device_gain_list.size(); ++index) {
QString value = s_device_gain_list.at(index);
combobox->addItem(value, index + 1);
}
editor = combobox;
} break;
case 3: { // 软件增益
case 4: { // 软件增益
QSpinBox* spinbox = new QSpinBox(parent);
spinbox->setRange(1, 2^32-1);
editor = spinbox;
} break;
case 4: { // 时间常数
QSpinBox* spinbox = new QSpinBox(parent);
case 5: { // 时间常数
QDoubleSpinBox* spinbox = new QDoubleSpinBox(parent);
spinbox->setRange(1, 100);
editor = spinbox;
} break;
case 5: { // 直流偏移
case 6: { // 直流偏移
QSpinBox* spinbox = new QSpinBox(parent);
spinbox->setRange(-1000, 1000);
editor = spinbox;
} break;
case 6: { // 上升时间
case 7: { // 成形时间
QSpinBox* spinbox = new QSpinBox(parent);
spinbox->setRange(1, 255);
spinbox->setRange(1, 10);
editor = spinbox;
} break;
case 7: { // 平顶时间
QSpinBox* spinbox = new QSpinBox(parent);
spinbox->setRange(1, 255);
case 8: { // 快通道触发阈值
QDoubleSpinBox* spinbox = new QDoubleSpinBox(parent);
spinbox->setRange(0, 1000);
editor = spinbox;
} break;
case 8: { // 最大能量范围
QSpinBox* spinbox = new QSpinBox(parent);
spinbox->setRange(0, 99999);
editor = spinbox;
case 9: { // CR微分模式
QComboBox *combobox = new QComboBox(parent);
combobox->addItem(QStringLiteral(u"启用"), true);
combobox->addItem(QStringLiteral(u"禁用"), false);
editor = combobox;
} break;
case 10: { // 输入信号正负极性选择
QComboBox *combobox = new QComboBox(parent);
combobox->addItem(QStringLiteral(u"启用"), true);
combobox->addItem(QStringLiteral(u"禁用"), false);
editor = combobox;
} break;
default:
break;
@ -80,24 +105,47 @@ void DeviceParamsItemDelegate::setEditorData(QWidget* editor, const QModelIndex&
int col = index.column();
switch (col) {
case 1:
case 2: {
case 2:
case 3: {
QComboBox *combo = qobject_cast<QComboBox*>(editor);
if (combo) {
int idx = combo->findText(value.toString());
if (idx >= 0) combo->setCurrentIndex(idx);
}
} break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8: {
case 4: {
QSpinBox *spinbox = qobject_cast<QSpinBox*>(editor);
if (spinbox) {
spinbox->setValue(value.toUInt());
}
} break;
case 5: {
QDoubleSpinBox *spinbox = qobject_cast<QDoubleSpinBox*>(editor);
if (spinbox) {
spinbox->setValue(value.toDouble());
}
} break;
case 6:
case 7: {
QSpinBox *spinbox = qobject_cast<QSpinBox*>(editor);
if (spinbox) {
spinbox->setValue(value.toUInt());
}
} break;
case 8: {
QDoubleSpinBox *spinbox = qobject_cast<QDoubleSpinBox*>(editor);
if (spinbox) {
spinbox->setValue(value.toDouble());
}
} break;
case 9:
case 10: {
QComboBox *combo = qobject_cast<QComboBox*>(editor);
if (combo) {
int idx = combo->findText(value.toString());
if (idx >= 0) combo->setCurrentIndex(idx);
}
} break;
default:
break;
}
@ -108,23 +156,45 @@ void DeviceParamsItemDelegate::setModelData(QWidget* editor, QAbstractItemModel*
int col = index.column();
switch (col) {
case 1:
case 2: {
case 2:
case 3: {
QComboBox *combobox = qobject_cast<QComboBox*>(editor);
if (combobox) {
model->setData(index, combobox->currentText());
}
} break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8: {
case 4: {
QSpinBox *spinbox = qobject_cast<QSpinBox*>(editor);
if (spinbox) {
model->setData(index, spinbox->value());
}
} break;
case 5: {
QDoubleSpinBox *spinbox = qobject_cast<QDoubleSpinBox*>(editor);
if (spinbox) {
model->setData(index, spinbox->value());
}
} break;
case 6:
case 7: {
QSpinBox *spinbox = qobject_cast<QSpinBox*>(editor);
if (spinbox) {
model->setData(index, spinbox->value());
}
} break;
case 8: {
QDoubleSpinBox *spinbox = qobject_cast<QDoubleSpinBox*>(editor);
if (spinbox) {
model->setData(index, spinbox->value());
}
} break;
case 9:
case 10: {
QComboBox *combobox = qobject_cast<QComboBox*>(editor);
if (combobox) {
model->setData(index, combobox->currentText());
}
} break;
default:
break;
}
@ -171,6 +241,7 @@ DeviceParamsTableForm::DeviceParamsTableForm(QWidget* parent)
ui->params_cfg_table->setItem(row, 7, new QTableWidgetItem());
ui->params_cfg_table->setItem(row, 8, new QTableWidgetItem());
ui->params_cfg_table->setItem(row, 9, new QTableWidgetItem());
ui->params_cfg_table->setItem(row, 10, new QTableWidgetItem());
}
connect(ui->btn_all_select, &QPushButton::clicked, this, &DeviceParamsTableForm::onAllSelectBtnClicked);
@ -178,6 +249,7 @@ DeviceParamsTableForm::DeviceParamsTableForm(QWidget* parent)
connect(ui->btn_channel_select, &QPushButton::clicked, this, &DeviceParamsTableForm::onCfgChannelSelectBtnClicked);
connect(ui->btn_update_to_other, &QPushButton::clicked, this, &DeviceParamsTableForm::onCurrentChannelToOther);
connect(ui->btn_save, &QPushButton::clicked, this, &DeviceParamsTableForm::onSaveSelectedChannelConfig);
connect(ui->btn_save_to_sys, &QPushButton::clicked, this, &DeviceParamsTableForm::onSaveSelectedChannelConfigToSys);
}
DeviceParamsTableForm::~DeviceParamsTableForm()
@ -204,6 +276,18 @@ void DeviceParamsTableForm::SetConfigFilename(const QString& filename)
if (!json_doc.isObject())
return;
QVariantMap device_config_info = json_doc.object().toVariantMap();
if (device_config_info.contains(QStringLiteral(u"ParamsConfigureInfo"))) {
QVariantMap config_info = device_config_info[QStringLiteral(u"ParamsConfigureInfo")].toMap();
if (config_info.contains(QStringLiteral(u"Name"))) {
this->_cfg_name = config_info[QStringLiteral(u"Name")].toString();
}
if (config_info.contains(QStringLiteral(u"Description"))) {
this->_cfg_description = config_info[QStringLiteral(u"Description")].toString();
}
}
this->ClearParamsTable();
if (!device_config_info.contains(QStringLiteral(u"ChannelConfig")))
return;
QVariantList channel_config_list = device_config_info[QStringLiteral(u"ChannelConfig")].toList();
@ -220,31 +304,57 @@ void DeviceParamsTableForm::SetConfigFilename(const QString& filename)
int row = board_id * 4 + channel_id;
if (row >= 32)
continue;
QVariantMap channel_info;
channel_info["board_id"] = board_id;
channel_info["channel_id"] = channel_id;
ui->params_cfg_table->item(row, 0)->setData(Qt::UserRole, channel_info);
// QVariantMap channel_info;
// channel_info["board_id"] = board_id;
// channel_info["channel_id"] = channel_id;
// ui->params_cfg_table->item(row, 0)->setData(Qt::UserRole, channel_info);
if (channel_config_info.contains("AddrCount"))
ui->params_cfg_table->item(row, 1)->setText(channel_config_info["AddrCount"].toString());
if (channel_config_info.contains("TransferMode")) {
int transfer_mode = channel_config_info["TransferMode"].toInt();
ui->params_cfg_table->item(row, 2)->setText(s_transfer_mode_list.value(transfer_mode));
}
if (channel_config_info.contains("DeviceGain"))
ui->params_cfg_table->item(row, 2)->setText(channel_config_info["DeviceGain"].toString());
if (channel_config_info.contains("DeviceGainSelectIndex"))
ui->params_cfg_table->item(row, 2)->setData(Qt::UserRole, channel_config_info["DeviceGainSelectIndex"]);
ui->params_cfg_table->item(row, 3)->setText(channel_config_info["DeviceGain"].toString());
// if (channel_config_info.contains("DeviceGainSelectIndex"))
// ui->params_cfg_table->item(row, 3)->setData(Qt::UserRole, channel_config_info["DeviceGainSelectIndex"]);
if (channel_config_info.contains("SoftGain"))
ui->params_cfg_table->item(row, 3)->setText(channel_config_info["SoftGain"].toString());
ui->params_cfg_table->item(row, 4)->setText(channel_config_info["SoftGain"].toString());
if (channel_config_info.contains("TimeConst"))
ui->params_cfg_table->item(row, 4)->setText(channel_config_info["TimeConst"].toString());
ui->params_cfg_table->item(row, 5)->setText(channel_config_info["TimeConst"].toString());
if (channel_config_info.contains("DcOffset"))
ui->params_cfg_table->item(row, 5)->setText(channel_config_info["DcOffset"].toString());
if (channel_config_info.contains("RiseTime"))
ui->params_cfg_table->item(row, 6)->setText(channel_config_info["RiseTime"].toString());
if (channel_config_info.contains("FlatTime"))
ui->params_cfg_table->item(row, 7)->setText(channel_config_info["FlatTime"].toString());
if (channel_config_info.contains("MaxEnergy"))
ui->params_cfg_table->item(row, 8)->setText(channel_config_info["MaxEnergy"].toString());
ui->params_cfg_table->item(row, 6)->setText(channel_config_info["DcOffset"].toString());
if (channel_config_info.contains("FormTime"))
ui->params_cfg_table->item(row, 7)->setText(channel_config_info["FormTime"].toString());
if (channel_config_info.contains("FastChannelTrigerValue"))
ui->params_cfg_table->item(row, 8)->setText(channel_config_info["FastChannelTrigerValue"].toString());
if (channel_config_info.contains("CRDivMode")) {
bool CRDiv_mode = channel_config_info["CRDivMode"].toBool();
ui->params_cfg_table->item(row, 9)->setText(CRDiv_mode ? QStringLiteral(u"启用") : QStringLiteral(u"禁用"));
}
if (channel_config_info.contains("InputSignalPostive")) {
bool input_signal_postive = channel_config_info["InputSignalPostive"].toBool();
ui->params_cfg_table->item(row, 10)->setText(input_signal_postive ? QStringLiteral(u"启用") : QStringLiteral(u"禁用"));
}
}
}
void DeviceParamsTableForm::SetButtonEnable(bool enable)
{
ui->btn_save->setVisible(enable);
ui->btn_save_to_sys->setVisible(enable);
}
const QString &DeviceParamsTableForm::GetConfigName() const
{
return _cfg_name;
}
const QString &DeviceParamsTableForm::GetConfigDescription() const
{
return _cfg_description;
}
void DeviceParamsTableForm::onAllSelectBtnClicked()
{
for (int row = 0; row < 32; ++row) {
@ -322,14 +432,57 @@ void DeviceParamsTableForm::onCurrentChannelToOther()
for (int row = 0; row < 32; ++row) {
if (ui->params_cfg_table->isRowHidden(row))
continue;
for (int col = 1; col < ui->params_cfg_table->columnCount(); ++col) {
const QString& current_value = ui->params_cfg_table->item(current_row, col)->text();
ui->params_cfg_table->item(row, col)->setText(current_value);
if (ui->params_cfg_table->item(row, 0)->checkState() == Qt::Checked) {
for (int col = 1; col < ui->params_cfg_table->columnCount(); ++col) {
QTableWidgetItem* current_item = ui->params_cfg_table->item(current_row, col);
if (current_item) {
const QString& current_value = current_item->text();
ui->params_cfg_table->item(row, col)->setText(current_value);
}
}
}
}
}
void DeviceParamsTableForm::onSaveSelectedChannelConfig()
{
if (SaveSelectedChannelConfig(this->_config_filename, this->_cfg_name, this->_cfg_description)) {
emit deviceConfigParamsSaved(this->_config_filename);
}
}
void DeviceParamsTableForm::onSaveSelectedChannelConfigToSys()
{
int selected_channel_count = 0;
for (int row = 0; row < 32; ++row) {
if (ui->params_cfg_table->item(row, 0)->checkState() == Qt::Checked) {
++selected_channel_count;
}
}
if (0 == selected_channel_count) {
QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"请选择需要保存的测量设备通道配置参数!"));
return;
}
DeviceParamsSaveToSysDlg params_save_to_sys_dlg;
if (QDialog::Accepted == params_save_to_sys_dlg.exec()) {
const QString& device_params_dir_path = QDir(qApp->applicationDirPath()).filePath("configure/DeviceParams");
const QString params_cfg_name = params_save_to_sys_dlg.GetCfgName();
const QString params_cfg_description = params_save_to_sys_dlg.GetCfgDescription();
const QString params_cfg_filename = QDir(device_params_dir_path).filePath(params_cfg_name) + ".mscfg";
if (QFile::exists(params_cfg_filename)) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"设备测量参数配置\"%1\"已存在!").arg(params_cfg_name));
} else {
if (this->SaveSelectedChannelConfig(params_cfg_filename, params_cfg_name, params_cfg_description)) {
this->_cfg_name = params_cfg_name;
this->_cfg_description = params_cfg_description;
QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"保存设备测量参数配置\"%1\"完成").arg(params_cfg_name));
}
}
}
}
bool DeviceParamsTableForm::SaveSelectedChannelConfig(const QString &save_filename, const QString& cfg_name, const QString& description)
{
QVariantList device_channel_params_list;
for (int row = 0; row < 32; ++row) {
@ -338,44 +491,82 @@ void DeviceParamsTableForm::onSaveSelectedChannelConfig()
int board_id = channel_info["board_id"].toInt();
int channel_id = channel_info["channel_id"].toInt();
int addr_count = ui->params_cfg_table->item(row, 1)->text().toInt();
int device_gain = ui->params_cfg_table->item(row, 2)->text().toInt();
int device_gain_index = ui->params_cfg_table->item(row, 2)->data(Qt::UserRole).toInt();
uint soft_gain = ui->params_cfg_table->item(row, 3)->text().toUInt();
int time_const = ui->params_cfg_table->item(row, 4)->text().toInt();
int dc_offset = ui->params_cfg_table->item(row, 5)->text().toInt();
int rise_time = ui->params_cfg_table->item(row, 6)->text().toInt();
int flat_time = ui->params_cfg_table->item(row, 7)->text().toInt();
int max_energy = ui->params_cfg_table->item(row, 8)->text().toInt();
auto transfer_mode_value = [](const QString& transfer_mode_text) {
int transfer_mode = 3;
for (QMap<int, QString>::iterator it = s_transfer_mode_list.begin(); it != s_transfer_mode_list.end(); ++it) {
if (it.value() == transfer_mode_text) {
transfer_mode = it.key();
break;
}
}
return transfer_mode;
};
int transfer_mode = transfer_mode_value(ui->params_cfg_table->item(row, 2)->text());
int device_gain = ui->params_cfg_table->item(row, 3)->text().toInt();
int device_gain_index = s_device_gain_list.indexOf(ui->params_cfg_table->item(row, 3)->text()) + 1;
uint soft_gain = ui->params_cfg_table->item(row, 4)->text().toUInt();
double time_const = ui->params_cfg_table->item(row, 5)->text().toDouble();
int dc_offset = ui->params_cfg_table->item(row, 6)->text().toInt();
int form_time = ui->params_cfg_table->item(row, 7)->text().toInt();
double fast_channel_triger_value = ui->params_cfg_table->item(row, 8)->text().toDouble();
auto is_enable = [](const QString& text) {
bool enable = false;
if (QStringLiteral(u"启用") == text) {
enable = true;
} else if (QStringLiteral(u"禁用") == text) {
enable = false;
}
return enable;
};
bool CRDiv_mode = is_enable(ui->params_cfg_table->item(row, 9)->text());
bool input_signal_postive = is_enable(ui->params_cfg_table->item(row, 10)->text());
QVariantMap device_channel_params;
device_channel_params["BoardId"] = board_id;
device_channel_params["ChannelId"] = channel_id;
device_channel_params["AddrCount"] = addr_count;
device_channel_params["TransferMode"] = transfer_mode;
device_channel_params["DeviceGain"] = device_gain;
device_channel_params["DeviceGainSelectIndex"] = device_gain_index;
device_channel_params["SoftGain"] = soft_gain;
device_channel_params["TimeConst"] = time_const;
device_channel_params["DcOffset"] = dc_offset;
device_channel_params["RiseTime"] = rise_time;
device_channel_params["FlatTime"] = flat_time;
device_channel_params["MaxEnergy"] = max_energy;
device_channel_params["FormTime"] = form_time;
device_channel_params["FastChannelTrigerValue"] = fast_channel_triger_value;
device_channel_params["CRDivMode"] = CRDiv_mode;
device_channel_params["InputSignalPostive"] = input_signal_postive;
device_channel_params_list.append(device_channel_params);
}
}
if (device_channel_params_list.isEmpty()) {
QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"请选择需要保存的测量设备通道配置参数!"));
return;
}
// if (device_channel_params_list.isEmpty()) {
// QMessageBox::information(this, QStringLiteral(u"提示"), QStringLiteral(u"请选择需要保存的测量设备通道配置参数!"));
// return false;
// }
QVariantMap device_config_info;
if (!cfg_name.isEmpty()) {
QVariantMap cfg_info;
cfg_info["Name"] = cfg_name;
cfg_info["Description"] = description;
device_config_info["ParamsConfigureInfo"] = cfg_info;
}
device_config_info["ChannelConfig"] = device_channel_params_list;
QJsonDocument json_doc = QJsonDocument::fromVariant(device_config_info);
QFile json_file(this->_config_filename);
QFile json_file(save_filename);
if (!json_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
return false;
}
json_file.write(json_doc.toJson());
json_file.close();
LOG_INFO(QStringLiteral(u"测量设备参数配置保存完成."));
emit deviceConfigParamsSaved(this->_config_filename);
LOG_INFO(QStringLiteral(u"测量设备参数配置保存完成: %1.").arg(save_filename));
return true;
}
void DeviceParamsTableForm::ClearParamsTable()
{
for (int row = 0; row < ui->params_cfg_table->rowCount(); ++row) {
for (int col = 1; col < ui->params_cfg_table->columnCount(); ++col) {
ui->params_cfg_table->item(row, col)->setText(QString());
}
}
}

View File

@ -15,11 +15,8 @@ public:
explicit DeviceParamsItemDelegate(QObject *parent = nullptr);
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
protected:
@ -36,12 +33,20 @@ public:
void SetConfigFilename(const QString& filename);
void SetButtonEnable(bool enable = true);
const QString& GetConfigName() const;
const QString& GetConfigDescription() const;
void ClearParamsTable();
bool SaveSelectedChannelConfig(const QString& save_filename, const QString &cfg_name = QString(), const QString &description = QString());
private slots:
void onAllSelectBtnClicked();
void onReserveSelectBtnClicked();
void onCfgChannelSelectBtnClicked();
void onCurrentChannelToOther();
void onSaveSelectedChannelConfig();
void onSaveSelectedChannelConfigToSys();
signals:
void deviceConfigParamsSaved(const QString& filename);
@ -49,6 +54,8 @@ signals:
private:
Ui::DeviceParamsTableForm *ui;
QString _config_filename;
QString _cfg_name;
QString _cfg_description;
};
#endif // DEVICEPARAMSTABLEFORM_H

View File

@ -42,7 +42,7 @@
<item>
<widget class="QPushButton" name="btn_update_to_other">
<property name="text">
<string>应用当前通道配置到其他通道</string>
<string>应用当前通道配置到选择通道</string>
</property>
</widget>
</item>
@ -68,6 +68,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_save_to_sys">
<property name="text">
<string>保存到系统</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -88,6 +95,11 @@
<string>道址数</string>
</property>
</column>
<column>
<property name="text">
<string>数据模式</string>
</property>
</column>
<column>
<property name="text">
<string>硬件增益</string>
@ -110,17 +122,22 @@
</column>
<column>
<property name="text">
<string>上升时间</string>
<string>成形时间</string>
</property>
</column>
<column>
<property name="text">
<string>平顶时间</string>
<string>快通道触发阈值</string>
</property>
</column>
<column>
<property name="text">
<string>最大能量范围</string>
<string>CR微分模式</string>
</property>
</column>
<column>
<property name="text">
<string>输入信号正负极性选择</string>
</property>
</column>
</widget>

View File

@ -1,75 +0,0 @@
#ifndef COINCIDENCESPECTRUMPROCESS_H
#define COINCIDENCESPECTRUMPROCESS_H
#include <armadillo>
// 定义板卡和通道的最大数量
static constexpr int MAX_BOARD = 8;
static constexpr int MAX_CHANNEL = 4;
// 用于存储三维数据
typedef struct SurfacePoint {
float primaryEnergy; // 初级粒子能量
float secondaryEnergySum; // 次级粒子能量和
int count; // 符合事件计数
}SURFACEPOINT;
namespace CoincidenceSpectrum {
// 二次符合事件筛选
arma::mat EventFilter2Order(const arma::mat& raw_spec_data, double conformity_event_time_win = 50.0f);
// 计算二维直方图
void Hist3(const arma::mat& data, int nx, int ny, arma::mat& counts, arma::vec& x_edges, arma::vec& y_edges);
// 二次符合事件处理
namespace F2t9Order {
// 能谱数据结构
struct SpectrumData {
int board_id; // 板卡号
int channel_id; // 通道号
double energy; // 能量
unsigned long long timestamp; // 时间戳(纳秒)
};
// 符合事件结果结构
struct CoincidenceEvent {
int coincidence_order; // 符合次数2-9
std::vector<SpectrumData> events; // 符合的事件集合
unsigned int time_window; // 使用的时间窗口(秒)
};
// 读取CSV数据文件
std::vector<SpectrumData> ReadCsv(const std::string& filename);
// 按时间戳排序数据
void SortDataByTimestamp(std::vector<SpectrumData>& data);
// 2-9次能谱符合处理
std::vector<CoincidenceEvent> ProcessCoincidence(
const std::vector<SpectrumData>& data,
unsigned int time_window, // 时间窗口(纳秒)
int min_order = 2, // 最小符合次数
int max_order = 9 // 最大符合次数
);
// 统计符合事件结果
arma::mat AnalyzeCoincidenceResults(
const std::vector<CoincidenceEvent>& results,
int max_order = 9
);
// 保存结果到文件
void SaveResults(
const std::vector<CoincidenceEvent>& results,
const arma::mat& stats,
const std::string& base_filename = "coincidence_results"
);
};
}
#endif // COINCIDENCESPECTRUMPROCESS_H

View File

@ -7,6 +7,17 @@
#include "QsLogManage.h"
#include <QThreadPool>
void InitAppRunEnv() {
// 在应用程序可执行文件所在目录检查并创建Projects目录
QString projects_dir_path = QDir(qApp->applicationDirPath()).filePath("Projects");
QDir projects_dir(projects_dir_path);
projects_dir.mkpath(projects_dir_path);
QString device_params_dir_path = QDir(qApp->applicationDirPath()).filePath("configure/DeviceParams");
QDir device_params_dir(device_params_dir_path);
device_params_dir.mkpath(device_params_dir_path);
}
int main(int argc, char *argv[])
{
qputenv("QT_WIN_DEBUG_CONSOLE", "attach");
@ -53,12 +64,7 @@ int main(int argc, char *argv[])
app.setWindowIcon(QIcon(":/logo/256.png"));
app.setQuitOnLastWindowClosed(true);
// 在应用程序可执行文件所在目录检查并创建Projects目录
QString projects_dir_path = QDir(app.applicationDirPath()).filePath("Projects");
QDir projects_dir(projects_dir_path);
if (!projects_dir.exists()) {
projects_dir.mkpath(projects_dir_path);
}
InitAppRunEnv();
MainWindow w;
w.showMaximized();

View File

@ -8,7 +8,6 @@ msvc {
QMAKE_CXXFLAGS += /utf-8
}
include($${PWD}/../Common.pri)
include($${PROJECT_DIR}/3rdlib/QsLog/QsLog.pri)
include($${PROJECT_DIR}/3rdlib/QtAdvancedDockingSystem/ads.pri)
@ -38,8 +37,8 @@ INCLUDEPATH += \
$${PWD}/DeviceParameterConfig \
$${PWD}/2DSpectralCompliance \
$${PWD}/ConformToTheEnergySpectrum \
$${PWD}/NuclideLib
$${PWD}/NuclideLib \
$${PWD}/AntiConformEnergySpectrumView
DEPENDPATH += \
$${PWD}/BusyIndicator \
@ -57,11 +56,8 @@ DEPENDPATH += \
$${PWD}/DeviceParameterConfig \
$${PWD}/2DSpectralCompliance \
$${PWD}/ConformToTheEnergySpectrum \
$${PWD}/NuclideLib
$${PWD}/NuclideLib \
$${PWD}/AntiConformEnergySpectrumView
SOURCES += \
2DSpectralCompliance/TwoDSpectralCompliance.cpp \
@ -70,9 +66,6 @@ SOURCES += \
CountRateAnalysisView/CountRateAnalysisView.cpp \
CustomQwtPlot.cpp \
DataProcessWorkPool.cpp \
DeviceParameterConfig/DeviceConfigView.cpp \
DeviceParameterConfig/DeviceParameterConfig.cpp \
DeviceParameterConfig/DeviceParameterConfigList.cpp \
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
EnergyCountPeakFitView/PeakFitParamsDialog.cpp \
EnergyCountPeakFitView/PlotRectItem.cpp \
@ -82,6 +75,8 @@ SOURCES += \
MainWindow.cpp \
MeasureAnalysisDataTableView/MeasureAnalysisDataTableView.cpp \
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.cpp \
MeasureDeviceParamsConfigView/DeviceParamsManagerDlg.cpp \
MeasureDeviceParamsConfigView/DeviceParamsSaveToSysDlg.cpp \
MeasureDeviceParamsConfigView/DeviceParamsTableForm.cpp \
MeasureDeviceParamsConfigView/MeasureDeviceParamsConfigView.cpp \
NuclideLib/NuclideEditDialog.cpp \
@ -93,7 +88,6 @@ SOURCES += \
ParticleCountPlotView/ParticleCountPlotView.cpp \
MeasureAnalysisTreeView.cpp \
MeasureAnalysisView.cpp \
MeasureDeviceParamsCfgForm.cpp \
NewMeasureAnalysisDlg.cpp \
MeasureAnalysisProjectModel.cpp \
ParticleInjectTimeView/ParticleInjectTimeAnalysisView.cpp \
@ -107,9 +101,9 @@ SOURCES += \
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.cpp \
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.cpp \
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
DeviceParameterConfig/DeviceParameterProxy.cpp \
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \
NuclideLib/NuclideLib.cpp \
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp \
main.cpp
HEADERS += \
@ -120,9 +114,6 @@ HEADERS += \
CountRateAnalysisView/CountRateAnalysisView.h \
CustomQwtPlot.h \
DataProcessWorkPool.h \
DeviceParameterConfig/DeviceConfigView.h \
DeviceParameterConfig/DeviceParameterConfig.h \
DeviceParameterConfig/DeviceParameterConfigList.h \
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
EnergyCountPeakFitView/PeakFitParamsDialog.h \
EnergyCountPeakFitView/PlotRectItem.h \
@ -133,6 +124,8 @@ HEADERS += \
MainWindow.h \
MeasureAnalysisDataTableView/MeasureAnalysisDataTableView.h \
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.h \
MeasureDeviceParamsConfigView/DeviceParamsManagerDlg.h \
MeasureDeviceParamsConfigView/DeviceParamsSaveToSysDlg.h \
MeasureDeviceParamsConfigView/DeviceParamsTableForm.h \
MeasureDeviceParamsConfigView/MeasureDeviceParamsConfigView.h \
NuclideLib/NuclideEditDialog.h \
@ -144,7 +137,6 @@ HEADERS += \
ParticleCountPlotView/ParticleCountPlotView.h \
MeasureAnalysisTreeView.h \
MeasureAnalysisView.h \
MeasureDeviceParamsCfgForm.h \
NewMeasureAnalysisDlg.h \
MeasureAnalysisProjectModel.h \
ParticleInjectTimeView/ParticleInjectTimeAnalysisView.h \
@ -159,12 +151,9 @@ HEADERS += \
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.h \
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
DeviceParameterConfig/DeviceParameterProxy.h \
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \
NuclideLib/NuclideLib.h
NuclideLib/NuclideLib.h \
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h
FORMS += \
2DSpectralCompliance/TwoDSpectralCompliance.ui \
@ -173,9 +162,10 @@ FORMS += \
EnergyScaleForm.ui \
MainWindow.ui \
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.ui \
MeasureDeviceParamsConfigView/DeviceParamsManagerDlg.ui \
MeasureDeviceParamsConfigView/DeviceParamsSaveToSysDlg.ui \
MeasureDeviceParamsConfigView/DeviceParamsTableForm.ui \
ParticleCountPlotView/BatchEnergyScaleDialog.ui \
MeasureDeviceParamsCfgForm.ui \
NewMeasureAnalysisDlg.ui \
ThreeDimensionalConformityAnalysisView/DetectorStatusSummary.ui \
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.ui \
@ -183,7 +173,6 @@ FORMS += \
ThreeDimensionalConformityAnalysisView/ConformityAnalysis.ui \
NuclideLib/NuclideLib.ui
DEFINES += ENABLE_DEBUG
contains(DEFINES, ENABLE_DEBUG) {
CONFIG += console

View File

@ -48,7 +48,7 @@ QHeaderView::section {
font-weight: normal;
}
/*
QScrollBar {
background-color: #f6f5ec;
padding: 0px;
@ -90,5 +90,5 @@ QScrollBar::add-page {
QScrollBar::sub-page {
background: rgba(0, 0, 0, 0);
}
*/