修改峰拟合分析
This commit is contained in:
parent
0e7981024a
commit
9b383103be
|
|
@ -181,6 +181,7 @@ void EnergyCountPeakFitView::setupPlot()
|
||||||
_plot->setAxisAutoScale(QwtPlot::xBottom, true);
|
_plot->setAxisAutoScale(QwtPlot::xBottom, true);
|
||||||
_plot->setAxisAutoScale(QwtPlot::yLeft, true);
|
_plot->setAxisAutoScale(QwtPlot::yLeft, true);
|
||||||
|
|
||||||
|
|
||||||
_plot->enableAxis(QwtPlot::xBottom);
|
_plot->enableAxis(QwtPlot::xBottom);
|
||||||
_plot->enableAxis(QwtPlot::yLeft);
|
_plot->enableAxis(QwtPlot::yLeft);
|
||||||
|
|
||||||
|
|
@ -483,45 +484,51 @@ void EnergyCountPeakFitView::finishSelection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (roiX.size() >= 3) {
|
if (roiX.size() >= 3)
|
||||||
|
{
|
||||||
QStringList algorithms;
|
QStringList algorithms;
|
||||||
algorithms << QStringLiteral(u"y=A*exp(-pow(x-P,2)/(2*pow(delt,2))) + H/(1+exp((x-P)/W)) + C");
|
algorithms << QStringLiteral(u"y=A*exp(-pow(x-P,2)/(2*pow(delt,2))) + H/(1+exp((x-P)/W)) + C");
|
||||||
bool ok = false;
|
|
||||||
QString selected = QInputDialog::getItem(this,
|
// 关键修改:实例化QInputDialog并设置窗口标志(去除问号按钮)
|
||||||
QStringLiteral(u"选择拟合算法"),
|
QInputDialog* algorithmDlg = new QInputDialog(this, Qt::Dialog | Qt::WindowCloseButtonHint);
|
||||||
QStringLiteral(u"请选择用于当前框选区域的峰拟合算法:"),
|
algorithmDlg->setWindowTitle(QStringLiteral(u"选择拟合算法"));
|
||||||
algorithms,
|
algorithmDlg->setLabelText(QStringLiteral(u"请选择用于当前框选区域的峰拟合算法:"));
|
||||||
0,
|
algorithmDlg->setComboBoxItems(algorithms);
|
||||||
false,
|
algorithmDlg->setComboBoxEditable(false);
|
||||||
&ok);
|
algorithmDlg->setModal(false); // 保持非模态
|
||||||
if (ok && selected == QStringLiteral(u"y=A*exp(-pow(x-P,2)/(2*pow(delt,2))) + H/(1+exp((x-P)/W)) + C"))
|
algorithmDlg->setAttribute(Qt::WA_DeleteOnClose); // 关闭自动释放内存
|
||||||
{
|
|
||||||
arma::vec armaRoiX(roiX.size()), armaRoiY(roiY.size());
|
// 异步处理用户选择(原if(ok)逻辑移到这里)
|
||||||
|
connect(algorithmDlg, &QInputDialog::accepted, this, [=]() {
|
||||||
|
QString selected = algorithmDlg->textValue();
|
||||||
|
if (selected == algorithms.first())
|
||||||
|
{
|
||||||
|
arma::vec armaRoiX(roiX.size()), armaRoiY(roiY.size());
|
||||||
for (int i = 0; i < roiX.size(); ++i) {
|
for (int i = 0; i < roiX.size(); ++i) {
|
||||||
armaRoiX(i) = roiX[i];
|
armaRoiX(i) = roiX[i];
|
||||||
armaRoiY(i) = roiY[i];
|
armaRoiY(i) = roiY[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
// 3. 执行拟合(曲线自动添加到主图)
|
// 执行拟合(曲线自动添加到主图)
|
||||||
QList<PeakFitResult> results = performPeakFitting(roiX, roiY/*, &userP0*/);
|
QList<PeakFitResult> results = performPeakFitting(roiX, roiY);
|
||||||
if (results.isEmpty()) {
|
if (results.isEmpty()) {
|
||||||
qDebug()<< QStringLiteral(u"拟合结果:") << QStringLiteral(u"未检测到有效峰或拟合失败。");
|
qDebug()<< QStringLiteral(u"拟合结果:") << QStringLiteral(u"未检测到有效峰或拟合失败。");
|
||||||
} else {
|
} else {
|
||||||
addSelectionRect(plotRect);
|
addSelectionRect(plotRect);
|
||||||
fadeSelectionRectBorders(); // 框选边框变为虚线(与原逻辑一致)
|
fadeSelectionRectBorders(); // 框选边框变为虚线(与原逻辑一致)
|
||||||
if (!_selectionRectItems.isEmpty() && !results.isEmpty())
|
if (!_selectionRectItems.isEmpty() && !results.isEmpty())
|
||||||
{
|
{
|
||||||
PlotRectItem* lastRect = _selectionRectItems.last();
|
PlotRectItem* lastRect = _selectionRectItems.last();
|
||||||
const PeakFitResult& r = results.first();
|
const PeakFitResult& r = results.first();
|
||||||
// 传入:峰位、FWHM、面积、本底
|
// 传入:峰位、FWHM、面积、本底
|
||||||
lastRect->setPeakData(r.center, r.fwhm, r.area, r.baseline);
|
lastRect->setPeakData(r.center, r.fwhm, r.area, r.baseline);
|
||||||
_plot->replot(); // 刷新显示
|
_plot->replot(); // 刷新显示
|
||||||
}
|
}
|
||||||
saveCurrentFitToHistory();
|
saveCurrentFitToHistory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
} else {
|
|
||||||
qDebug() << QStringLiteral(u"框选区域内数据点不足3个,无法拟合。");
|
algorithmDlg->show(); // 非模态显示
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -872,34 +879,41 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasCurveData) {
|
if (!hasCurveData) {
|
||||||
QMessageBox::information(this,
|
QMessageBox* msgBox = new QMessageBox(this);
|
||||||
QStringLiteral(u"峰拟合结果"),
|
msgBox->setWindowTitle(QStringLiteral(u"峰拟合结果"));
|
||||||
QStringLiteral(u"暂无历史拟合数据,请先进行拟合并保存。"));
|
msgBox->setText(QStringLiteral(u"暂无历史拟合数据,请先进行拟合并保存。"));
|
||||||
|
msgBox->setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox->setModal(false);
|
||||||
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
|
||||||
|
msgBox->show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog dlg(this);
|
// 替换栈变量为堆上非模态对话框
|
||||||
dlg.setWindowTitle(QStringLiteral(u"峰拟合结果历史"));
|
QDialog* historyDlg = new QDialog(this , Qt::Dialog | Qt::WindowCloseButtonHint);
|
||||||
dlg.setMinimumSize(1000, 500);
|
historyDlg->setWindowTitle(QStringLiteral(u"峰拟合结果"));
|
||||||
QVBoxLayout* layout = new QVBoxLayout(&dlg);
|
historyDlg->setMinimumSize(1000, 500);
|
||||||
|
historyDlg->setModal(false);
|
||||||
|
historyDlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
QStandardItemModel* model = new QStandardItemModel(&dlg);
|
QVBoxLayout* layout = new QVBoxLayout(historyDlg);
|
||||||
|
QStandardItemModel* model = new QStandardItemModel(historyDlg);
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
headers << "" << "振幅(A)" << "高斯宽度(delt)" << "Sigmoid幅度(H)" << "Sigmoid宽度(W)" << "基线(C)" << "峰中心(P)";
|
headers << "" << "振幅(A)" << "高斯宽度(delt)" << "Sigmoid幅度(H)" << "Sigmoid宽度(W)" << "基线(C)" << "峰中心(P)";
|
||||||
model->setHorizontalHeaderLabels(headers);
|
model->setHorizontalHeaderLabels(headers);
|
||||||
|
|
||||||
QVector<QPair<int, int>> rowToDataIndices;
|
QVector<QPair<int, int>> rowToDataIndices;
|
||||||
|
|
||||||
model->blockSignals(true);
|
model->blockSignals(true);
|
||||||
for (int historyIdx = 0; historyIdx < _fitHistoryList.size(); ++historyIdx) {
|
for (int historyIdx = 0; historyIdx < _fitHistoryList.size(); ++historyIdx) {
|
||||||
const auto& historyItem = _fitHistoryList[historyIdx];
|
const auto& historyItem = _fitHistoryList[historyIdx];
|
||||||
for (int curveIdx = 0; curveIdx < historyItem.curveList.size(); ++curveIdx) {
|
for (int curveIdx = 0; curveIdx < historyItem.curveList.size(); ++curveIdx) {
|
||||||
const auto& curve = historyItem.curveList[curveIdx];
|
const auto& curve = historyItem.curveList[curveIdx];
|
||||||
QList<QStandardItem*> rowItems;
|
QList<QStandardItem*> rowItems;
|
||||||
|
|
||||||
QStandardItem* checkItem = new QStandardItem();
|
QStandardItem* checkItem = new QStandardItem();
|
||||||
checkItem->setCheckable(true);
|
checkItem->setCheckable(true);
|
||||||
checkItem->setEditable(false);
|
checkItem->setEditable(false);
|
||||||
|
|
||||||
bool isCurrentlyDisplayed = false;
|
bool isCurrentlyDisplayed = false;
|
||||||
for (const auto& ref : _displayedHistoryCurves) {
|
for (const auto& ref : _displayedHistoryCurves) {
|
||||||
if (ref.historyIndex == historyIdx && ref.curveIndex == curveIdx) {
|
if (ref.historyIndex == historyIdx && ref.curveIndex == curveIdx) {
|
||||||
|
|
@ -910,35 +924,12 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
checkItem->setCheckState(isCurrentlyDisplayed ? Qt::Checked : Qt::Unchecked);
|
checkItem->setCheckState(isCurrentlyDisplayed ? Qt::Checked : Qt::Unchecked);
|
||||||
rowItems.append(checkItem);
|
rowItems.append(checkItem);
|
||||||
|
|
||||||
// 2. 振幅 (A)
|
rowItems.append(new QStandardItem(QString::number(curve.amplitude, 'f', 4)));
|
||||||
QStandardItem* itemA = new QStandardItem(QString::number(curve.amplitude, 'f', 4));
|
rowItems.append(new QStandardItem(QString::number(curve.sigma, 'f', 4)));
|
||||||
itemA->setEditable(false);
|
rowItems.append(new QStandardItem(QString::number(curve.sigmoidH, 'f', 4)));
|
||||||
rowItems.append(itemA);
|
rowItems.append(new QStandardItem(QString::number(curve.sigmoidW, 'f', 4)));
|
||||||
|
rowItems.append(new QStandardItem(QString::number(curve.baseline, 'f', 4)));
|
||||||
// 3. Sigma (delt)
|
rowItems.append(new QStandardItem(QString::number(curve.center, 'f', 4)));
|
||||||
QStandardItem* itemDelt = new QStandardItem(QString::number(curve.sigma, 'f', 4));
|
|
||||||
itemDelt->setEditable(false);
|
|
||||||
rowItems.append(itemDelt);
|
|
||||||
|
|
||||||
// 4. SigmoidH (H)
|
|
||||||
QStandardItem* itemH = new QStandardItem(QString::number(curve.sigmoidH, 'f', 4));
|
|
||||||
itemH->setEditable(false);
|
|
||||||
rowItems.append(itemH);
|
|
||||||
|
|
||||||
// 5. SigmoidW (W)
|
|
||||||
QStandardItem* itemW = new QStandardItem(QString::number(curve.sigmoidW, 'f', 4));
|
|
||||||
itemW->setEditable(false);
|
|
||||||
rowItems.append(itemW);
|
|
||||||
|
|
||||||
// 6. 本底 (C)
|
|
||||||
QStandardItem* itemC = new QStandardItem(QString::number(curve.baseline, 'f', 4));
|
|
||||||
itemC->setEditable(false);
|
|
||||||
rowItems.append(itemC);
|
|
||||||
|
|
||||||
// 7. 峰位 (P)
|
|
||||||
QStandardItem* itemP = new QStandardItem(QString::number(curve.center, 'f', 4));
|
|
||||||
itemP->setEditable(false);
|
|
||||||
rowItems.append(itemP);
|
|
||||||
|
|
||||||
model->appendRow(rowItems);
|
model->appendRow(rowItems);
|
||||||
rowToDataIndices.append(qMakePair(historyIdx, curveIdx));
|
rowToDataIndices.append(qMakePair(historyIdx, curveIdx));
|
||||||
|
|
@ -947,14 +938,14 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
model->blockSignals(false);
|
model->blockSignals(false);
|
||||||
|
|
||||||
QHBoxLayout* topBtnLayout = new QHBoxLayout();
|
QHBoxLayout* topBtnLayout = new QHBoxLayout();
|
||||||
QPushButton* btnSelectAll = new QPushButton(QStringLiteral(u"全选"), &dlg);
|
QPushButton* btnSelectAll = new QPushButton(QStringLiteral(u"全选"), historyDlg);
|
||||||
QPushButton* btnInvertSelection = new QPushButton(QStringLiteral(u"反选"), &dlg);
|
QPushButton* btnInvertSelection = new QPushButton(QStringLiteral(u"反选"), historyDlg);
|
||||||
topBtnLayout->addWidget(btnSelectAll);
|
topBtnLayout->addWidget(btnSelectAll);
|
||||||
topBtnLayout->addWidget(btnInvertSelection);
|
topBtnLayout->addWidget(btnInvertSelection);
|
||||||
topBtnLayout->addStretch();
|
topBtnLayout->addStretch();
|
||||||
layout->addLayout(topBtnLayout);
|
layout->addLayout(topBtnLayout);
|
||||||
|
|
||||||
QTableView* tableView = new QTableView(&dlg);
|
QTableView* tableView = new QTableView(historyDlg);
|
||||||
tableView->setModel(model);
|
tableView->setModel(model);
|
||||||
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
@ -964,16 +955,16 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
layout->addWidget(tableView);
|
layout->addWidget(tableView);
|
||||||
|
|
||||||
QPushButton* btnDelete = new QPushButton(QStringLiteral(u"删除选中记录"), &dlg);
|
QPushButton* btnDelete = new QPushButton(QStringLiteral(u"删除选中记录"), historyDlg);
|
||||||
QPushButton* btnClose = new QPushButton(QStringLiteral(u"关闭"), &dlg);
|
QPushButton* btnClose = new QPushButton(QStringLiteral(u"关闭"), historyDlg);
|
||||||
QHBoxLayout* bottomBtnLayout = new QHBoxLayout();
|
QHBoxLayout* bottomBtnLayout = new QHBoxLayout();
|
||||||
bottomBtnLayout->addStretch();
|
bottomBtnLayout->addStretch();
|
||||||
bottomBtnLayout->addWidget(btnDelete);
|
bottomBtnLayout->addWidget(btnDelete);
|
||||||
bottomBtnLayout->addWidget(btnClose);
|
bottomBtnLayout->addWidget(btnClose);
|
||||||
layout->addLayout(bottomBtnLayout);
|
layout->addLayout(bottomBtnLayout);
|
||||||
|
|
||||||
// --- 全选按钮 ---
|
// 全选按钮逻辑保持不变
|
||||||
connect(btnSelectAll, &QPushButton::clicked, [&]() {
|
connect(btnSelectAll, &QPushButton::clicked, [=]() {
|
||||||
model->blockSignals(true);
|
model->blockSignals(true);
|
||||||
for (int row = 0; row < model->rowCount(); ++row) {
|
for (int row = 0; row < model->rowCount(); ++row) {
|
||||||
model->item(row, 0)->setCheckState(Qt::Checked);
|
model->item(row, 0)->setCheckState(Qt::Checked);
|
||||||
|
|
@ -996,8 +987,8 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
displaySelectedCurves(selectedCurves, selectedRefs);
|
displaySelectedCurves(selectedCurves, selectedRefs);
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- 反选按钮 ---
|
// 反选按钮逻辑保持不变
|
||||||
connect(btnInvertSelection, &QPushButton::clicked, [&]() {
|
connect(btnInvertSelection, &QPushButton::clicked, [=]() {
|
||||||
model->blockSignals(true);
|
model->blockSignals(true);
|
||||||
for (int row = 0; row < model->rowCount(); ++row) {
|
for (int row = 0; row < model->rowCount(); ++row) {
|
||||||
QStandardItem* item = model->item(row, 0);
|
QStandardItem* item = model->item(row, 0);
|
||||||
|
|
@ -1021,8 +1012,8 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
displaySelectedCurves(selectedCurves, selectedRefs);
|
displaySelectedCurves(selectedCurves, selectedRefs);
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- 复选框状态改变 ---
|
// 复选框状态改变逻辑保持不变
|
||||||
connect(model, &QStandardItemModel::itemChanged, [&](QStandardItem* /*item*/) {
|
connect(model, &QStandardItemModel::itemChanged, [=](QStandardItem* /*item*/) {
|
||||||
QList<FitCurveData> selectedCurves;
|
QList<FitCurveData> selectedCurves;
|
||||||
QList<DisplayedCurveRef> selectedRefs;
|
QList<DisplayedCurveRef> selectedRefs;
|
||||||
for (int row = 0; row < model->rowCount(); ++row) {
|
for (int row = 0; row < model->rowCount(); ++row) {
|
||||||
|
|
@ -1038,9 +1029,8 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
displaySelectedCurves(selectedCurves, selectedRefs);
|
displaySelectedCurves(selectedCurves, selectedRefs);
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- 删除选中记录按钮(核心精准删除逻辑) ---
|
// 删除按钮逻辑(改为非模态确认框)
|
||||||
connect(btnDelete, &QPushButton::clicked, [&]() {
|
connect(btnDelete, &QPushButton::clicked, [=]() {
|
||||||
// 1. 收集要删除的历史索引
|
|
||||||
QSet<int> historyIndicesToDelete;
|
QSet<int> historyIndicesToDelete;
|
||||||
for (int row = 0; row < model->rowCount(); ++row) {
|
for (int row = 0; row < model->rowCount(); ++row) {
|
||||||
if (model->item(row, 0)->checkState() == Qt::Checked) {
|
if (model->item(row, 0)->checkState() == Qt::Checked) {
|
||||||
|
|
@ -1048,95 +1038,101 @@ void EnergyCountPeakFitView::onActionShowFitHistory()
|
||||||
historyIndicesToDelete.insert(indices.first);
|
historyIndicesToDelete.insert(indices.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (historyIndicesToDelete.isEmpty()) {
|
if (historyIndicesToDelete.isEmpty()) {
|
||||||
QMessageBox::warning(&dlg, QStringLiteral(u"提示"), QStringLiteral(u"请先勾选要删除的记录。"));
|
QMessageBox* msgBox = new QMessageBox(historyDlg);
|
||||||
|
msgBox->setWindowTitle(QStringLiteral(u"提示"));
|
||||||
|
msgBox->setText(QStringLiteral(u"请先勾选要删除的记录。"));
|
||||||
|
msgBox->setStandardButtons(QMessageBox::Ok);
|
||||||
|
msgBox->setModal(false);
|
||||||
|
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
msgBox->show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 确认删除
|
|
||||||
QString msg = QStringLiteral(u"确定要删除选中的 %1 条历史记录吗?").arg(historyIndicesToDelete.size());
|
QString msg = QStringLiteral(u"确定要删除选中的 %1 条历史记录吗?").arg(historyIndicesToDelete.size());
|
||||||
QMessageBox::StandardButton reply = QMessageBox::question(&dlg, QStringLiteral(u"确认删除"), msg, QMessageBox::Yes | QMessageBox::No);
|
QMessageBox* confirmBox = new QMessageBox(historyDlg);
|
||||||
if (reply != QMessageBox::Yes) return;
|
confirmBox->setWindowTitle(QStringLiteral(u"确认删除"));
|
||||||
|
confirmBox->setText(msg);
|
||||||
|
confirmBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||||
|
confirmBox->setModal(false);
|
||||||
|
confirmBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
// 3. 先从界面上精准删除显示(从后往前删)
|
// 保存临时数据
|
||||||
QList<int> sortedDisplayIndices;
|
confirmBox->setProperty("historyIndicesToDelete", QVariant::fromValue(historyIndicesToDelete));
|
||||||
for (int i = 0; i < _displayedHistoryCurves.size(); ++i) {
|
confirmBox->setProperty("model", QVariant::fromValue(model));
|
||||||
if (historyIndicesToDelete.contains(_displayedHistoryCurves[i].historyIndex)) {
|
confirmBox->setProperty("rowToDataIndices", QVariant::fromValue(rowToDataIndices));
|
||||||
sortedDisplayIndices.append(i);
|
|
||||||
|
connect(confirmBox, &QMessageBox::buttonClicked, this, [=](QAbstractButton* button) {
|
||||||
|
if (confirmBox->standardButton(button) == QMessageBox::Yes) {
|
||||||
|
QSet<int> historyIndicesToDelete = confirmBox->property("historyIndicesToDelete").value<QSet<int>>();
|
||||||
|
|
||||||
|
// 原有删除逻辑保持不变
|
||||||
|
QList<int> sortedDisplayIndices;
|
||||||
|
for (int i = 0; i < _displayedHistoryCurves.size(); ++i) {
|
||||||
|
if (historyIndicesToDelete.contains(_displayedHistoryCurves[i].historyIndex)) {
|
||||||
|
sortedDisplayIndices.append(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(sortedDisplayIndices.begin(), sortedDisplayIndices.end(), std::greater<int>());
|
||||||
|
for (int dispIdx : sortedDisplayIndices) {
|
||||||
|
const auto& ref = _displayedHistoryCurves[dispIdx];
|
||||||
|
if (ref.curveStartIndex + 1 < _fitCurves.size()) {
|
||||||
|
_fitCurves[ref.curveStartIndex + 1]->detach();
|
||||||
|
delete _fitCurves[ref.curveStartIndex + 1];
|
||||||
|
_fitCurves.removeAt(ref.curveStartIndex + 1);
|
||||||
|
_fitCurves[ref.curveStartIndex]->detach();
|
||||||
|
delete _fitCurves[ref.curveStartIndex];
|
||||||
|
_fitCurves.removeAt(ref.curveStartIndex);
|
||||||
|
}
|
||||||
|
if (ref.rectIndex < _selectionRectItems.size()) {
|
||||||
|
_selectionRectItems[ref.rectIndex]->detach();
|
||||||
|
delete _selectionRectItems[ref.rectIndex];
|
||||||
|
_selectionRectItems.removeAt(ref.rectIndex);
|
||||||
|
}
|
||||||
|
_displayedHistoryCurves.removeAt(dispIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<FitCurveData> remainingCurves;
|
||||||
|
QList<DisplayedCurveRef> remainingRefs;
|
||||||
|
for (const auto& ref : _displayedHistoryCurves) {
|
||||||
|
remainingCurves.append(_fitHistoryList[ref.historyIndex].curveList[ref.curveIndex]);
|
||||||
|
remainingRefs.append(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<int> sortedHistoryIndices = historyIndicesToDelete.values();
|
||||||
|
std::sort(sortedHistoryIndices.begin(), sortedHistoryIndices.end(), std::greater<int>());
|
||||||
|
for (auto& ref : remainingRefs) {
|
||||||
|
int offset = 0;
|
||||||
|
for (int delIdx : sortedHistoryIndices) {
|
||||||
|
if (delIdx < ref.historyIndex) offset++;
|
||||||
|
}
|
||||||
|
ref.historyIndex -= offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int historyIdx : sortedHistoryIndices) {
|
||||||
|
_fitHistoryList.removeAt(historyIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearFitCurves();
|
||||||
|
clearAllSelectionRects();
|
||||||
|
_displayedHistoryCurves.clear();
|
||||||
|
if (!remainingCurves.isEmpty()) {
|
||||||
|
displaySelectedCurves(remainingCurves, remainingRefs);
|
||||||
|
} else {
|
||||||
|
_plot->replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
saveHistoryToFile();
|
||||||
|
historyDlg->accept();
|
||||||
|
onActionShowFitHistory(); // 重新打开更新后的历史窗口
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
std::sort(sortedDisplayIndices.begin(), sortedDisplayIndices.end(), std::greater<int>());
|
|
||||||
|
|
||||||
for (int dispIdx : sortedDisplayIndices) {
|
confirmBox->show();
|
||||||
const auto& ref = _displayedHistoryCurves[dispIdx];
|
|
||||||
|
|
||||||
// 删除曲线(先删本底,再删拟合)
|
|
||||||
if (ref.curveStartIndex + 1 < _fitCurves.size()) {
|
|
||||||
_fitCurves[ref.curveStartIndex + 1]->detach();
|
|
||||||
delete _fitCurves[ref.curveStartIndex + 1];
|
|
||||||
_fitCurves.removeAt(ref.curveStartIndex + 1);
|
|
||||||
|
|
||||||
_fitCurves[ref.curveStartIndex]->detach();
|
|
||||||
delete _fitCurves[ref.curveStartIndex];
|
|
||||||
_fitCurves.removeAt(ref.curveStartIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除框选
|
|
||||||
if (ref.rectIndex < _selectionRectItems.size()) {
|
|
||||||
_selectionRectItems[ref.rectIndex]->detach();
|
|
||||||
delete _selectionRectItems[ref.rectIndex];
|
|
||||||
_selectionRectItems.removeAt(ref.rectIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除引用
|
|
||||||
_displayedHistoryCurves.removeAt(dispIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 收集剩余显示的数据(用于重建)
|
|
||||||
QList<FitCurveData> remainingCurves;
|
|
||||||
QList<DisplayedCurveRef> remainingRefs;
|
|
||||||
for (const auto& ref : _displayedHistoryCurves) {
|
|
||||||
remainingCurves.append(_fitHistoryList[ref.historyIndex].curveList[ref.curveIndex]);
|
|
||||||
remainingRefs.append(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 更新剩余引用的 historyIndex(处理索引偏移)
|
|
||||||
QList<int> sortedHistoryIndices = historyIndicesToDelete.values();
|
|
||||||
std::sort(sortedHistoryIndices.begin(), sortedHistoryIndices.end(), std::greater<int>());
|
|
||||||
|
|
||||||
for (auto& ref : remainingRefs) {
|
|
||||||
int offset = 0;
|
|
||||||
for (int delIdx : sortedHistoryIndices) {
|
|
||||||
if (delIdx < ref.historyIndex) offset++;
|
|
||||||
}
|
|
||||||
ref.historyIndex -= offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. 删除历史数据
|
|
||||||
for (int historyIdx : sortedHistoryIndices) {
|
|
||||||
_fitHistoryList.removeAt(historyIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. 重建界面显示(确保索引正确)
|
|
||||||
clearFitCurves();
|
|
||||||
clearAllSelectionRects();
|
|
||||||
_displayedHistoryCurves.clear();
|
|
||||||
|
|
||||||
if (!remainingCurves.isEmpty()) {
|
|
||||||
displaySelectedCurves(remainingCurves, remainingRefs);
|
|
||||||
} else {
|
|
||||||
_plot->replot();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. 保存并刷新
|
|
||||||
saveHistoryToFile();
|
|
||||||
dlg.accept();
|
|
||||||
onActionShowFitHistory();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(btnClose, &QPushButton::clicked, &dlg, &QDialog::accept);
|
connect(btnClose, &QPushButton::clicked, historyDlg, &QDialog::close);
|
||||||
dlg.exec();
|
historyDlg->show(); // 非模态显示
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
void EnergyCountPeakFitView::onActionDeleteHoveredRect()
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
#include "PeakFitParamsDialog.h"
|
#include "PeakFitParamsDialog.h"
|
||||||
|
|
||||||
PeakFitParamsDialog::PeakFitParamsDialog(const FitParams& defaultParams, QWidget* parent)
|
PeakFitParamsDialog::PeakFitParamsDialog(const FitParams& defaultParams, QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent, Qt::Dialog | Qt::WindowCloseButtonHint)
|
||||||
{
|
{
|
||||||
setWindowTitle(QStringLiteral(u"光子峰拟合参数设置"));
|
setWindowTitle(QStringLiteral(u"光子峰拟合参数设置"));
|
||||||
setModal(true);
|
setModal(true);
|
||||||
|
|
||||||
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
||||||
QFormLayout* form = new QFormLayout();
|
QFormLayout* form = new QFormLayout();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user