对峰拟合分析进行修改,新增核素库新增核素信息,新增射线信息,修改核素信息,修改射线信息
This commit is contained in:
parent
a27195899a
commit
36f9f7ad32
Binary file not shown.
|
|
@ -22,6 +22,9 @@
|
|||
#include <QLineEdit>
|
||||
#include <QMouseEvent>
|
||||
#include <QSet>
|
||||
#include "BusyIndicator.h"
|
||||
#include <QThread>
|
||||
|
||||
class HeatMapColorMap : public QwtLinearColorMap
|
||||
{
|
||||
public:
|
||||
|
|
@ -45,6 +48,8 @@ TwoDSpectralCompliance::TwoDSpectralCompliance(QWidget *parent) :
|
|||
layout->addWidget(this->_plot);
|
||||
setupPlot();
|
||||
createFloatingInfoWidget();
|
||||
_busy_indicator = new BusyIndicator(this);
|
||||
|
||||
}
|
||||
|
||||
TwoDSpectralCompliance::~TwoDSpectralCompliance()
|
||||
|
|
@ -64,10 +69,15 @@ void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant
|
|||
QString csvFile = data_files_set.first().toString();
|
||||
if (csvFile.isEmpty())
|
||||
return;
|
||||
|
||||
auto functionToRun = [this, csvFile](){
|
||||
_busy_indicator->Start();
|
||||
readCsv(csvFile);
|
||||
generateSurfaceData();
|
||||
updateSpectrogram();
|
||||
_busy_indicator->Stop();
|
||||
};
|
||||
QThread* load_data_thread = QThread::create(functionToRun);
|
||||
load_data_thread->start();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -432,3 +442,12 @@ bool TwoDSpectralCompliance::eventFilter(QObject *obj, QEvent *event)
|
|||
}
|
||||
return QWidget::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void TwoDSpectralCompliance::showEvent(QShowEvent *e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
if (_busy_indicator) {
|
||||
_busy_indicator->setGeometry(this->rect());
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class QwtPlotSpectrogram;
|
|||
class QPushButton;
|
||||
class QLineEdit;
|
||||
class ScatterPlotItem;
|
||||
class BusyIndicator;
|
||||
namespace Ui {
|
||||
class TwoDSpectralCompliance;
|
||||
}
|
||||
|
|
@ -34,6 +35,7 @@ public:
|
|||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
virtual void showEvent(QShowEvent* e) override final;
|
||||
|
||||
private:
|
||||
void setupPlot();
|
||||
|
|
@ -80,6 +82,8 @@ private:
|
|||
|
||||
QPoint m_dragPosition;
|
||||
bool m_dragging = false;
|
||||
BusyIndicator* _busy_indicator = nullptr;
|
||||
|
||||
};
|
||||
|
||||
#endif // TWODSPECTRALCOMPLIANCE_H
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <QDebug>
|
||||
#include <GlobalDefine.h>
|
||||
#include "csv.h"
|
||||
#include <QThread>
|
||||
#include "BusyIndicator.h"
|
||||
|
||||
CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) :
|
||||
MeasureAnalysisView(parent),
|
||||
|
|
@ -24,6 +26,7 @@ CountRateAnalysisView::CountRateAnalysisView(QWidget *parent) :
|
|||
this->setViewType(PlotFrame);
|
||||
|
||||
InitUi();
|
||||
_busy_indicator = new BusyIndicator(this);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -36,13 +39,28 @@ void CountRateAnalysisView::InitViewWorkspace(const QString &project_name)
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
void CountRateAnalysisView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
|
||||
{
|
||||
if(!data_files_set.isEmpty())
|
||||
{
|
||||
m_AllData = getParticleInjectTimeData(data_files_set.first().toString());
|
||||
setData(m_AllData);
|
||||
auto functionToRun = [this,data_files_set]
|
||||
{
|
||||
_busy_indicator->Start();
|
||||
m_AllData = getParticleInjectTimeData(data_files_set.first().toString());
|
||||
setData(m_AllData);
|
||||
_busy_indicator->Stop();
|
||||
};
|
||||
QThread* load_data_thread = QThread::create(functionToRun);
|
||||
load_data_thread->start();
|
||||
}
|
||||
}
|
||||
|
||||
void CountRateAnalysisView::showEvent(QShowEvent *e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
if (_busy_indicator) {
|
||||
_busy_indicator->setGeometry(this->rect());
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +137,6 @@ QVector<ParticleInjectTime> CountRateAnalysisView::getParticleInjectTimeData(QSt
|
|||
rec.dTime = time_count;
|
||||
records.append(rec);
|
||||
}
|
||||
return records;
|
||||
|
||||
return records;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
#include "MeasureAnalysisView.h"
|
||||
|
||||
class CustomQwtPlot;
|
||||
class BusyIndicator;
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class CountRateAnalysisView;
|
||||
|
|
@ -23,6 +25,8 @@ public:
|
|||
virtual void InitViewWorkspace(const QString& project_name) override final;
|
||||
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set);
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent* e) override final;
|
||||
void setData(QVector<ParticleInjectTime> data);
|
||||
|
||||
//获取数据
|
||||
|
|
@ -33,8 +37,10 @@ private:
|
|||
|
||||
private:
|
||||
Ui::CountRateAnalysisView *ui;
|
||||
BusyIndicator* _busy_indicator = nullptr;
|
||||
CustomQwtPlot *plot;
|
||||
QVector<ParticleInjectTime> m_AllData;//存储的所有的粒子入射时间数据
|
||||
};
|
||||
|
||||
#endif //COUNTRATEANALYSIS_H
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,22 +27,45 @@ struct PeakFitResult
|
|||
double baseline; // 常数项 C
|
||||
double sigmoidH; // Sigmoid 项高度 H
|
||||
double sigmoidW; // Sigmoid 项宽度 W
|
||||
};
|
||||
struct PeakFitHistoryItem {
|
||||
QDateTime timestamp; // 时间戳
|
||||
double center; // 峰中心能量 (keV)
|
||||
double fwhm; // 半高宽
|
||||
double area; // 峰面积
|
||||
double amplitude; // 幅度 A
|
||||
double sigma; // 标准差 delt
|
||||
double sigmoidH; // H
|
||||
double sigmoidW; // W
|
||||
double baseline; // C
|
||||
double xMin; // 拟合曲线显示范围左边界
|
||||
double xMax; // 拟合曲线显示范围右边界
|
||||
};
|
||||
|
||||
QJsonObject toJson() const;
|
||||
static PeakFitHistoryItem fromJson(const QJsonObject& obj);
|
||||
struct FitCurveData {
|
||||
double amplitude; // 峰幅度
|
||||
double sigma; // 高斯sigma
|
||||
double sigmoidH; // Sigmoid高度
|
||||
double sigmoidW; // Sigmoid宽度
|
||||
double baseline; // 本底
|
||||
double center; // 峰中心
|
||||
double xMin; // 曲线X范围最小值
|
||||
double xMax; // 曲线X范围最大值
|
||||
QRectF selectionRect; //关联的框选区域
|
||||
|
||||
double fwhm; // 半高宽
|
||||
double area; // 峰面积
|
||||
};
|
||||
|
||||
struct PeakFitHistoryItem {
|
||||
QDateTime timestamp;
|
||||
QList<FitCurveData> curveList; //存储多条曲线
|
||||
|
||||
QJsonObject toJson() const;
|
||||
static PeakFitHistoryItem fromJson(const QJsonObject& obj);
|
||||
};
|
||||
|
||||
struct CurrentFitRecord {
|
||||
PeakFitResult result; // 拟合结果
|
||||
arma::vec params; // 完整拟合参数
|
||||
double xMin; // X范围最小值
|
||||
double xMax; // X范围最大值
|
||||
int historyIndex; // 对应_fitHistoryList中的索引,-1表示未保存
|
||||
CurrentFitRecord() : historyIndex(-1) {} // 构造函数初始化
|
||||
};
|
||||
|
||||
struct DisplayedCurveRef {
|
||||
int historyIndex; // 对应 _fitHistoryList 的索引
|
||||
int curveIndex; // 对应 curveList 的索引
|
||||
int curveStartIndex; //对应 _fitCurves 中的起始索引(一条历史曲线对应2条Qwt曲线:拟合+本底)
|
||||
int rectIndex; //对应 _selectionRectItems 中的索引
|
||||
};
|
||||
|
||||
class PlotRectItem; // 前向声明
|
||||
|
|
@ -51,6 +74,7 @@ class CustomQwtPlot;
|
|||
class CustomQwtPlotXaxisSelector;
|
||||
class QwtPlotPicker;
|
||||
class QwtPlotCurve;
|
||||
class BusyIndicator;
|
||||
|
||||
class EnergyCountPeakFitView : public MeasureAnalysisView
|
||||
{
|
||||
|
|
@ -72,16 +96,21 @@ private:
|
|||
void saveHistoryToFile();
|
||||
void saveCurrentFitToHistory(); // 保存当前拟合结果
|
||||
void displayFitFromHistory(const PeakFitHistoryItem& item); // 显示历史拟合曲线
|
||||
|
||||
//处理鼠标悬停检测
|
||||
void updateHoverState(const QPoint& mousePos);
|
||||
//显示选中的曲线
|
||||
void displaySelectedCurves(const QList<FitCurveData>& curves, const QList<DisplayedCurveRef>& refs);
|
||||
private slots:
|
||||
void onActionCurveShowSetting();
|
||||
void onActionPlotConfigure();
|
||||
void clearAllSelectionRects();
|
||||
void clearFitCurves(); // 清除所有拟合曲线
|
||||
|
||||
|
||||
// [NEW] 新增菜单槽函数
|
||||
void onActionSaveCurrentFit();
|
||||
void onActionShowFitHistory();
|
||||
void onActionSaveCurrentFit();
|
||||
void onActionShowFitHistory();
|
||||
void onActionDeleteHoveredRect();
|
||||
//重新拟合当前悬停的框选区域
|
||||
void onActionRefitCurrentRect();
|
||||
protected:
|
||||
bool eventFilter(QObject* watched, QEvent* event) override; // 事件过滤器
|
||||
|
||||
|
|
@ -92,9 +121,12 @@ private:
|
|||
void addSelectionRect(const QRectF& plotRect);
|
||||
void fadeSelectionRectBorders();
|
||||
|
||||
QList<PeakFitResult> performPeakFitting(const QVector<double>& x, const QVector<double>& y, const arma::vec* userP0 = nullptr);
|
||||
QList<PeakFitResult> performPeakFitting(const QVector<double>& x, const QVector<double>& y/*, const arma::vec* userP0 = nullptr*/);
|
||||
// 根据拟合参数生成曲线
|
||||
QwtPlotCurve* createFitCurve(const PeakFitResult& result, double xMin, double xMax, const QString& name);
|
||||
|
||||
QList<QwtPlotCurve*> createFitCurve(const PeakFitResult& result, arma::vec xVec);
|
||||
|
||||
private:
|
||||
CustomQwtPlot* _plot = nullptr;
|
||||
QMenu* _menu = nullptr;
|
||||
|
|
@ -112,8 +144,7 @@ private:
|
|||
QList<QwtPlotCurve*> _fitCurves;
|
||||
|
||||
|
||||
// [NEW] 历史记录相关成员
|
||||
QList<PeakFitHistoryItem> _fitHistoryList;
|
||||
|
||||
QString _historyFilePath;
|
||||
|
||||
// [NEW] 最近一次拟合结果(用于手动保存)
|
||||
|
|
@ -123,6 +154,14 @@ private:
|
|||
bool _hasLastFit = false;
|
||||
QString _workspace;
|
||||
|
||||
//存储当前所有拟合结果(用于多曲线管理)
|
||||
QList<CurrentFitRecord> _currentFitRecords;
|
||||
//历史记录列表
|
||||
QList<PeakFitHistoryItem> _fitHistoryList;
|
||||
//当前悬停的框选区域
|
||||
PlotRectItem* _hoveredRectItem = nullptr;
|
||||
QList<DisplayedCurveRef> _displayedHistoryCurves;
|
||||
|
||||
};
|
||||
|
||||
#endif // ENERGYCOUNTPEAKFITVIEW_H
|
||||
|
|
|
|||
|
|
@ -2,23 +2,63 @@
|
|||
#include <QPainter>
|
||||
#include <QwtScaleMap>
|
||||
PlotRectItem::PlotRectItem(const QString &title)
|
||||
: QwtPlotItem() {
|
||||
: QwtPlotItem(), m_isHovered(false), m_hasPeakData(false)
|
||||
,m_selectionType(""), m_selectionIndex(-1)
|
||||
{
|
||||
setTitle(title);
|
||||
setZ(1000);
|
||||
m_pen = QPen(Qt::red, 2, Qt::SolidLine);
|
||||
// 初始化普通状态画笔:红色虚线,线宽2
|
||||
m_normalPen = QPen(Qt::red, 2, Qt::DashLine);
|
||||
// 初始化悬停状态画笔:红色实线,线宽2
|
||||
m_hoverPen = QPen(Qt::red, 2, Qt::SolidLine);
|
||||
|
||||
m_brush = QBrush(QColor(255, 0, 0, 30));
|
||||
}
|
||||
|
||||
void PlotRectItem::setRect(const QRectF &rect) {
|
||||
m_rect = rect;
|
||||
itemChanged(); // 触发重绘
|
||||
}
|
||||
|
||||
void PlotRectItem::setPen(const QPen &pen) {
|
||||
m_pen = pen;
|
||||
m_normalPen = pen;
|
||||
// 同步悬停画笔的颜色和宽度,仅改变线型
|
||||
m_hoverPen = pen;
|
||||
m_hoverPen.setStyle(Qt::SolidLine);
|
||||
itemChanged();
|
||||
}
|
||||
|
||||
void PlotRectItem::setBrush(const QBrush &brush) {
|
||||
m_brush = brush;
|
||||
itemChanged();
|
||||
}
|
||||
|
||||
//设置悬停状态
|
||||
void PlotRectItem::setHovered(bool hovered) {
|
||||
if (m_isHovered != hovered) {
|
||||
m_isHovered = hovered;
|
||||
itemChanged(); // 触发重绘
|
||||
}
|
||||
}
|
||||
|
||||
//获取悬停状态
|
||||
bool PlotRectItem::isHovered() const {
|
||||
return m_isHovered;
|
||||
}
|
||||
|
||||
//获取矩形区域
|
||||
QRectF PlotRectItem::rect() const {
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
void PlotRectItem::setPeakData(double center, double fwhm, double area, double baseline)
|
||||
{
|
||||
m_hasPeakData = true;
|
||||
m_peakCenter = center;
|
||||
m_fwhm = fwhm;
|
||||
m_peakArea = area;
|
||||
m_baseline = baseline;
|
||||
itemChanged(); // 触发重绘
|
||||
}
|
||||
|
||||
void PlotRectItem::draw(QPainter *painter,
|
||||
|
|
@ -31,10 +71,45 @@ void PlotRectItem::draw(QPainter *painter,
|
|||
const QRect rect(QPoint(x1, y1), QPoint(x2, y2));
|
||||
|
||||
painter->save();
|
||||
painter->setPen(m_pen);
|
||||
// 根据悬停状态选择画笔
|
||||
painter->setPen(m_isHovered ? m_hoverPen : m_normalPen);
|
||||
painter->setBrush(m_brush);
|
||||
painter->drawRect(rect);
|
||||
painter->restore();
|
||||
|
||||
if (m_hasPeakData) {
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::TextAntialiasing);
|
||||
|
||||
// 构建文本内容
|
||||
QString text = QString("峰位: %1 keV\n"
|
||||
"FWHM: %2\n"
|
||||
"面积: %3\n"
|
||||
"本底: %4")
|
||||
.arg(m_peakCenter, 0, 'f', 2)
|
||||
.arg(m_fwhm, 0, 'f', 2)
|
||||
.arg(m_peakArea, 0, 'f', 2)
|
||||
.arg(m_baseline, 0, 'f', 2);
|
||||
|
||||
// 计算文本位置:矩形右上角 + 偏移量
|
||||
QPoint textPos(x2 + 10, y2);
|
||||
|
||||
// 绘制半透明背景框(增强可读性)
|
||||
QFont font = painter->font();
|
||||
font.setPointSize(9); // 稍微小一点
|
||||
painter->setFont(font);
|
||||
|
||||
QFontMetrics fm(font);
|
||||
QRect textRect = fm.boundingRect(QRect(0, 0, 1, 1), Qt::AlignLeft, text);
|
||||
textRect.moveTopLeft(textPos);
|
||||
textRect.adjust(-5, -3, 5, 3); // 增加边距
|
||||
|
||||
painter->fillRect(textRect, QColor(255, 255, 255, 220)); // 白底微透
|
||||
painter->setPen(Qt::black);
|
||||
painter->drawText(textRect, Qt::AlignLeft, text);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
QRectF PlotRectItem::boundingRect() const {
|
||||
|
|
|
|||
|
|
@ -13,16 +13,42 @@ public:
|
|||
void setPen(const QPen &pen);
|
||||
void setBrush(const QBrush &brush);
|
||||
|
||||
//设置/获取悬停状态
|
||||
void setHovered(bool hovered);
|
||||
bool isHovered() const;
|
||||
//获取当前矩形区域(用于碰撞检测)
|
||||
QRectF rect() const;
|
||||
//设置要显示的峰拟合数据
|
||||
void setPeakData(double center, double fwhm, double area, double baseline);
|
||||
void setSelectionType(const QString& type) { m_selectionType = type; }
|
||||
QString selectionType() const { return m_selectionType; }
|
||||
|
||||
void setSelectionIndex(int index) { m_selectionIndex = index; }
|
||||
int selectionIndex() const { return m_selectionIndex; }
|
||||
virtual void draw(QPainter *painter,
|
||||
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||||
const QRectF &canvasRect) const override;
|
||||
|
||||
virtual QRectF boundingRect() const override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
QRectF m_rect;
|
||||
QPen m_pen;
|
||||
QPen m_normalPen; //普通状态画笔(虚线)
|
||||
QPen m_hoverPen; //悬停状态画笔(实线)
|
||||
QBrush m_brush;
|
||||
bool m_isHovered; //悬停状态标志
|
||||
|
||||
|
||||
bool m_hasPeakData;
|
||||
double m_peakCenter;
|
||||
double m_fwhm;
|
||||
double m_peakArea;
|
||||
double m_baseline;
|
||||
|
||||
QString m_selectionType; // "current" 或 "history"
|
||||
int m_selectionIndex; // 对应的索引
|
||||
};
|
||||
|
||||
#endif // PLOTRECTITEM_H
|
||||
|
|
|
|||
101
src/NuclideLib/NuclideEditDialog.cpp
Normal file
101
src/NuclideLib/NuclideEditDialog.cpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#include "NuclideEditDialog.h"
|
||||
|
||||
NuclideEditDialog::NuclideEditDialog(bool isEdit, const QStringList& nuclideData, QWidget *parent)
|
||||
: QDialog(parent), m_isEdit(isEdit)
|
||||
{
|
||||
// 编辑模式下提取ID和已有数据
|
||||
if (isEdit && !nuclideData.isEmpty()) {
|
||||
m_id = nuclideData[0]; // 第一个元素是ID
|
||||
}
|
||||
initUI();
|
||||
|
||||
// 编辑模式:填充已有数据(字段顺序不变,仅数据库字段名修改)
|
||||
if (isEdit && nuclideData.size() >= 6) {
|
||||
m_leName->setText(nuclideData[1]);
|
||||
m_leHalfLife->setText(nuclideData[2]);
|
||||
m_leHalfLifeUnc->setText(nuclideData[3]);
|
||||
m_leParentNuclide->setText(nuclideData[4]);
|
||||
m_leChildNuclide->setText(nuclideData[5]);
|
||||
}
|
||||
}
|
||||
|
||||
void NuclideEditDialog::initUI()
|
||||
{
|
||||
setWindowTitle(m_isEdit ? "编辑核素信息" : "添加核素信息");
|
||||
setFixedSize(400, 220); // 稍微增加高度适配新校验提示
|
||||
|
||||
// 表单布局(控件名称不变,仅数据库映射修改)
|
||||
QFormLayout *formLayout = new QFormLayout(this);
|
||||
m_leName = new QLineEdit(this);
|
||||
m_leHalfLife = new QLineEdit(this);
|
||||
m_leHalfLifeUnc = new QLineEdit(this);
|
||||
m_leParentNuclide = new QLineEdit(this);
|
||||
m_leChildNuclide = new QLineEdit(this);
|
||||
|
||||
// 设置表单项(标签不变,用户界面无感知)
|
||||
formLayout->addRow("核素名称", m_leName);
|
||||
formLayout->addRow("半衰期", m_leHalfLife);
|
||||
formLayout->addRow("半衰期不确定度", m_leHalfLifeUnc);
|
||||
formLayout->addRow("母体核素名称", m_leParentNuclide);
|
||||
formLayout->addRow("子体核素名称", m_leChildNuclide);
|
||||
|
||||
// 按钮盒
|
||||
QDialogButtonBox *btnBox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
||||
Qt::Horizontal, this);
|
||||
formLayout->addRow(btnBox);
|
||||
|
||||
// 信号连接
|
||||
connect(btnBox, &QDialogButtonBox::accepted, this, [this]() {
|
||||
if (validateInput()) {
|
||||
accept();
|
||||
}
|
||||
});
|
||||
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
bool NuclideEditDialog::validateInput()
|
||||
{
|
||||
// 必填项校验
|
||||
if (m_leName->text().trimmed().isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "核素名称不能为空!");
|
||||
return false;
|
||||
}
|
||||
if (m_leHalfLife->text().trimmed().isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "半衰期不能为空!");
|
||||
return false;
|
||||
}
|
||||
if (m_leHalfLifeUnc->text().trimmed().isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "半衰期不确定度不能为空!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
// 半衰期校验(保留原逻辑,TEXT类型可存储带单位的字符串)
|
||||
m_leHalfLife->text().toDouble(&ok);
|
||||
if (!ok) {
|
||||
QMessageBox::warning(this, "输入错误", "半衰期必须为数字(可带单位,如12.5d)!");
|
||||
return false;
|
||||
}
|
||||
m_leHalfLifeUnc->text().toDouble(&ok);
|
||||
if (!ok) {
|
||||
QMessageBox::warning(this, "输入错误", "半衰期不确定度必须为有效数字!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList NuclideEditDialog::getNuclideData() const
|
||||
{
|
||||
QStringList data;
|
||||
if (m_isEdit) {
|
||||
data << m_id; // 编辑模式返回ID
|
||||
}
|
||||
data << m_leName->text().trimmed()
|
||||
<< m_leHalfLife->text().trimmed()
|
||||
<< m_leHalfLifeUnc->text().trimmed()
|
||||
<< m_leParentNuclide->text().trimmed()
|
||||
<< m_leChildNuclide->text().trimmed();
|
||||
return data;
|
||||
}
|
||||
35
src/NuclideLib/NuclideEditDialog.h
Normal file
35
src/NuclideLib/NuclideEditDialog.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef NUCLIDEEDITDIALOG_H
|
||||
#define NUCLIDEEDITDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QFormLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QMessageBox>
|
||||
|
||||
class NuclideEditDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// 构造函数:isEdit=true为编辑模式,传入已有数据;false为添加模式
|
||||
explicit NuclideEditDialog(bool isEdit = false, const QStringList& nuclideData = {}, QWidget *parent = nullptr);
|
||||
~NuclideEditDialog() = default;
|
||||
|
||||
// 获取用户输入的核素数据(编辑模式:ID+5个字段;添加模式:5个字段)
|
||||
QStringList getNuclideData() const;
|
||||
|
||||
private:
|
||||
void initUI(); // 初始化界面
|
||||
bool validateInput(); // 输入校验(新增半衰期不确定度的数字校验)
|
||||
|
||||
QLineEdit *m_leName; // 核素名称(对应NUCLIDE_NAME)
|
||||
QLineEdit *m_leHalfLife; // 半衰期(对应HALF_LIFE)
|
||||
QLineEdit *m_leHalfLifeUnc; // 半衰期不确定度(对应HALF_LIFE_UNCERTAINTY)
|
||||
QLineEdit *m_leParentNuclide; // 母体核素名称(对应PARENT_NUCLIDE_NAME)
|
||||
QLineEdit *m_leChildNuclide; // 子体核素名称(对应CHILD_NUCLIDE_NAME)
|
||||
|
||||
bool m_isEdit; // 是否为编辑模式
|
||||
QString m_id; // 编辑模式下的核素ID
|
||||
};
|
||||
|
||||
#endif // NUCLIDEEDITDIALOG_H
|
||||
|
|
@ -7,7 +7,9 @@
|
|||
#include <QStyleOptionButton>
|
||||
#include <QMouseEvent>
|
||||
#include <QApplication>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDateTime>
|
||||
#include "NuclideRayListDialog.h"
|
||||
ButtonDelegate::ButtonDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
|
||||
|
||||
void ButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
|
|
@ -62,10 +64,20 @@ NuclideLibManage::NuclideLibManage(QWidget *parent) :
|
|||
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
ui->tableView->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
QString dbPath = QCoreApplication::applicationDirPath() + "/nuclideLib.db"; // 绝对路径(推荐)
|
||||
qDebug()<<dbPath;
|
||||
bool dbOpened = SqliteManager::instance().openDatabase(dbPath);
|
||||
if (!dbOpened) {
|
||||
QMessageBox::critical(this, "数据库错误", "打开数据库失败:" + SqliteManager::instance().lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置委托
|
||||
m_delegate = new ButtonDelegate(this);
|
||||
ui->tableView->setItemDelegateForColumn(7, m_delegate);
|
||||
connect(m_delegate, &ButtonDelegate::buttonClicked, this, &NuclideLibManage::onButtonClicked);
|
||||
loadNuclideData();
|
||||
|
||||
}
|
||||
|
||||
NuclideLibManage::~NuclideLibManage()
|
||||
|
|
@ -75,45 +87,42 @@ NuclideLibManage::~NuclideLibManage()
|
|||
|
||||
void NuclideLibManage::loadNuclideData()
|
||||
{
|
||||
QString sql = "SELECT ID, NAME, HALF_LIFE, HALF_LIFE_UNC, PARENT_NUCLIDE, CHILD_NUCLIDE FROM tbl_nuclide_library;";
|
||||
QString sql = "SELECT ID, NUCLIDE_NAME, HALF_LIFE, HALF_LIFE_UNCERTAINTY, PARENT_NUCLIDE_NAME, CHILD_NUCLIDE_NAME FROM nuclideLib;";
|
||||
auto rows = SqliteManager::instance().selectRows(sql);
|
||||
|
||||
m_listNuclide.clear();
|
||||
m_model->setRowCount(0);
|
||||
|
||||
int row = 0;
|
||||
for (const auto& rec : rows) {
|
||||
QStringList item;
|
||||
item << rec["ID"].toString()
|
||||
<< rec["NAME"].toString()
|
||||
<< rec["NUCLIDE_NAME"].toString()
|
||||
<< rec["HALF_LIFE"].toString()
|
||||
<< rec["HALF_LIFE_UNC"].toString()
|
||||
<< rec["PARENT_NUCLIDE"].toString()
|
||||
<< rec["CHILD_NUCLIDE"].toString();
|
||||
<< rec["HALF_LIFE_UNCERTAINTY"].toString() // 对应新字段名
|
||||
<< rec["PARENT_NUCLIDE_NAME"].toString() // 对应新字段名
|
||||
<< rec["CHILD_NUCLIDE_NAME"].toString(); // 对应新字段名
|
||||
m_listNuclide.append(item);
|
||||
|
||||
// 插入模型行
|
||||
// 插入模型行(界面显示逻辑不变)
|
||||
QList<QStandardItem*> rowItems;
|
||||
// 第0列:ID(隐藏)
|
||||
QStandardItem *idItem = new QStandardItem(item[0]);
|
||||
idItem->setTextAlignment(Qt::AlignCenter);
|
||||
idItem->setFlags(idItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << idItem;
|
||||
|
||||
// 第1列:序号(行号+1)
|
||||
QStandardItem *seqItem = new QStandardItem(QString::number(row + 1));
|
||||
seqItem->setTextAlignment(Qt::AlignCenter);
|
||||
seqItem->setFlags(seqItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << seqItem;
|
||||
|
||||
// 第2~6列:核素名称、半衰期等
|
||||
for (int col = 1; col <= 5; ++col) { // item的下标1~5对应NAME到CHILD_NUCLIDE
|
||||
for (int col = 1; col <= 5; ++col) {
|
||||
QStandardItem *dataItem = new QStandardItem(item[col]);
|
||||
dataItem->setTextAlignment(Qt::AlignCenter);
|
||||
dataItem->setFlags(dataItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << dataItem;
|
||||
}
|
||||
|
||||
// 第7列:操作列(存储空字符串,委托负责绘制按钮)
|
||||
// 第7列:操作列
|
||||
QStandardItem *opItem = new QStandardItem("");
|
||||
opItem->setFlags(opItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << opItem;
|
||||
|
|
@ -134,7 +143,27 @@ QStringList NuclideLibManage::getNuclideData(const QString &id)
|
|||
|
||||
void NuclideLibManage::on_pushButton_add_clicked()
|
||||
{
|
||||
loadNuclideData(); // 刷新数据
|
||||
NuclideEditDialog dlg(false, {}, this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
QStringList data = dlg.getNuclideData();
|
||||
if (data.size() < 5) return;
|
||||
|
||||
QMap<QString, QVariant> fieldValues;
|
||||
fieldValues["NUCLIDE_NAME"] = data[0];
|
||||
fieldValues["HALF_LIFE"] = data[1];
|
||||
fieldValues["HALF_LIFE_UNCERTAINTY"] = data[2].toDouble(); // 显式转换为REAL类型
|
||||
fieldValues["PARENT_NUCLIDE_NAME"] = data[3];
|
||||
fieldValues["CHILD_NUCLIDE_NAME"] = data[4];
|
||||
fieldValues["CREATE_TIME"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
qint64 newId = SqliteManager::instance().insertRow("nuclideLib", fieldValues);
|
||||
if (newId > 0) {
|
||||
QMessageBox::information(this, "成功", "核素添加成功!");
|
||||
loadNuclideData();
|
||||
} else {
|
||||
QMessageBox::warning(this, "失败", "添加失败:" + SqliteManager::instance().lastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NuclideLibManage::on_pushButton_edit_clicked()
|
||||
|
|
@ -144,10 +173,40 @@ void NuclideLibManage::on_pushButton_edit_clicked()
|
|||
QMessageBox::information(this, "提示", "请先选择要修改的核素行!");
|
||||
return;
|
||||
}
|
||||
|
||||
int row = selected.first().row();
|
||||
QString id = m_model->index(row, 0).data().toString(); // 隐藏的ID列
|
||||
QString id = m_model->index(row, 0).data().toString();
|
||||
QStringList data = getNuclideData(id);
|
||||
if (data.isEmpty()) return;
|
||||
|
||||
NuclideEditDialog dlg(true, data, this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
QStringList newData = dlg.getNuclideData();
|
||||
if (newData.size() < 6) return;
|
||||
|
||||
QMap<QString, QVariant> fieldValues;
|
||||
fieldValues["NUCLIDE_NAME"] = newData[1];
|
||||
fieldValues["HALF_LIFE"] = newData[2];
|
||||
fieldValues["HALF_LIFE_UNCERTAINTY"] = newData[3].toDouble(); // 显式转换为REAL类型
|
||||
fieldValues["PARENT_NUCLIDE_NAME"] = newData[4];
|
||||
fieldValues["CHILD_NUCLIDE_NAME"] = newData[5];
|
||||
|
||||
int affectedRows = SqliteManager::instance().updateRow(
|
||||
"nuclideLib",
|
||||
fieldValues,
|
||||
"ID = ?",
|
||||
{newData[0]}
|
||||
);
|
||||
|
||||
if (affectedRows > 0) {
|
||||
QMessageBox::information(this, "成功", "核素修改成功!");
|
||||
loadNuclideData();
|
||||
} else if (affectedRows == 0) {
|
||||
QMessageBox::information(this, "提示", "未修改任何数据!");
|
||||
} else {
|
||||
QMessageBox::warning(this, "失败", "修改失败:" + SqliteManager::instance().lastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NuclideLibManage::on_pushButton_del_clicked()
|
||||
|
|
@ -157,6 +216,7 @@ void NuclideLibManage::on_pushButton_del_clicked()
|
|||
QMessageBox::information(this, "提示", "请先选择要删除的核素行!");
|
||||
return;
|
||||
}
|
||||
|
||||
int row = selected.first().row();
|
||||
QString id = m_model->index(row, 0).data().toString();
|
||||
|
||||
|
|
@ -166,7 +226,7 @@ void NuclideLibManage::on_pushButton_del_clicked()
|
|||
box.button(QMessageBox::No)->setText("取消");
|
||||
if (box.exec() != QMessageBox::Yes) return;
|
||||
|
||||
bool ok = SqliteManager::instance().deleteRow("tbl_nuclide_library", "ID = ?", {id});
|
||||
bool ok = SqliteManager::instance().deleteRow("nuclideLib", "ID = ?", {id});
|
||||
if (ok) {
|
||||
loadNuclideData();
|
||||
} else {
|
||||
|
|
@ -178,4 +238,10 @@ void NuclideLibManage::onButtonClicked(const QModelIndex &index)
|
|||
{
|
||||
int row = index.row();
|
||||
QString nuclideId = m_model->index(row, 0).data().toString();
|
||||
QString nuclideName = m_model->index(row, 2).data().toString();
|
||||
|
||||
// 打开射线信息管理对话框
|
||||
NuclideRayListDialog dlg(nuclideId, nuclideName, this);
|
||||
dlg.exec();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <QVector>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QStandardItemModel>
|
||||
#include "NuclideEditDialog.h"
|
||||
|
||||
namespace Ui {
|
||||
class NuclideLibManage;
|
||||
|
|
|
|||
133
src/NuclideLib/NuclideRayDialog.cpp
Normal file
133
src/NuclideLib/NuclideRayDialog.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
#include "NuclideRayDialog.h"
|
||||
|
||||
NuclideRayDialog::NuclideRayDialog(bool isEdit, const QStringList& rayData, QWidget *parent)
|
||||
: QDialog(parent), m_isEdit(isEdit)
|
||||
{
|
||||
// 编辑模式下提取ID和已有数据
|
||||
if (isEdit && !rayData.isEmpty()) {
|
||||
m_id = rayData[0]; // 第一个元素是ID
|
||||
}
|
||||
initUI();
|
||||
|
||||
// 编辑模式:填充已有数据
|
||||
if (isEdit && rayData.size() >= 8) {
|
||||
m_cmbRayType->setCurrentText(rayData[1]);
|
||||
m_leRayMev->setText(rayData[2]);
|
||||
m_leRayMevUnc->setText(rayData[3]);
|
||||
m_leBranchRatio->setText(rayData[4]);
|
||||
m_leBranchRatioUnc->setText(rayData[5]);
|
||||
m_cmbMainRayIdent->setCurrentText(rayData[6]);
|
||||
m_leJiahePeak->setText(rayData[7]);
|
||||
}
|
||||
}
|
||||
|
||||
void NuclideRayDialog::initUI()
|
||||
{
|
||||
setWindowTitle(m_isEdit ? "编辑射线信息" : "添加射线信息");
|
||||
setFixedSize(450, 300);
|
||||
|
||||
QFormLayout *formLayout = new QFormLayout(this);
|
||||
|
||||
// 射线类型下拉框(常用核素射线类型)
|
||||
m_cmbRayType = new QComboBox(this);
|
||||
m_cmbRayType->addItems({"γ", "β⁻", "β⁺", "α", "X射线", "中子", "电子俘获"});
|
||||
formLayout->addRow("射线类型", m_cmbRayType);
|
||||
|
||||
m_leRayMev = new QLineEdit(this);
|
||||
m_leRayMev->setPlaceholderText("例如:1.332 MeV");
|
||||
formLayout->addRow("射线能量", m_leRayMev);
|
||||
|
||||
m_leRayMevUnc = new QLineEdit(this);
|
||||
m_leRayMevUnc->setPlaceholderText("例如:0.001 MeV");
|
||||
formLayout->addRow("能量不确定度", m_leRayMevUnc);
|
||||
|
||||
m_leBranchRatio = new QLineEdit(this);
|
||||
m_leBranchRatio->setPlaceholderText("例如:0.9998");
|
||||
formLayout->addRow("分支比", m_leBranchRatio);
|
||||
|
||||
m_leBranchRatioUnc = new QLineEdit(this);
|
||||
m_leBranchRatioUnc->setPlaceholderText("例如:0.0001");
|
||||
formLayout->addRow("分支比不确定度", m_leBranchRatioUnc);
|
||||
|
||||
// 主射线标识下拉框
|
||||
m_cmbMainRayIdent = new QComboBox(this);
|
||||
m_cmbMainRayIdent->addItems({"是", "否"});
|
||||
formLayout->addRow("是否为主射线", m_cmbMainRayIdent);
|
||||
|
||||
m_leJiahePeak = new QLineEdit(this);
|
||||
m_leJiahePeak->setPlaceholderText("无则留空");
|
||||
formLayout->addRow("加和峰", m_leJiahePeak);
|
||||
|
||||
// 按钮盒
|
||||
QDialogButtonBox *btnBox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
|
||||
Qt::Horizontal, this);
|
||||
formLayout->addRow(btnBox);
|
||||
|
||||
// 信号连接
|
||||
connect(btnBox, &QDialogButtonBox::accepted, this, [this]() {
|
||||
if (validateInput()) {
|
||||
accept();
|
||||
}
|
||||
});
|
||||
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
bool NuclideRayDialog::validateInput()
|
||||
{
|
||||
// 必填项校验
|
||||
if (m_leRayMev->text().trimmed().isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "射线能量不能为空!");
|
||||
return false;
|
||||
}
|
||||
if (m_leRayMevUnc->text().trimmed().isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "能量不确定度不能为空!");
|
||||
return false;
|
||||
}
|
||||
if (m_leBranchRatioUnc->text().trimmed().isEmpty()) {
|
||||
QMessageBox::warning(this, "输入错误", "分支比不确定度不能为空!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 数字格式校验(允许带单位)
|
||||
bool ok;
|
||||
// 提取数字部分进行校验
|
||||
QString mevText = m_leRayMev->text().trimmed().replace(QRegExp("[^0-9.]"), "");
|
||||
mevText.toDouble(&ok);
|
||||
if (!ok) {
|
||||
QMessageBox::warning(this, "输入错误", "射线能量必须为有效数字!");
|
||||
return false;
|
||||
}
|
||||
|
||||
QString mevUncText = m_leRayMevUnc->text().trimmed().replace(QRegExp("[^0-9.]"), "");
|
||||
mevUncText.toDouble(&ok);
|
||||
if (!ok) {
|
||||
QMessageBox::warning(this, "输入错误", "能量不确定度必须为有效数字!");
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ratioUncText = m_leBranchRatioUnc->text().trimmed().replace(QRegExp("[^0-9.]"), "");
|
||||
ratioUncText.toDouble(&ok);
|
||||
if (!ok) {
|
||||
QMessageBox::warning(this, "输入错误", "分支比不确定度必须为有效数字!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList NuclideRayDialog::getRayData() const
|
||||
{
|
||||
QStringList data;
|
||||
if (m_isEdit) {
|
||||
data << m_id; // 编辑模式返回ID
|
||||
}
|
||||
data << m_cmbRayType->currentText().trimmed()
|
||||
<< m_leRayMev->text().trimmed()
|
||||
<< m_leRayMevUnc->text().trimmed()
|
||||
<< m_leBranchRatio->text().trimmed()
|
||||
<< m_leBranchRatioUnc->text().trimmed()
|
||||
<< m_cmbMainRayIdent->currentText().trimmed()
|
||||
<< m_leJiahePeak->text().trimmed();
|
||||
return data;
|
||||
}
|
||||
37
src/NuclideLib/NuclideRayDialog.h
Normal file
37
src/NuclideLib/NuclideRayDialog.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef NUCLIDERAYDIALOG_H
|
||||
#define NUCLIDERAYDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QMessageBox>
|
||||
|
||||
class NuclideRayDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NuclideRayDialog(bool isEdit = false, const QStringList& rayData = {}, QWidget *parent = nullptr);
|
||||
~NuclideRayDialog() = default;
|
||||
|
||||
|
||||
QStringList getRayData() const;
|
||||
|
||||
private:
|
||||
void initUI(); // 初始化界面
|
||||
bool validateInput(); // 输入校验
|
||||
|
||||
QComboBox *m_cmbRayType; // 射线类型(下拉选择)
|
||||
QLineEdit *m_leRayMev; // 射线能量
|
||||
QLineEdit *m_leRayMevUnc; // 能量不确定度
|
||||
QLineEdit *m_leBranchRatio; // 分支比
|
||||
QLineEdit *m_leBranchRatioUnc; // 分支比不确定度
|
||||
QComboBox *m_cmbMainRayIdent; // 主射线标识
|
||||
QLineEdit *m_leJiahePeak; // 加和峰
|
||||
|
||||
bool m_isEdit; // 是否为编辑模式
|
||||
QString m_id; // 编辑模式下的射线ID
|
||||
};
|
||||
|
||||
#endif // NUCLIDERAYDIALOG_H
|
||||
248
src/NuclideLib/NuclideRayListDialog.cpp
Normal file
248
src/NuclideLib/NuclideRayListDialog.cpp
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
#include "NuclideRayListDialog.h"
|
||||
#include <QTableView>
|
||||
RayButtonDelegate::RayButtonDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
|
||||
|
||||
void RayButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() == 8) { // 第8列是操作列
|
||||
// 绘制编辑按钮
|
||||
QStyleOptionButton editBtn;
|
||||
editBtn.rect = QRect(option.rect.x(), option.rect.y() + 2, 60, option.rect.height() - 4);
|
||||
editBtn.text = "编辑";
|
||||
editBtn.state = QStyle::State_Enabled;
|
||||
if (option.state & QStyle::State_MouseOver)
|
||||
editBtn.state |= QStyle::State_MouseOver;
|
||||
QApplication::style()->drawControl(QStyle::CE_PushButton, &editBtn, painter);
|
||||
|
||||
// 绘制删除按钮
|
||||
QStyleOptionButton delBtn;
|
||||
delBtn.rect = QRect(option.rect.x() + 70, option.rect.y() + 2, 60, option.rect.height() - 4);
|
||||
delBtn.text = "删除";
|
||||
delBtn.state = QStyle::State_Enabled;
|
||||
if (option.state & QStyle::State_MouseOver)
|
||||
delBtn.state |= QStyle::State_MouseOver;
|
||||
QApplication::style()->drawControl(QStyle::CE_PushButton, &delBtn, painter);
|
||||
} else {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
bool RayButtonDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
|
||||
{
|
||||
if (index.column() == 8 && event->type() == QEvent::MouseButtonRelease) {
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
QRect editRect = QRect(option.rect.x(), option.rect.y() + 2, 60, option.rect.height() - 4);
|
||||
QRect delRect = QRect(option.rect.x() + 70, option.rect.y() + 2, 60, option.rect.height() - 4);
|
||||
|
||||
if (editRect.contains(mouseEvent->pos())) {
|
||||
emit editButtonClicked(index);
|
||||
return true;
|
||||
} else if (delRect.contains(mouseEvent->pos())) {
|
||||
emit deleteButtonClicked(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
NuclideRayListDialog::NuclideRayListDialog(const QString& nuclideId, const QString& nuclideName, QWidget *parent)
|
||||
: QDialog(parent), m_nuclideId(nuclideId), m_nuclideName(nuclideName)
|
||||
{
|
||||
initUI();
|
||||
loadRayData();
|
||||
}
|
||||
|
||||
void NuclideRayListDialog::initUI()
|
||||
{
|
||||
setWindowTitle(QString("%1 - 射线信息管理").arg(m_nuclideName));
|
||||
setFixedSize(900, 500);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
|
||||
// 添加按钮
|
||||
QPushButton *btnAdd = new QPushButton("添加射线", this);
|
||||
connect(btnAdd, &QPushButton::clicked, this, &NuclideRayListDialog::onAddRayClicked);
|
||||
mainLayout->addWidget(btnAdd, 0, Qt::AlignRight);
|
||||
|
||||
// 射线列表
|
||||
m_model = new QStandardItemModel(0, 9, this);
|
||||
m_model->setHorizontalHeaderLabels({
|
||||
"ID", "射线类型", "能量(MeV)", "能量不确定度", "分支比",
|
||||
"分支比不确定度", "主射线", "加和峰", "操作"
|
||||
});
|
||||
|
||||
QTableView *tableView = new QTableView(this);
|
||||
tableView->setModel(m_model);
|
||||
tableView->setColumnHidden(0, true); // 隐藏ID列
|
||||
tableView->setColumnWidth(1, 80); // 射线类型
|
||||
tableView->setColumnWidth(2, 120); // 能量
|
||||
tableView->setColumnWidth(3, 120); // 能量不确定度
|
||||
tableView->setColumnWidth(4, 100); // 分支比
|
||||
tableView->setColumnWidth(5, 120); // 分支比不确定度
|
||||
tableView->setColumnWidth(6, 80); // 主射线
|
||||
tableView->setColumnWidth(7, 100); // 加和峰
|
||||
tableView->setColumnWidth(8, 150); // 操作列
|
||||
|
||||
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
tableView->setAlternatingRowColors(true);
|
||||
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
tableView->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
// 设置委托
|
||||
m_delegate = new RayButtonDelegate(this);
|
||||
tableView->setItemDelegateForColumn(8, m_delegate);
|
||||
connect(m_delegate, &RayButtonDelegate::editButtonClicked, this, &NuclideRayListDialog::onEditRayClicked);
|
||||
connect(m_delegate, &RayButtonDelegate::deleteButtonClicked, this, &NuclideRayListDialog::onDeleteRayClicked);
|
||||
|
||||
mainLayout->addWidget(tableView);
|
||||
|
||||
// 关闭按钮
|
||||
QPushButton *btnClose = new QPushButton("关闭", this);
|
||||
connect(btnClose, &QPushButton::clicked, this, &QDialog::accept);
|
||||
mainLayout->addWidget(btnClose, 0, Qt::AlignRight);
|
||||
}
|
||||
|
||||
void NuclideRayListDialog::loadRayData()
|
||||
{
|
||||
// 查询当前核素的所有射线信息
|
||||
QString sql = "SELECT ID, RAY_TYPE, RAY_MEV, RAY_MEV_UNCERTAINTY, RAY_BRANCH_RATIO, "
|
||||
"RAY_BRANCH_RATIO_UNCERTAINTY, MAIN_RAY_IDENT, JIAHE_PEAK "
|
||||
"FROM nuclideRayInfo WHERE NUCLIDE_ID = ?;";
|
||||
auto rows = SqliteManager::instance().selectRows(sql, {m_nuclideId});
|
||||
|
||||
m_listRay.clear();
|
||||
m_model->setRowCount(0);
|
||||
int row = 0;
|
||||
|
||||
for (const auto& rec : rows) {
|
||||
QStringList item;
|
||||
item << rec["ID"].toString()
|
||||
<< rec["RAY_TYPE"].toString()
|
||||
<< rec["RAY_MEV"].toString()
|
||||
<< rec["RAY_MEV_UNCERTAINTY"].toString()
|
||||
<< rec["RAY_BRANCH_RATIO"].toString()
|
||||
<< rec["RAY_BRANCH_RATIO_UNCERTAINTY"].toString()
|
||||
<< rec["MAIN_RAY_IDENT"].toString()
|
||||
<< rec["JIAHE_PEAK"].toString();
|
||||
m_listRay.append(item);
|
||||
|
||||
// 插入模型行
|
||||
QList<QStandardItem*> rowItems;
|
||||
// 第0列:ID(隐藏)
|
||||
QStandardItem *idItem = new QStandardItem(item[0]);
|
||||
idItem->setTextAlignment(Qt::AlignCenter);
|
||||
idItem->setFlags(idItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << idItem;
|
||||
|
||||
// 第1~7列:射线数据
|
||||
for (int col = 1; col <= 7; ++col) {
|
||||
QStandardItem *dataItem = new QStandardItem(item[col]);
|
||||
dataItem->setTextAlignment(Qt::AlignCenter);
|
||||
dataItem->setFlags(dataItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << dataItem;
|
||||
}
|
||||
|
||||
// 第8列:操作列
|
||||
QStandardItem *opItem = new QStandardItem("");
|
||||
opItem->setFlags(opItem->flags() & ~Qt::ItemIsEditable);
|
||||
rowItems << opItem;
|
||||
|
||||
m_model->appendRow(rowItems);
|
||||
++row;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList NuclideRayListDialog::getRayData(const QString &id)
|
||||
{
|
||||
for (const auto& item : m_listRay) {
|
||||
if (item.at(0) == id)
|
||||
return item;
|
||||
}
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
void NuclideRayListDialog::onAddRayClicked()
|
||||
{
|
||||
NuclideRayDialog dlg(false, {}, this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
QStringList data = dlg.getRayData();
|
||||
if (data.size() < 7) return;
|
||||
|
||||
QMap<QString, QVariant> fieldValues;
|
||||
fieldValues["NUCLIDE_ID"] = m_nuclideId.toInt();
|
||||
fieldValues["RAY_TYPE"] = data[0];
|
||||
fieldValues["RAY_MEV"] = data[1];
|
||||
fieldValues["RAY_MEV_UNCERTAINTY"] = data[2];
|
||||
fieldValues["RAY_BRANCH_RATIO"] = data[3];
|
||||
fieldValues["RAY_BRANCH_RATIO_UNCERTAINTY"] = data[4];
|
||||
fieldValues["MAIN_RAY_IDENT"] = data[5];
|
||||
fieldValues["JIAHE_PEAK"] = data[6];
|
||||
fieldValues["CREATE_TIME"] = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
qint64 newId = SqliteManager::instance().insertRow("nuclideRayInfo", fieldValues);
|
||||
if (newId > 0) {
|
||||
QMessageBox::information(this, "成功", "射线信息添加成功!");
|
||||
loadRayData(); // 刷新列表
|
||||
} else {
|
||||
QMessageBox::warning(this, "失败", "添加失败:" + SqliteManager::instance().lastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NuclideRayListDialog::onEditRayClicked(const QModelIndex &index)
|
||||
{
|
||||
int row = index.row();
|
||||
QString id = m_model->index(row, 0).data().toString();
|
||||
QStringList data = getRayData(id);
|
||||
if (data.isEmpty()) return;
|
||||
|
||||
NuclideRayDialog dlg(true, data, this);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
QStringList newData = dlg.getRayData();
|
||||
if (newData.size() < 8) return;
|
||||
|
||||
QMap<QString, QVariant> fieldValues;
|
||||
fieldValues["RAY_TYPE"] = newData[1];
|
||||
fieldValues["RAY_MEV"] = newData[2];
|
||||
fieldValues["RAY_MEV_UNCERTAINTY"] = newData[3];
|
||||
fieldValues["RAY_BRANCH_RATIO"] = newData[4];
|
||||
fieldValues["RAY_BRANCH_RATIO_UNCERTAINTY"] = newData[5];
|
||||
fieldValues["MAIN_RAY_IDENT"] = newData[6];
|
||||
fieldValues["JIAHE_PEAK"] = newData[7];
|
||||
|
||||
int affectedRows = SqliteManager::instance().updateRow(
|
||||
"nuclideRayInfo",
|
||||
fieldValues,
|
||||
"ID = ?",
|
||||
{newData[0]}
|
||||
);
|
||||
|
||||
if (affectedRows > 0) {
|
||||
QMessageBox::information(this, "成功", "射线信息修改成功!");
|
||||
loadRayData();
|
||||
} else if (affectedRows == 0) {
|
||||
QMessageBox::information(this, "提示", "未修改任何数据!");
|
||||
} else {
|
||||
QMessageBox::warning(this, "失败", "修改失败:" + SqliteManager::instance().lastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NuclideRayListDialog::onDeleteRayClicked(const QModelIndex &index)
|
||||
{
|
||||
int row = index.row();
|
||||
QString id = m_model->index(row, 0).data().toString();
|
||||
|
||||
QMessageBox box(QMessageBox::Question, "提示", "确定删除该射线信息吗?",
|
||||
QMessageBox::Yes | QMessageBox::No, this);
|
||||
box.button(QMessageBox::Yes)->setText("确认");
|
||||
box.button(QMessageBox::No)->setText("取消");
|
||||
if (box.exec() != QMessageBox::Yes) return;
|
||||
|
||||
bool ok = SqliteManager::instance().deleteRow("nuclideRayInfo", "ID = ?", {id});
|
||||
if (ok) {
|
||||
loadRayData();
|
||||
} else {
|
||||
QMessageBox::warning(this, "错误", "删除失败:" + SqliteManager::instance().lastError());
|
||||
}
|
||||
}
|
||||
57
src/NuclideLib/NuclideRayListDialog.h
Normal file
57
src/NuclideLib/NuclideRayListDialog.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef NUCLIDERAYLISTDIALOG_H
|
||||
#define NUCLIDERAYLISTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QStandardItemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QMessageBox>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionButton>
|
||||
#include <QMouseEvent>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include "sqlitemanager.h"
|
||||
#include "NuclideRayDialog.h"
|
||||
|
||||
// 射线列表操作按钮委托
|
||||
class RayButtonDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit RayButtonDelegate(QObject *parent = nullptr);
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
|
||||
signals:
|
||||
void editButtonClicked(const QModelIndex &index) const;
|
||||
void deleteButtonClicked(const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
class NuclideRayListDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NuclideRayListDialog(const QString& nuclideId, const QString& nuclideName, QWidget *parent = nullptr);
|
||||
~NuclideRayListDialog() = default;
|
||||
|
||||
private slots:
|
||||
void onAddRayClicked(); // 添加射线
|
||||
void onEditRayClicked(const QModelIndex &index); // 编辑射线
|
||||
void onDeleteRayClicked(const QModelIndex &index); // 删除射线
|
||||
|
||||
private:
|
||||
void initUI(); // 初始化界面
|
||||
void loadRayData(); // 加载当前核素的射线数据
|
||||
QStringList getRayData(const QString &id); // 获取指定ID的射线数据
|
||||
|
||||
QString m_nuclideId; // 当前核素ID
|
||||
QString m_nuclideName; // 当前核素名称
|
||||
QStandardItemModel *m_model; // 射线列表模型
|
||||
RayButtonDelegate *m_delegate;// 按钮委托
|
||||
QVector<QStringList> m_listRay; // 缓存射线数据
|
||||
};
|
||||
|
||||
#endif // NUCLIDERAYLISTDIALOG_H
|
||||
|
|
@ -30,7 +30,9 @@ void ConformityAnalysis::SetAnalyzeDataFilename(const QMap<QString, QVariant> &d
|
|||
{
|
||||
QStringList ch_count_data_name = data_files_set.keys();
|
||||
int conformCount = ui->comboBox->currentIndex() + 2;
|
||||
for (const QString& ch_count_data_name : ch_count_data_name) {
|
||||
|
||||
for (const QString& ch_count_data_name : ch_count_data_name)
|
||||
{
|
||||
if(conformCount == ch_count_data_name.toInt())
|
||||
{
|
||||
setCsvFile(data_files_set[ch_count_data_name].toString());
|
||||
|
|
@ -96,6 +98,8 @@ void ConformityAnalysis::slot_ClickedBoard(int board,int channel)
|
|||
ui->widget->setWidgetData(board,channel,m_boardChannel[board - 1][channel - 1],data.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConformityAnalysis::handleBoard()
|
||||
{
|
||||
for(auto spetruData:_spectrumDataList)
|
||||
|
|
|
|||
|
|
@ -6,15 +6,17 @@
|
|||
#include "ParticleDataStatistics.h"
|
||||
#include "ThreeDDisplay.h"
|
||||
#include "csv.h"
|
||||
#include "CoincidenceSpectrumProcess.h"
|
||||
#include "MeasureAnalysisView.h"
|
||||
#include <QVector>
|
||||
using namespace CoincidenceSpectrum;
|
||||
|
||||
//using namespace CoincidenceSpectrum;
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class ConformityAnalysis;
|
||||
}
|
||||
|
||||
|
||||
typedef struct particleCoincidenceEvent
|
||||
{
|
||||
int eventId;//事件ID
|
||||
|
|
@ -24,6 +26,13 @@ typedef struct particleCoincidenceEvent
|
|||
qulonglong timeCounter;//时间计数
|
||||
}PARTICLECOINCIDENCEEVENT;
|
||||
|
||||
//// 用于存储三维数据
|
||||
//typedef struct SurfacePoint {
|
||||
// float primaryEnergy; // 初级粒子能量
|
||||
// float secondaryEnergySum; // 次级粒子能量和
|
||||
// int count; // 符合事件计数
|
||||
//}SURFACEPOINT;
|
||||
|
||||
class ConformityAnalysis : public MeasureAnalysisView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -50,7 +59,6 @@ public:
|
|||
private slots:
|
||||
void slot_InitialState();
|
||||
void slot_ClickedBoard(int board,int channel);
|
||||
|
||||
private:
|
||||
//处理板卡信息
|
||||
void handleBoard();
|
||||
|
|
@ -76,7 +84,7 @@ private:
|
|||
|
||||
QString m_fileName;
|
||||
|
||||
std::vector<F2t9Order::CoincidenceEvent> m_CoincidenceEventVector;//所有的能谱符合处理
|
||||
// std::vector<F2t9Order::CoincidenceEvent> m_CoincidenceEventVector;//所有的能谱符合处理
|
||||
|
||||
int m_boardChannel[MAX_BOARD][MAX_CHANNEL];
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,35 @@
|
|||
|
||||
#include <QWidget>
|
||||
#include "DetectorStatusSummary.h"
|
||||
#include "CoincidenceSpectrumProcess.h"
|
||||
//#include "CoincidenceSpectrumProcess.h"
|
||||
#include <QMap>
|
||||
using namespace CoincidenceSpectrum;
|
||||
//using namespace CoincidenceSpectrum;
|
||||
|
||||
namespace Ui {
|
||||
class ParticleDataStatistics;
|
||||
}
|
||||
|
||||
// 二次符合事件处理
|
||||
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; // 使用的时间窗口(秒)
|
||||
};
|
||||
}
|
||||
// 定义板卡和通道的最大数量
|
||||
static constexpr int MAX_BOARD = 8;
|
||||
static constexpr int MAX_CHANNEL = 4;
|
||||
class ParticleDataStatistics : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
#include <QtDataVisualization>
|
||||
#include <QLabel>
|
||||
|
||||
#include "CoincidenceSpectrumProcess.h"
|
||||
//#include "CoincidenceSpectrumProcess.h"
|
||||
using namespace QtDataVisualization;
|
||||
|
||||
//// 用于存储三维数据
|
||||
//typedef struct SurfacePoint {
|
||||
// float primaryEnergy; // 初级粒子能量
|
||||
// float secondaryEnergySum; // 次级粒子能量和
|
||||
// int count; // 符合事件计数
|
||||
//}SURFACEPOINT;
|
||||
// 用于存储三维数据
|
||||
typedef struct SurfacePoint {
|
||||
float primaryEnergy; // 初级粒子能量
|
||||
float secondaryEnergySum; // 次级粒子能量和
|
||||
int count; // 符合事件计数
|
||||
}SURFACEPOINT;
|
||||
|
||||
namespace Ui {
|
||||
class ThreeDDisplay;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@ SOURCES += \
|
|||
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.cpp \
|
||||
MeasureDeviceParamsConfigView/DeviceParamsTableForm.cpp \
|
||||
MeasureDeviceParamsConfigView/MeasureDeviceParamsConfigView.cpp \
|
||||
NuclideLib/NuclideEditDialog.cpp \
|
||||
NuclideLib/NuclideRayDialog.cpp \
|
||||
NuclideLib/NuclideRayListDialog.cpp \
|
||||
NuclideLib/sqlitemanager.cpp \
|
||||
ParticleCountPlotView/BatchEnergyScaleDialog.cpp \
|
||||
ParticleCountPlotView/FindPeaksResultDialog.cpp \
|
||||
|
|
@ -132,6 +135,9 @@ HEADERS += \
|
|||
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.h \
|
||||
MeasureDeviceParamsConfigView/DeviceParamsTableForm.h \
|
||||
MeasureDeviceParamsConfigView/MeasureDeviceParamsConfigView.h \
|
||||
NuclideLib/NuclideEditDialog.h \
|
||||
NuclideLib/NuclideRayDialog.h \
|
||||
NuclideLib/NuclideRayListDialog.h \
|
||||
NuclideLib/sqlitemanager.h \
|
||||
ParticleCountPlotView/BatchEnergyScaleDialog.h \
|
||||
ParticleCountPlotView/FindPeaksResultDialog.h \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user