修改以下 峰拟合框线条粗细变化问题,峰拟合结果对话框中的表头适应内容;峰拟合当前选择的峰拟合结果的峰信息着重显示黑色、未选中的峰信息显示暗淡灰色;删除锋拟合结果后剩下的峰拟合结果项会自动勾选;峰拟合图表中的本地曲线的颜色使用暗黄色,核素库删除核素,其相关的射线记录未删除;核素库管理对话框名称修改为“核素库";核素库添加成功时,先将数据添加到数据库中,在界面显示,再弹出添加成功对话框,核素库半衰期的参数输入应支持”年、月、日、时、分、秒“的单位;修改符合二维符合能谱只加载两个粒子的数据
This commit is contained in:
parent
20ea8ad131
commit
0f0a46c5f7
Binary file not shown.
|
|
@ -23,7 +23,10 @@
|
||||||
#include <QwtText>
|
#include <QwtText>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <qwt_matrix_raster_data.h>
|
#include <qwt_matrix_raster_data.h>
|
||||||
|
#include "csv.h"
|
||||||
|
#include <GlobalDefine.h>
|
||||||
|
|
||||||
class HeatMapColorMap : public QwtLinearColorMap {
|
class HeatMapColorMap : public QwtLinearColorMap {
|
||||||
public:
|
public:
|
||||||
|
|
@ -65,12 +68,18 @@ void TwoDSpectralCompliance::SetAnalyzeDataFilename(const QMap<QString, QVariant
|
||||||
{
|
{
|
||||||
if (data_files_set.isEmpty())
|
if (data_files_set.isEmpty())
|
||||||
return;
|
return;
|
||||||
QString csvFile = data_files_set.first().toString();
|
QStringList _data_filenames;
|
||||||
if (csvFile.isEmpty())
|
|
||||||
return;
|
for (const QVariant& file_value : data_files_set) {
|
||||||
|
QString filename = file_value.toString();
|
||||||
|
if (!filename.isEmpty() && QFileInfo(filename).exists()) {
|
||||||
|
_data_filenames.append(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_busy_indicator->Start();
|
_busy_indicator->Start();
|
||||||
auto functionToRun = [this, csvFile]() {
|
auto functionToRun = [this, _data_filenames]() {
|
||||||
readCsv(csvFile);
|
readCsv(_data_filenames);
|
||||||
generateSurfaceData();
|
generateSurfaceData();
|
||||||
QMetaObject::invokeMethod(this, [this]() {
|
QMetaObject::invokeMethod(this, [this]() {
|
||||||
updateSpectrogram();
|
updateSpectrogram();
|
||||||
|
|
@ -115,37 +124,35 @@ void TwoDSpectralCompliance::setupPlot()
|
||||||
_spectrogram->attach(_plot);
|
_spectrogram->attach(_plot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwoDSpectralCompliance::readCsv(const QString& filename)
|
void TwoDSpectralCompliance::readCsv(const QStringList& filename)
|
||||||
{
|
{
|
||||||
m_rawData.clear();
|
if (filename.isEmpty()) {
|
||||||
QFile file(filename);
|
QMetaObject::invokeMethod(this, [this]() {
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
_busy_indicator->Stop();
|
||||||
qWarning() << QStringLiteral(u"无法打开文件:") << filename;
|
}, Qt::QueuedConnection);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
for (const QString& filename : filename) {
|
||||||
QTextStream stream(&file);
|
io::CSVReader<5> in(QStrToSysPath(filename));
|
||||||
QString header = stream.readLine();
|
in.read_header(io::ignore_extra_column,
|
||||||
Q_UNUSED(header);
|
QString(QStringLiteral(u"事件ID")).toStdString(),
|
||||||
|
QString(QStringLiteral(u"板卡号")).toStdString(),
|
||||||
while (!stream.atEnd()) {
|
QString(QStringLiteral(u"通道号")).toStdString(),
|
||||||
QString line = stream.readLine();
|
QString(QStringLiteral(u"能量(KeV)")).toStdString(),
|
||||||
if (line.isEmpty())
|
QString(QStringLiteral(u"时间计数")).toStdString());
|
||||||
continue;
|
int eventId,board, channel;
|
||||||
|
double energy;
|
||||||
QStringList fields = line.split(',');
|
unsigned long long time_count;
|
||||||
if (fields.size() < 5)
|
while (in.read_row(eventId,board, channel, energy, time_count)) {
|
||||||
continue;
|
EventData sd;
|
||||||
|
sd.eventId = eventId;
|
||||||
EventData data;
|
sd.board = board;
|
||||||
data.eventId = fields[0].toInt();
|
sd.channel = channel;
|
||||||
data.board = fields[1].toInt();
|
sd.energy = energy;
|
||||||
data.channel = fields[2].toInt();
|
sd.timeCounter = time_count;
|
||||||
data.energy = fields[3].toDouble();
|
m_rawData.push_back(sd);
|
||||||
data.timeCounter = fields[4].toULongLong();
|
}
|
||||||
m_rawData.append(data);
|
|
||||||
}
|
}
|
||||||
file.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwoDSpectralCompliance::generateSurfaceData()
|
void TwoDSpectralCompliance::generateSurfaceData()
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupPlot();
|
void setupPlot();
|
||||||
void readCsv(const QString& filename);
|
void readCsv(const QStringList& filename);
|
||||||
void generateSurfaceData();
|
void generateSurfaceData();
|
||||||
void updateSpectrogram();
|
void updateSpectrogram();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include "PlotRectItem.h"
|
#include "PlotRectItem.h"
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QDebug>
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
|
|
@ -223,7 +222,7 @@ void EnergyCountPeakFitView::setupPlot()
|
||||||
dummyFit->attach(_plot);
|
dummyFit->attach(_plot);
|
||||||
|
|
||||||
QwtPlotCurve *dummyBg = new QwtPlotCurve(QStringLiteral(u"本底数据"));
|
QwtPlotCurve *dummyBg = new QwtPlotCurve(QStringLiteral(u"本底数据"));
|
||||||
dummyBg->setPen(QPen(Qt::yellow, 2));
|
dummyBg->setPen(QPen(QColor("#C9A84C"), 2));
|
||||||
dummyBg->setSamples(QVector<double>(), QVector<double>());
|
dummyBg->setSamples(QVector<double>(), QVector<double>());
|
||||||
dummyBg->setVisible(false);
|
dummyBg->setVisible(false);
|
||||||
dummyBg->attach(_plot);
|
dummyBg->attach(_plot);
|
||||||
|
|
@ -551,7 +550,7 @@ void EnergyCountPeakFitView::fadeSelectionRectBorders()
|
||||||
{
|
{
|
||||||
for (PlotRectItem* item : _selectionRectItems) {
|
for (PlotRectItem* item : _selectionRectItems) {
|
||||||
if (item) {
|
if (item) {
|
||||||
QPen fadedPen(Qt::red, 1, Qt::DashLine);
|
QPen fadedPen(Qt::red, 2, Qt::DashLine);
|
||||||
item->setPen(fadedPen);
|
item->setPen(fadedPen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -593,12 +592,12 @@ QList<PeakFitResult> EnergyCountPeakFitView::performPeakFitting(const QVector<do
|
||||||
FitParams userParams = paramDlg.getParams();
|
FitParams userParams = paramDlg.getParams();
|
||||||
|
|
||||||
AdaptiveSimpsonIntegrate::FitFunction fitFunc;
|
AdaptiveSimpsonIntegrate::FitFunction fitFunc;
|
||||||
fitFunc.A = userParams.A ;//p_fit(0);
|
fitFunc.A = userParams.A ;
|
||||||
fitFunc.delt= userParams.delt;//p_fit(1);
|
fitFunc.delt= userParams.delt;
|
||||||
fitFunc.H = userParams.H ;//p_fit(2);
|
fitFunc.H = userParams.H ;
|
||||||
fitFunc.W = userParams.W ;//p_fit(3);
|
fitFunc.W = userParams.W ;
|
||||||
fitFunc.C = userParams.C ;//p_fit(4);
|
fitFunc.C = userParams.C ;
|
||||||
fitFunc.P = userParams.P ;//p_fit(5);
|
fitFunc.P = userParams.P ;
|
||||||
double lower = fitFunc.P - 3.0 * fitFunc.delt;
|
double lower = fitFunc.P - 3.0 * fitFunc.delt;
|
||||||
double upper = fitFunc.P + 3.0 * fitFunc.delt;
|
double upper = fitFunc.P + 3.0 * fitFunc.delt;
|
||||||
double area = AdaptiveSimpsonIntegrate::integrate(fitFunc, lower, upper);
|
double area = AdaptiveSimpsonIntegrate::integrate(fitFunc, lower, upper);
|
||||||
|
|
@ -670,7 +669,7 @@ QList<QwtPlotCurve *> EnergyCountPeakFitView::createFitCurve(const PeakFitResult
|
||||||
curveList.append(curve);
|
curveList.append(curve);
|
||||||
|
|
||||||
QwtPlotCurve* curveTw = new QwtPlotCurve(QStringLiteral(u"本底数据"));
|
QwtPlotCurve* curveTw = new QwtPlotCurve(QStringLiteral(u"本底数据"));
|
||||||
curveTw->setPen(QPen(Qt::yellow, 2));
|
curveTw->setPen(QPen(QColor("#C9A84C"), 2));
|
||||||
curveTw->setSamples(xs, ysTw);
|
curveTw->setSamples(xs, ysTw);
|
||||||
curveTw->setItemAttribute(QwtPlotItem::Legend, false);
|
curveTw->setItemAttribute(QwtPlotItem::Legend, false);
|
||||||
curveTw->attach(_plot);
|
curveTw->attach(_plot);
|
||||||
|
|
@ -679,6 +678,64 @@ QList<QwtPlotCurve *> EnergyCountPeakFitView::createFitCurve(const PeakFitResult
|
||||||
return curveList;
|
return curveList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnergyCountPeakFitView::updateHistoryDialogWithSelection(const QList<DisplayedCurveRef> &selectedRefs)
|
||||||
|
{
|
||||||
|
if (!_historyDlg) return;
|
||||||
|
|
||||||
|
QTableView* tableView = _historyDlg->findChild<QTableView*>("historyTableView");
|
||||||
|
QStandardItemModel* model = qobject_cast<QStandardItemModel*>(tableView ? tableView->model() : nullptr);
|
||||||
|
if (!model) return;
|
||||||
|
|
||||||
|
// 将选中的引用转换为集合,方便快速查找
|
||||||
|
QSet<QPair<int, int>> selectedSet;
|
||||||
|
for (const auto& ref : selectedRefs) {
|
||||||
|
selectedSet.insert(qMakePair(ref.historyIndex, ref.curveIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新构建表格
|
||||||
|
model->clear();
|
||||||
|
QStringList headers;
|
||||||
|
headers << "序号" << "振幅(A)" << "高斯宽度(delt)" << "Sigmoid幅度(H)" << "Sigmoid宽度(W)" << "基线(C)";
|
||||||
|
model->setHorizontalHeaderLabels(headers);
|
||||||
|
|
||||||
|
QVector<QPair<int, int>> newRowMap;
|
||||||
|
model->blockSignals(true);
|
||||||
|
int rowNumber = 1;
|
||||||
|
|
||||||
|
for (int historyIdx = 0; historyIdx < _fitHistoryList.size(); ++historyIdx) {
|
||||||
|
const auto& historyItem = _fitHistoryList[historyIdx];
|
||||||
|
for (int curveIdx = 0; curveIdx < historyItem.curveList.size(); ++curveIdx) {
|
||||||
|
const auto& curve = historyItem.curveList[curveIdx];
|
||||||
|
QList<QStandardItem*> rowItems;
|
||||||
|
|
||||||
|
QStandardItem* checkItem = new QStandardItem(QString::number(rowNumber++));
|
||||||
|
checkItem->setCheckable(true);
|
||||||
|
checkItem->setEditable(false);
|
||||||
|
checkItem->setCheckState(selectedSet.contains(qMakePair(historyIdx, curveIdx))
|
||||||
|
? Qt::Checked : Qt::Unchecked);
|
||||||
|
rowItems.append(checkItem);
|
||||||
|
|
||||||
|
rowItems.append(new QStandardItem(QString::number(curve.amplitude, 'f', 4)));
|
||||||
|
rowItems.append(new QStandardItem(QString::number(curve.sigma, 'f', 4)));
|
||||||
|
rowItems.append(new QStandardItem(QString::number(curve.sigmoidH, 'f', 4)));
|
||||||
|
rowItems.append(new QStandardItem(QString::number(curve.sigmoidW, 'f', 4)));
|
||||||
|
rowItems.append(new QStandardItem(QString::number(curve.baseline, 'f', 4)));
|
||||||
|
|
||||||
|
model->appendRow(rowItems);
|
||||||
|
newRowMap.append(qMakePair(historyIdx, curveIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model->blockSignals(false);
|
||||||
|
_historyDlg->setProperty("rowToDataIndices", QVariant::fromValue(newRowMap));
|
||||||
|
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
|
tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||||
|
tableView->horizontalHeader()->resizeSection(0, 70);
|
||||||
|
tableView->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
tableView->viewport()->update();
|
||||||
|
LOG_DEBUG(QStringLiteral(u"历史对话框已更新"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EnergyCountPeakFitView::clearFitCurves()
|
void EnergyCountPeakFitView::clearFitCurves()
|
||||||
{
|
{
|
||||||
|
|
@ -776,17 +833,18 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasCurveData) {
|
//空表时直接打开
|
||||||
QMessageBox* msgBox = new QMessageBox(this);
|
// if (!hasCurveData) {
|
||||||
msgBox->setWindowTitle(QStringLiteral(u"峰拟合结果"));
|
// QMessageBox* msgBox = new QMessageBox(this);
|
||||||
msgBox->setText(QStringLiteral(u"暂无历史拟合数据,请先进行拟合并保存。"));
|
// msgBox->setWindowTitle(QStringLiteral(u"峰拟合结果"));
|
||||||
msgBox->setStandardButtons(QMessageBox::Ok);
|
// msgBox->setText(QStringLiteral(u"暂无历史拟合数据,请先进行拟合并保存。"));
|
||||||
msgBox->setModal(false);
|
// msgBox->setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
// msgBox->setModal(false);
|
||||||
msgBox->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
|
// msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
msgBox->show();
|
// msgBox->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
|
||||||
return;
|
// msgBox->show();
|
||||||
}
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
if (_historyDlg) {
|
if (_historyDlg) {
|
||||||
_historyDlg->raise();
|
_historyDlg->raise();
|
||||||
|
|
@ -852,9 +910,15 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||||
tableView->horizontalHeader()->setStretchLastSection(true);
|
|
||||||
tableView->verticalHeader()->setVisible(false);
|
tableView->verticalHeader()->setVisible(false);
|
||||||
|
|
||||||
|
// 关键:先设置所有列为拉伸模式
|
||||||
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
|
// 再单独将序号列(第0列)设置为固定宽度
|
||||||
|
tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||||
|
tableView->horizontalHeader()->resizeSection(0, 70);
|
||||||
|
// 最后设置最后一列拉伸
|
||||||
|
tableView->horizontalHeader()->setStretchLastSection(true);
|
||||||
layout->addWidget(tableView);
|
layout->addWidget(tableView);
|
||||||
|
|
||||||
QPushButton* btnDelete = new QPushButton(QStringLiteral(u"删除选中记录"), _historyDlg);
|
QPushButton* btnDelete = new QPushButton(QStringLiteral(u"删除选中记录"), _historyDlg);
|
||||||
|
|
@ -1015,8 +1079,10 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
saveHistoryToFile();
|
saveHistoryToFile();
|
||||||
|
if (_historyDlg) {
|
||||||
emit newFitResultAdded();
|
updateHistoryDialogWithSelection(remainingRefs);
|
||||||
|
}
|
||||||
|
// emit newFitResultAdded();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
confirmBox->show();
|
confirmBox->show();
|
||||||
|
|
@ -1028,6 +1094,71 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
|
|
||||||
void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
||||||
{
|
{
|
||||||
|
// if (!_hoveredRectItem) {
|
||||||
|
// QMessageBox::information(this, QStringLiteral(u"提示"),
|
||||||
|
// QStringLiteral(u"请先将鼠标移动到要删除的框选区域上(区域边框会变为实线),然后再点击此菜单。"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// QString rectType = _hoveredRectItem->selectionType();
|
||||||
|
// int historyIndex = _hoveredRectItem->selectionIndex();
|
||||||
|
|
||||||
|
// int curveStartIdx = historyIndex * 2;
|
||||||
|
// if (curveStartIdx + 1 < _fitCurves.size()) {
|
||||||
|
// _fitCurves[curveStartIdx + 1]->detach();
|
||||||
|
// delete _fitCurves[curveStartIdx + 1];
|
||||||
|
// _fitCurves.removeAt(curveStartIdx + 1);
|
||||||
|
// _fitCurves[curveStartIdx]->detach();
|
||||||
|
// delete _fitCurves[curveStartIdx];
|
||||||
|
// _fitCurves.removeAt(curveStartIdx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _hoveredRectItem->detach();
|
||||||
|
// delete _hoveredRectItem;
|
||||||
|
// for (auto it = _selectionRectItems.begin(); it != _selectionRectItems.end();) {
|
||||||
|
// if (*it && (*it)->selectionIndex() == historyIndex) {
|
||||||
|
// it = _selectionRectItems.erase(it);
|
||||||
|
// } else {
|
||||||
|
// ++it;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// _hoveredRectItem = nullptr;
|
||||||
|
|
||||||
|
// if (historyIndex >= 0 && historyIndex < _fitHistoryList.size()) {
|
||||||
|
// _fitHistoryList.removeAt(historyIndex);
|
||||||
|
// saveHistoryToFile();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (auto& ref : _displayedHistoryCurves) {
|
||||||
|
// if (ref.historyIndex > historyIndex) {
|
||||||
|
// ref.historyIndex--;
|
||||||
|
// ref.rectIndex = ref.historyIndex;
|
||||||
|
// ref.curveStartIndex = ref.rectIndex * 2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (auto it = _displayedHistoryCurves.begin(); it != _displayedHistoryCurves.end();) {
|
||||||
|
// if (it->historyIndex == historyIndex) {
|
||||||
|
// it = _displayedHistoryCurves.erase(it);
|
||||||
|
// } else {
|
||||||
|
// ++it;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (PlotRectItem* item : _selectionRectItems) {
|
||||||
|
// if (item && item->selectionIndex() > historyIndex) {
|
||||||
|
// item->setSelectionIndex(item->selectionIndex() - 1);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (auto& record : _currentFitRecords) {
|
||||||
|
// if (record.historyIndex > historyIndex) {
|
||||||
|
// record.historyIndex--;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _plot->replot();
|
||||||
|
|
||||||
|
|
||||||
|
// emit newFitResultAdded();
|
||||||
if (!_hoveredRectItem) {
|
if (!_hoveredRectItem) {
|
||||||
QMessageBox::information(this, QStringLiteral(u"提示"),
|
QMessageBox::information(this, QStringLiteral(u"提示"),
|
||||||
QStringLiteral(u"请先将鼠标移动到要删除的框选区域上(区域边框会变为实线),然后再点击此菜单。"));
|
QStringLiteral(u"请先将鼠标移动到要删除的框选区域上(区域边框会变为实线),然后再点击此菜单。"));
|
||||||
|
|
@ -1035,7 +1166,6 @@ void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
||||||
}
|
}
|
||||||
QString rectType = _hoveredRectItem->selectionType();
|
QString rectType = _hoveredRectItem->selectionType();
|
||||||
int historyIndex = _hoveredRectItem->selectionIndex();
|
int historyIndex = _hoveredRectItem->selectionIndex();
|
||||||
|
|
||||||
int curveStartIdx = historyIndex * 2;
|
int curveStartIdx = historyIndex * 2;
|
||||||
if (curveStartIdx + 1 < _fitCurves.size()) {
|
if (curveStartIdx + 1 < _fitCurves.size()) {
|
||||||
_fitCurves[curveStartIdx + 1]->detach();
|
_fitCurves[curveStartIdx + 1]->detach();
|
||||||
|
|
@ -1045,7 +1175,6 @@ void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
||||||
delete _fitCurves[curveStartIdx];
|
delete _fitCurves[curveStartIdx];
|
||||||
_fitCurves.removeAt(curveStartIdx);
|
_fitCurves.removeAt(curveStartIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
_hoveredRectItem->detach();
|
_hoveredRectItem->detach();
|
||||||
delete _hoveredRectItem;
|
delete _hoveredRectItem;
|
||||||
for (auto it = _selectionRectItems.begin(); it != _selectionRectItems.end();) {
|
for (auto it = _selectionRectItems.begin(); it != _selectionRectItems.end();) {
|
||||||
|
|
@ -1056,41 +1185,52 @@ void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_hoveredRectItem = nullptr;
|
_hoveredRectItem = nullptr;
|
||||||
|
|
||||||
if (historyIndex >= 0 && historyIndex < _fitHistoryList.size()) {
|
if (historyIndex >= 0 && historyIndex < _fitHistoryList.size()) {
|
||||||
_fitHistoryList.removeAt(historyIndex);
|
_fitHistoryList.removeAt(historyIndex);
|
||||||
saveHistoryToFile();
|
saveHistoryToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<DisplayedCurveRef> remainingRefs;
|
||||||
for (auto& ref : _displayedHistoryCurves) {
|
for (auto& ref : _displayedHistoryCurves) {
|
||||||
|
if (ref.historyIndex == historyIndex) {
|
||||||
|
continue; // 跳过要删除的记录
|
||||||
|
}
|
||||||
if (ref.historyIndex > historyIndex) {
|
if (ref.historyIndex > historyIndex) {
|
||||||
ref.historyIndex--;
|
ref.historyIndex--;
|
||||||
ref.rectIndex = ref.historyIndex;
|
ref.rectIndex = ref.historyIndex;
|
||||||
ref.curveStartIndex = ref.rectIndex * 2;
|
ref.curveStartIndex = ref.rectIndex * 2;
|
||||||
}
|
}
|
||||||
|
remainingRefs.append(ref);
|
||||||
}
|
}
|
||||||
for (auto it = _displayedHistoryCurves.begin(); it != _displayedHistoryCurves.end();) {
|
|
||||||
if (it->historyIndex == historyIndex) {
|
_displayedHistoryCurves = remainingRefs;
|
||||||
it = _displayedHistoryCurves.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PlotRectItem* item : _selectionRectItems) {
|
for (PlotRectItem* item : _selectionRectItems) {
|
||||||
if (item && item->selectionIndex() > historyIndex) {
|
if (item && item->selectionIndex() > historyIndex) {
|
||||||
item->setSelectionIndex(item->selectionIndex() - 1);
|
item->setSelectionIndex(item->selectionIndex() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& record : _currentFitRecords) {
|
for (auto& record : _currentFitRecords) {
|
||||||
if (record.historyIndex > historyIndex) {
|
if (record.historyIndex > historyIndex) {
|
||||||
record.historyIndex--;
|
record.historyIndex--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearFitCurves();
|
||||||
|
clearAllSelectionRects();
|
||||||
|
if (!remainingRefs.isEmpty()) {
|
||||||
|
QList<FitCurveData> remainingCurves;
|
||||||
|
for (const auto& ref : remainingRefs) {
|
||||||
|
remainingCurves.append(_fitHistoryList[ref.historyIndex].curveList[ref.curveIndex]);
|
||||||
|
}
|
||||||
|
displaySelectedCurves(remainingCurves, remainingRefs);
|
||||||
|
} else {
|
||||||
_plot->replot();
|
_plot->replot();
|
||||||
emit newFitResultAdded();
|
}
|
||||||
|
|
||||||
|
if (_historyDlg) {
|
||||||
|
updateHistoryDialogWithSelection(remainingRefs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnergyCountPeakFitView::onActionRefitCurrentRect()
|
void EnergyCountPeakFitView::onActionRefitCurrentRect()
|
||||||
|
|
@ -1300,7 +1440,7 @@ void EnergyCountPeakFitView::displaySelectedCurves(const QList<FitCurveData> &cu
|
||||||
for (int j = 0; j < yTw.size(); ++j) ysTw.append(yTw(j));
|
for (int j = 0; j < yTw.size(); ++j) ysTw.append(yTw(j));
|
||||||
|
|
||||||
QwtPlotCurve* bgCurve = new QwtPlotCurve(QStringLiteral(u"历史本底数据"));
|
QwtPlotCurve* bgCurve = new QwtPlotCurve(QStringLiteral(u"历史本底数据"));
|
||||||
bgCurve->setPen(QPen(Qt::yellow, 2, Qt::DashLine));
|
bgCurve->setPen(QPen(QColor("#C9A84C"), 2, Qt::DashLine));
|
||||||
bgCurve->setSamples(xs, ysTw);
|
bgCurve->setSamples(xs, ysTw);
|
||||||
bgCurve->setItemAttribute(QwtPlotItem::Legend, false);
|
bgCurve->setItemAttribute(QwtPlotItem::Legend, false);
|
||||||
bgCurve->attach(_plot);
|
bgCurve->attach(_plot);
|
||||||
|
|
@ -1423,7 +1563,10 @@ void EnergyCountPeakFitView::onNewFitResultAdded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
displaySelectedCurves(selectedCurves, selectedRefs);
|
displaySelectedCurves(selectedCurves, selectedRefs);
|
||||||
|
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
|
tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||||
|
tableView->horizontalHeader()->resizeSection(0, 70);
|
||||||
|
tableView->horizontalHeader()->setStretchLastSection(true);
|
||||||
tableView->viewport()->update();
|
tableView->viewport()->update();
|
||||||
LOG_DEBUG(QStringLiteral(u"历史对话框已同步刷新"));
|
LOG_DEBUG(QStringLiteral(u"历史对话框已同步刷新"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,8 @@ private:
|
||||||
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*/);
|
||||||
// 根据拟合参数生成曲线
|
// 根据拟合参数生成曲线
|
||||||
QList<QwtPlotCurve*> createFitCurve(const PeakFitResult& result, arma::vec xVec);
|
QList<QwtPlotCurve*> createFitCurve(const PeakFitResult& result, arma::vec xVec);
|
||||||
|
// 更新历史对话框并保持指定的选中状态
|
||||||
|
void updateHistoryDialogWithSelection(const QList<DisplayedCurveRef>& selectedRefs);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void newFitResultAdded();
|
void newFitResultAdded();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ PlotRectItem::PlotRectItem(const QString &title)
|
||||||
m_hoverPen = QPen(Qt::red, 2, Qt::SolidLine);
|
m_hoverPen = QPen(Qt::red, 2, Qt::SolidLine);
|
||||||
|
|
||||||
m_brush = QBrush(QColor(255, 0, 0, 30));
|
m_brush = QBrush(QColor(255, 0, 0, 30));
|
||||||
|
|
||||||
|
m_normalTextPen = QPen(Qt::gray); // 普通状态黑色文本
|
||||||
|
m_hoverTextPen = QPen(Qt::black); // 悬停状态高亮黑色文本
|
||||||
|
m_hoverTextPen.setWidth(1); // 稍微加粗
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlotRectItem::setRect(const QRectF &rect) {
|
void PlotRectItem::setRect(const QRectF &rect) {
|
||||||
|
|
@ -98,6 +102,10 @@ void PlotRectItem::draw(QPainter *painter,
|
||||||
// 绘制半透明背景框(增强可读性)
|
// 绘制半透明背景框(增强可读性)
|
||||||
QFont font = painter->font();
|
QFont font = painter->font();
|
||||||
font.setPointSize(9); // 稍微小一点
|
font.setPointSize(9); // 稍微小一点
|
||||||
|
// 悬停时加粗字体
|
||||||
|
// if (m_isHovered) {
|
||||||
|
// font.setBold(true);
|
||||||
|
// }
|
||||||
painter->setFont(font);
|
painter->setFont(font);
|
||||||
|
|
||||||
QFontMetrics fm(font);
|
QFontMetrics fm(font);
|
||||||
|
|
@ -105,8 +113,8 @@ void PlotRectItem::draw(QPainter *painter,
|
||||||
textRect.moveTopLeft(textPos);
|
textRect.moveTopLeft(textPos);
|
||||||
textRect.adjust(-5, -3, 5, 3); // 增加边距
|
textRect.adjust(-5, -3, 5, 3); // 增加边距
|
||||||
|
|
||||||
painter->fillRect(textRect, QColor(255, 255, 255, 220)); // 白底微透
|
painter->fillRect(textRect, QColor(255, 255, 255, 0)); // 白底微透
|
||||||
painter->setPen(Qt::black);
|
painter->setPen(m_isHovered ? m_hoverTextPen : m_normalTextPen);
|
||||||
painter->drawText(textRect, Qt::AlignLeft, text);
|
painter->drawText(textRect, Qt::AlignLeft, text);
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ private:
|
||||||
QPen m_normalPen; //普通状态画笔(虚线)
|
QPen m_normalPen; //普通状态画笔(虚线)
|
||||||
QPen m_hoverPen; //悬停状态画笔(实线)
|
QPen m_hoverPen; //悬停状态画笔(实线)
|
||||||
QBrush m_brush;
|
QBrush m_brush;
|
||||||
|
QPen m_normalTextPen; // 普通状态文本画笔
|
||||||
|
QPen m_hoverTextPen; // 悬停状态高亮文本画笔
|
||||||
bool m_isHovered; //悬停状态标志
|
bool m_isHovered; //悬停状态标志
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,6 @@ bool NuclideEditDialog::validateInput()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
// 半衰期校验(保留原逻辑,TEXT类型可存储带单位的字符串)
|
|
||||||
m_leHalfLife->text().toDouble(&ok);
|
|
||||||
if (!ok) {
|
|
||||||
QMessageBox::warning(this, "输入错误", "半衰期必须为数字(可带单位,如12.5d)!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_leHalfLifeUnc->text().toDouble(&ok);
|
m_leHalfLifeUnc->text().toDouble(&ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
QMessageBox::warning(this, "输入错误", "半衰期不确定度必须为有效数字!");
|
QMessageBox::warning(this, "输入错误", "半衰期不确定度必须为有效数字!");
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,12 @@ void ButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option
|
||||||
{
|
{
|
||||||
if (index.column() == 7) {
|
if (index.column() == 7) {
|
||||||
QStyleOptionButton button;
|
QStyleOptionButton button;
|
||||||
button.rect = option.rect;
|
const int btnWidth = 180; // 按钮宽度(可根据需要调整)
|
||||||
|
const int btnHeight = option.rect.height() - 4; // 按钮高度(上下各留2px边距)
|
||||||
|
const int x = option.rect.x() + (option.rect.width() - btnWidth) / 2; // 水平居中
|
||||||
|
const int y = option.rect.y() + 2; // 垂直居中(上下边距)
|
||||||
|
button.rect = QRect(x, y, btnWidth, btnHeight);
|
||||||
|
// button.rect = option.rect;
|
||||||
button.text = QStringLiteral(u"核素发射射线信息");
|
button.text = QStringLiteral(u"核素发射射线信息");
|
||||||
button.state = QStyle::State_Enabled;
|
button.state = QStyle::State_Enabled;
|
||||||
if (option.state & QStyle::State_MouseOver)
|
if (option.state & QStyle::State_MouseOver)
|
||||||
|
|
@ -53,7 +58,7 @@ NuclideLibManage::NuclideLibManage(QWidget *parent) :
|
||||||
ui->tableView->setColumnHidden(0, true);
|
ui->tableView->setColumnHidden(0, true);
|
||||||
|
|
||||||
ui->tableView->setColumnWidth(1, 90); // 序号
|
ui->tableView->setColumnWidth(1, 90); // 序号
|
||||||
ui->tableView->setColumnWidth(7, 280); // 操作列
|
ui->tableView->setColumnWidth(7, 180); // 操作列
|
||||||
ui->tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
|
ui->tableView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
|
||||||
ui->tableView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
|
ui->tableView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
|
||||||
ui->tableView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch);
|
ui->tableView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch);
|
||||||
|
|
@ -159,8 +164,8 @@ void NuclideLibManage::on_pushButton_add_clicked()
|
||||||
|
|
||||||
qint64 newId = SqliteManager::instance().insertRow("nuclideLib", fieldValues);
|
qint64 newId = SqliteManager::instance().insertRow("nuclideLib", fieldValues);
|
||||||
if (newId > 0) {
|
if (newId > 0) {
|
||||||
QMessageBox::information(this, QStringLiteral(u"成功"), QStringLiteral(u"核素添加成功!"));
|
|
||||||
loadNuclideData();
|
loadNuclideData();
|
||||||
|
QMessageBox::information(this, QStringLiteral(u"成功"), QStringLiteral(u"核素添加成功!"));
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this, QStringLiteral(u"失败"), QStringLiteral(u"添加失败:") + SqliteManager::instance().lastError());
|
QMessageBox::warning(this, QStringLiteral(u"失败"), QStringLiteral(u"添加失败:") + SqliteManager::instance().lastError());
|
||||||
}
|
}
|
||||||
|
|
@ -219,19 +224,50 @@ void NuclideLibManage::on_pushButton_del_clicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = selected.first().row();
|
int row = selected.first().row();
|
||||||
QString id = m_model->index(row, 0).data().toString();
|
QString nuclideId = m_model->index(row, 0).data().toString();
|
||||||
|
|
||||||
QMessageBox box(QMessageBox::Question, QStringLiteral(u"提示"), QStringLiteral(u"确定删除该核素吗?"),
|
QMessageBox box(QMessageBox::Question, QStringLiteral(u"提示"),
|
||||||
|
QStringLiteral(u"确定删除该核素及其所有关联的射线信息吗?"),
|
||||||
QMessageBox::Yes | QMessageBox::No, this);
|
QMessageBox::Yes | QMessageBox::No, this);
|
||||||
box.button(QMessageBox::Yes)->setText(QStringLiteral(u"确认"));
|
box.button(QMessageBox::Yes)->setText(QStringLiteral(u"确认"));
|
||||||
box.button(QMessageBox::No)->setText(QStringLiteral(u"取消"));
|
box.button(QMessageBox::No)->setText(QStringLiteral(u"取消"));
|
||||||
if (box.exec() != QMessageBox::Yes) return;
|
if (box.exec() != QMessageBox::Yes) return;
|
||||||
|
|
||||||
bool ok = SqliteManager::instance().deleteRow("nuclideLib", "ID = ?", {id});
|
SqliteManager& dbMgr = SqliteManager::instance();
|
||||||
if (ok) {
|
// 开始事务
|
||||||
loadNuclideData();
|
if (!dbMgr.beginTransaction()) {
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"错误"),
|
||||||
|
QStringLiteral(u"开启事务失败:") + dbMgr.lastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤1:删除该核素关联的所有射线信息
|
||||||
|
int rayDelCount = dbMgr.deleteRow("nuclideRayInfo", "NUCLIDE_ID = ?", {nuclideId.toInt()});
|
||||||
|
if (rayDelCount == -1) { // 删除射线失败
|
||||||
|
dbMgr.rollbackTransaction(); // 回滚事务
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"错误"),
|
||||||
|
QStringLiteral(u"删除关联射线信息失败:") + dbMgr.lastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤2:删除核素本身
|
||||||
|
int nuclideDelCount = dbMgr.deleteRow("nuclideLib", "ID = ?", {nuclideId});
|
||||||
|
if (nuclideDelCount == -1) { // 删除核素失败
|
||||||
|
dbMgr.rollbackTransaction(); // 回滚事务
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"错误"),
|
||||||
|
QStringLiteral(u"删除核素失败:") + dbMgr.lastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交事务(所有操作成功)
|
||||||
|
if (dbMgr.commitTransaction()) {
|
||||||
|
QMessageBox::information(this, QStringLiteral(u"成功"),
|
||||||
|
QStringLiteral(u"核素及关联的%1条射线信息已删除!").arg(rayDelCount));
|
||||||
|
loadNuclideData(); // 刷新核素列表
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this, QStringLiteral(u"错误"), QStringLiteral(u"删除失败:") + SqliteManager::instance().lastError());
|
dbMgr.rollbackTransaction();
|
||||||
|
QMessageBox::warning(this, QStringLiteral(u"错误"),
|
||||||
|
QStringLiteral(u"提交事务失败:") + dbMgr.lastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>NuclideLibManage</string>
|
<string>核素库</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
|
|
||||||
|
|
@ -182,8 +182,8 @@ void NuclideRayListDialog::onAddRayClicked()
|
||||||
|
|
||||||
qint64 newId = SqliteManager::instance().insertRow("nuclideRayInfo", fieldValues);
|
qint64 newId = SqliteManager::instance().insertRow("nuclideRayInfo", fieldValues);
|
||||||
if (newId > 0) {
|
if (newId > 0) {
|
||||||
QMessageBox::information(this, QStringLiteral(u"成功"), QStringLiteral(u"射线信息添加成功!"));
|
|
||||||
loadRayData(); // 刷新列表
|
loadRayData(); // 刷新列表
|
||||||
|
QMessageBox::information(this, QStringLiteral(u"成功"), QStringLiteral(u"射线信息添加成功!"));
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this, QStringLiteral(u"失败"), QStringLiteral(u"添加失败:") + SqliteManager::instance().lastError());
|
QMessageBox::warning(this, QStringLiteral(u"失败"), QStringLiteral(u"添加失败:") + SqliteManager::instance().lastError());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user