Compare commits
No commits in common. "3f9fe830ec106297578e36e3d56fada9a6889a38" and "8ba3063a84684f19b1766c53039d65dd4a5ae9a9" have entirely different histories.
3f9fe830ec
...
8ba3063a84
|
|
@ -1,446 +0,0 @@
|
||||||
#include "DeviceConfigView.h"
|
|
||||||
#include "DeviceParameterProxy.h"
|
|
||||||
#include <QTableView>
|
|
||||||
#include <QStandardItemModel>
|
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QStyleOptionButton>
|
|
||||||
#include <GlobalDefine.h>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DeviceConfigView::DeviceConfigView(QWidget *parent)
|
|
||||||
: MeasureAnalysisView(parent)
|
|
||||||
, m_tableView(nullptr)
|
|
||||||
, m_model(nullptr)
|
|
||||||
{
|
|
||||||
initTableView();
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceConfigView::~DeviceConfigView()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::initTableView()
|
|
||||||
{
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
|
|
||||||
m_tableView = new QTableView(this);
|
|
||||||
layout->addWidget(m_tableView);
|
|
||||||
|
|
||||||
// 设置表头
|
|
||||||
QStringList headList;
|
|
||||||
headList << tr("数据传输模式") << tr("硬件增益") << tr("硬件增益选择索引")
|
|
||||||
<< tr("软件增益") << tr("时间常数") << tr("成形时间") << tr("快通道触发阈值")
|
|
||||||
<< tr("多道分辨率") << tr("控制功能") << tr("幅度提前延迟") << tr("积分长度")
|
|
||||||
<< tr("dcfd缩放倍数") << tr("dcfd延迟") << tr("直流偏移") << tr("最大能量范围")
|
|
||||||
<< tr("Am 峰面积寻峰法的面积比例") << tr("K40与 Am241的峰位校正系数") << tr("高压关断阈值")
|
|
||||||
<< tr("获取能谱周期") << tr("总测量时间") << tr("总测量次数") << tr("滤波参数")
|
|
||||||
<< tr("上升时间") << tr("平顶时间") << tr("ICR 校正使能") << tr("CRZA 值")
|
|
||||||
<< tr("ZA 使能值") << tr("操作");
|
|
||||||
|
|
||||||
m_model = new QStandardItemModel(this);
|
|
||||||
m_model->setColumnCount(headList.size());
|
|
||||||
m_model->setHorizontalHeaderLabels(headList);
|
|
||||||
m_model->setRowCount(32);
|
|
||||||
|
|
||||||
for (int i = 0; i < 32; ++i) {
|
|
||||||
QString rowName = tr("通道%1").arg(i + 1);
|
|
||||||
m_model->setHeaderData(i, Qt::Vertical, rowName, Qt::DisplayRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 操作列最后一列不可编辑
|
|
||||||
int actionCol = headList.size() - 1;
|
|
||||||
for (int row = 0; row < 32; ++row) {
|
|
||||||
QStandardItem *item = new QStandardItem(QString());
|
|
||||||
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
|
|
||||||
m_model->setItem(row, actionCol, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_tableView->setModel(m_model);
|
|
||||||
m_tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Interactive);
|
|
||||||
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
|
|
||||||
m_tableView->setEditTriggers(QAbstractItemView::DoubleClicked);
|
|
||||||
// 设置代理
|
|
||||||
DeviceParameterProxy *proxy = new DeviceParameterProxy(this);
|
|
||||||
m_tableView->setItemDelegate(proxy);
|
|
||||||
|
|
||||||
setupActionColumnButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::setupActionColumnButtons()
|
|
||||||
{
|
|
||||||
int actionCol = m_model->columnCount() - 1;
|
|
||||||
for (int row = 0; row < m_model->rowCount(); ++row) {
|
|
||||||
QModelIndex idx = m_model->index(row, actionCol);
|
|
||||||
QPushButton *btn = new QPushButton(tr("应用"), m_tableView);
|
|
||||||
btn->setProperty("row", row);
|
|
||||||
connect(btn, &QPushButton::clicked, this, &DeviceConfigView::onActionButtonClicked);
|
|
||||||
m_tableView->setIndexWidget(idx, btn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::onActionButtonClicked()
|
|
||||||
{
|
|
||||||
QPushButton *btn = qobject_cast<QPushButton*>(sender());
|
|
||||||
if (!btn) return;
|
|
||||||
|
|
||||||
int srcRow = btn->property("row").toInt();
|
|
||||||
int srcChannel = srcRow + 1;
|
|
||||||
|
|
||||||
QList<int> targetChannels = selectTargetChannels(srcChannel);
|
|
||||||
if (targetChannels.isEmpty()) return;
|
|
||||||
|
|
||||||
int paramColCount = m_model->columnCount() - 1;
|
|
||||||
m_model->blockSignals(true);
|
|
||||||
for (int ch : targetChannels) {
|
|
||||||
int dstRow = ch - 1;
|
|
||||||
if (dstRow == srcRow) continue;
|
|
||||||
for (int col = 0; col < paramColCount; ++col) {
|
|
||||||
QVariant srcData = m_model->data(m_model->index(srcRow, col));
|
|
||||||
m_model->setData(m_model->index(dstRow, col), srcData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_model->blockSignals(false);
|
|
||||||
|
|
||||||
emit m_model->dataChanged(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, paramColCount - 1));
|
|
||||||
QMessageBox::information(this, tr("提示"),
|
|
||||||
tr("已成功将通道%1的参数应用到 %2 个通道").arg(srcChannel).arg(targetChannels.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<int> DeviceConfigView::selectTargetChannels(int currentChannel) const
|
|
||||||
{
|
|
||||||
QDialog dlg(const_cast<DeviceConfigView*>(this));
|
|
||||||
dlg.setWindowTitle(tr("选择目标通道"));
|
|
||||||
dlg.resize(300, 400);
|
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(&dlg);
|
|
||||||
QLabel *label = new QLabel(tr("请选择要应用参数的目标通道(可多选):"));
|
|
||||||
layout->addWidget(label);
|
|
||||||
|
|
||||||
QListWidget *listWidget = new QListWidget(&dlg);
|
|
||||||
for (int i = 1; i <= 32; ++i) {
|
|
||||||
QString itemText = tr("通道 %1").arg(i);
|
|
||||||
if (i == currentChannel) itemText += tr(" (源通道)");
|
|
||||||
QListWidgetItem *item = new QListWidgetItem(itemText, listWidget);
|
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
|
||||||
item->setCheckState(Qt::Unchecked);
|
|
||||||
item->setData(Qt::UserRole, i);
|
|
||||||
if (i == currentChannel) {
|
|
||||||
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layout->addWidget(listWidget);
|
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dlg);
|
|
||||||
layout->addWidget(buttonBox);
|
|
||||||
connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
|
|
||||||
connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
|
|
||||||
|
|
||||||
QList<int> selected;
|
|
||||||
if (dlg.exec() == QDialog::Accepted) {
|
|
||||||
for (int i = 0; i < listWidget->count(); ++i) {
|
|
||||||
QListWidgetItem *item = listWidget->item(i);
|
|
||||||
if (item->checkState() == Qt::Checked) {
|
|
||||||
int ch = item->data(Qt::UserRole).toInt();
|
|
||||||
if (ch != currentChannel) selected.append(ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceConfigView::loadJson(const QString &filePath)
|
|
||||||
{
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
qWarning() << "无法打开文件:" << file.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QByteArray jsonData = file.readAll();
|
|
||||||
file.close();
|
|
||||||
return parseJsonImpl(jsonData);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceConfigView::parseJsonImpl(const QByteArray &data)
|
|
||||||
{
|
|
||||||
QJsonParseError parseError;
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &parseError);
|
|
||||||
if (parseError.error != QJsonParseError::NoError) {
|
|
||||||
qWarning() << "JSON 解析错误:" << parseError.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!jsonDoc.isObject()) {
|
|
||||||
qWarning() << "JSON 文档不是对象";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject rootObj = jsonDoc.object();
|
|
||||||
QJsonArray channelsArray = rootObj["channels"].toArray();
|
|
||||||
|
|
||||||
m_model->blockSignals(true);
|
|
||||||
|
|
||||||
// 清空现有数据
|
|
||||||
for (int row = 0; row < m_model->rowCount(); ++row) {
|
|
||||||
for (int col = 0; col < m_model->columnCount(); ++col) {
|
|
||||||
m_model->setData(m_model->index(row, col), QVariant());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = qMin(channelsArray.size(), m_model->rowCount());
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
QJsonValue channelValue = channelsArray[i];
|
|
||||||
if (!channelValue.isObject()) continue;
|
|
||||||
QJsonObject channelObj = channelValue.toObject();
|
|
||||||
|
|
||||||
for (int col = 0; col < m_model->columnCount(); ++col) {
|
|
||||||
QString header = m_model->headerData(col, Qt::Horizontal).toString();
|
|
||||||
QString jsonKey = m_columnToJsonKey.value(header);
|
|
||||||
if (jsonKey.isEmpty()) continue;
|
|
||||||
|
|
||||||
QJsonValue value = channelObj[jsonKey];
|
|
||||||
if (value.isUndefined()) continue;
|
|
||||||
|
|
||||||
if (value.isString())
|
|
||||||
m_model->setData(m_model->index(i, col), value.toString());
|
|
||||||
else if (value.isDouble())
|
|
||||||
m_model->setData(m_model->index(i, col), value.toDouble());
|
|
||||||
else if (value.isBool())
|
|
||||||
m_model->setData(m_model->index(i, col), value.toBool());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit m_model->dataChanged(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, m_model->columnCount() - 1));
|
|
||||||
emit dataChanged();
|
|
||||||
|
|
||||||
m_tableView->viewport()->update();
|
|
||||||
m_tableView->horizontalHeader()->update();
|
|
||||||
m_tableView->verticalHeader()->update();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceConfigView::saveJson(const QString &filePath)
|
|
||||||
{
|
|
||||||
QJsonObject rootObj;
|
|
||||||
rootObj["command"] = "SET";
|
|
||||||
QJsonArray channelsArray;
|
|
||||||
|
|
||||||
for (int row = 0; row < m_model->rowCount(); ++row) {
|
|
||||||
QJsonObject channelObj;
|
|
||||||
for (int col = 0; col < m_model->columnCount(); ++col) {
|
|
||||||
QString header = m_model->headerData(col, Qt::Horizontal).toString();
|
|
||||||
QString jsonKey = m_columnToJsonKey.value(header);
|
|
||||||
if (jsonKey.isEmpty()) continue;
|
|
||||||
|
|
||||||
QVariant value = m_model->index(row, col).data(Qt::EditRole);
|
|
||||||
if (!value.isValid() || value.isNull()) continue;
|
|
||||||
channelObj[jsonKey] = QJsonValue::fromVariant(value);
|
|
||||||
}
|
|
||||||
channelsArray.append(channelObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
rootObj["channels"] = channelsArray;
|
|
||||||
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
qWarning() << "无法创建文件:" << file.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QJsonDocument doc(rootObj);
|
|
||||||
file.write(doc.toJson());
|
|
||||||
file.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStandardItemModel* DeviceConfigView::getModel() const
|
|
||||||
{
|
|
||||||
return m_model;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::showColumnControlDialog()
|
|
||||||
{
|
|
||||||
int colCount = m_model->columnCount();
|
|
||||||
if (colCount == 0) return;
|
|
||||||
|
|
||||||
QDialog dlg(this);
|
|
||||||
dlg.setWindowTitle(tr("列显示控制"));
|
|
||||||
dlg.resize(800, 400);
|
|
||||||
dlg.setWindowModality(Qt::WindowModal);
|
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout(&dlg);
|
|
||||||
|
|
||||||
// 工具栏
|
|
||||||
QHBoxLayout *row1Layout = new QHBoxLayout();
|
|
||||||
QPushButton *btnSelectAll = new QPushButton(tr("全选"));
|
|
||||||
QPushButton *btnInvert = new QPushButton(tr("反选"));
|
|
||||||
QPushButton *btnSave = new QPushButton(tr("保存配置"));
|
|
||||||
QPushButton *btnLoad = new QPushButton(tr("加载配置"));
|
|
||||||
row1Layout->addWidget(btnSelectAll);
|
|
||||||
row1Layout->addWidget(btnInvert);
|
|
||||||
row1Layout->addWidget(btnSave);
|
|
||||||
row1Layout->addWidget(btnLoad);
|
|
||||||
row1Layout->addStretch();
|
|
||||||
mainLayout->addLayout(row1Layout);
|
|
||||||
|
|
||||||
QScrollArea *scrollArea = new QScrollArea();
|
|
||||||
scrollArea->setWidgetResizable(true);
|
|
||||||
QWidget *scrollWidget = new QWidget();
|
|
||||||
QGridLayout *gridLayout = new QGridLayout(scrollWidget);
|
|
||||||
scrollArea->setWidget(scrollWidget);
|
|
||||||
mainLayout->addWidget(scrollArea);
|
|
||||||
|
|
||||||
int gridCols = std::sqrt(colCount);
|
|
||||||
if (gridCols < 1) gridCols = 1;
|
|
||||||
|
|
||||||
QMap<int, QCheckBox*> colCheckBoxMap;
|
|
||||||
for (int col = 0; col < colCount; ++col) {
|
|
||||||
QString header = m_model->headerData(col, Qt::Horizontal).toString();
|
|
||||||
QCheckBox *cb = new QCheckBox(header);
|
|
||||||
cb->setChecked(!m_tableView->isColumnHidden(col));
|
|
||||||
connect(cb, &QCheckBox::toggled, this, [this, col](bool checked) {
|
|
||||||
m_tableView->setColumnHidden(col, !checked);
|
|
||||||
});
|
|
||||||
int row = col / gridCols;
|
|
||||||
int colInGrid = col % gridCols;
|
|
||||||
gridLayout->addWidget(cb, row, colInGrid);
|
|
||||||
colCheckBoxMap[col] = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(btnSelectAll, &QPushButton::clicked, this, [colCheckBoxMap, this]() {
|
|
||||||
// 先断开所有复选框的信号
|
|
||||||
for (QCheckBox *cb : colCheckBoxMap) {
|
|
||||||
cb->blockSignals(true);
|
|
||||||
cb->setChecked(true);
|
|
||||||
cb->blockSignals(false);
|
|
||||||
}
|
|
||||||
// 一次性更新所有列的隐藏状态
|
|
||||||
for (int col : colCheckBoxMap.keys()) {
|
|
||||||
m_tableView->setColumnHidden(col, !colCheckBoxMap[col]->isChecked());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(btnInvert, &QPushButton::clicked, this, [colCheckBoxMap, this]() {
|
|
||||||
for (QCheckBox *cb : colCheckBoxMap) {
|
|
||||||
cb->blockSignals(true);
|
|
||||||
cb->setChecked(!cb->isChecked());
|
|
||||||
cb->blockSignals(false);
|
|
||||||
}
|
|
||||||
for (int col : colCheckBoxMap.keys()) {
|
|
||||||
m_tableView->setColumnHidden(col, !colCheckBoxMap[col]->isChecked());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(btnSave, &QPushButton::clicked, this, [this, &dlg, colCheckBoxMap]() {
|
|
||||||
QString saveDir = QDir::currentPath() + "/columnConfigs";
|
|
||||||
QDir().mkpath(saveDir);
|
|
||||||
QString fileName = QFileDialog::getSaveFileName(&dlg, tr("保存列配置"),
|
|
||||||
saveDir + "/untitled.json",
|
|
||||||
"JSON Files (*.json)");
|
|
||||||
if (fileName.isEmpty()) return;
|
|
||||||
|
|
||||||
QJsonObject root;
|
|
||||||
for (int col = 0; col < m_model->columnCount(); ++col) {
|
|
||||||
QString header = m_model->headerData(col, Qt::Horizontal).toString();
|
|
||||||
bool checked = colCheckBoxMap[col]->isChecked();
|
|
||||||
root[header] = checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonDocument doc(root);
|
|
||||||
QFile file(fileName);
|
|
||||||
if (file.open(QIODevice::WriteOnly)) {
|
|
||||||
file.write(doc.toJson());
|
|
||||||
file.close();
|
|
||||||
QMessageBox::information(&dlg, tr("成功"), tr("列配置已保存"));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(&dlg, tr("错误"), tr("无法保存文件:%1").arg(file.errorString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(btnLoad, &QPushButton::clicked, this, [this, &dlg, colCheckBoxMap]() {
|
|
||||||
QString loadDir = QDir::currentPath() + "/columnConfigs";
|
|
||||||
QString fileName = QFileDialog::getOpenFileName(&dlg, tr("加载列配置"),
|
|
||||||
loadDir, "JSON Files (*.json)");
|
|
||||||
if (fileName.isEmpty()) return;
|
|
||||||
|
|
||||||
QFile file(fileName);
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
|
||||||
QMessageBox::warning(&dlg, tr("错误"), tr("无法打开文件:%1").arg(file.errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QByteArray data = file.readAll();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
QJsonParseError err;
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data, &err);
|
|
||||||
if (err.error != QJsonParseError::NoError || !doc.isObject()) {
|
|
||||||
QMessageBox::warning(&dlg, tr("错误"), tr("JSON解析失败"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject root = doc.object();
|
|
||||||
for (int col = 0; col < m_model->columnCount(); ++col) {
|
|
||||||
QString header = m_model->headerData(col, Qt::Horizontal).toString();
|
|
||||||
if (root.contains(header)) {
|
|
||||||
colCheckBoxMap[col]->blockSignals(true);
|
|
||||||
colCheckBoxMap[col]->setChecked(root[header].toBool(false));
|
|
||||||
colCheckBoxMap[col]->blockSignals(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 一次性更新列隐藏
|
|
||||||
for (int col : colCheckBoxMap.keys()) {
|
|
||||||
m_tableView->setColumnHidden(col, !colCheckBoxMap[col]->isChecked());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::reset()
|
|
||||||
{
|
|
||||||
m_model->blockSignals(true);
|
|
||||||
for (int row = 0; row < m_model->rowCount(); ++row) {
|
|
||||||
for (int col = 0; col < m_model->columnCount(); ++col) {
|
|
||||||
m_model->setData(m_model->index(row, col), QVariant());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_model->blockSignals(false);
|
|
||||||
emit m_model->dataChanged(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, m_model->columnCount() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::setColumnMapping(const QHash<QString, QString> &mapping)
|
|
||||||
{
|
|
||||||
m_columnToJsonKey = mapping;
|
|
||||||
// 构建反向映射(可选)
|
|
||||||
m_jsonKeyToColumn.clear();
|
|
||||||
for (auto it = m_columnToJsonKey.constBegin(); it != m_columnToJsonKey.constEnd(); ++it) {
|
|
||||||
m_jsonKeyToColumn[it.value()] = m_model->headerData(0, Qt::Horizontal, Qt::DisplayRole).toString().indexOf(it.key());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::InitViewWorkspace(const QString &project_name)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceConfigView::SetAnalyzeDataFilename(const QMap<QString, QVariant> &data_files_set)
|
|
||||||
{
|
|
||||||
if (data_files_set.isEmpty()) {
|
|
||||||
LOG_WARN("文件集合为空");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString filePath = data_files_set.first().toString();
|
|
||||||
LOG_INFO("读取文件: " + filePath);
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
#ifndef DEVICECONFIGVIEW_H
|
|
||||||
#define DEVICECONFIGVIEW_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QHash>
|
|
||||||
#include "MeasureAnalysisView.h"
|
|
||||||
|
|
||||||
class QTableView;
|
|
||||||
class QStandardItemModel;
|
|
||||||
class QPushButton;
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceConfigView : public MeasureAnalysisView
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DeviceConfigView(QWidget *parent = nullptr);
|
|
||||||
~DeviceConfigView();
|
|
||||||
|
|
||||||
|
|
||||||
bool loadJson(const QString &filePath);
|
|
||||||
|
|
||||||
|
|
||||||
bool saveJson(const QString &filePath);
|
|
||||||
|
|
||||||
|
|
||||||
QStandardItemModel* getModel() const;
|
|
||||||
|
|
||||||
|
|
||||||
void showColumnControlDialog();
|
|
||||||
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
|
|
||||||
void setColumnMapping(const QHash<QString, QString> &mapping);
|
|
||||||
|
|
||||||
virtual void InitViewWorkspace(const QString& project_name) override final;
|
|
||||||
virtual void SetAnalyzeDataFilename(const QMap<QString, QVariant>& data_files_set);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void dataChanged();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onActionButtonClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void initTableView();
|
|
||||||
void setupActionColumnButtons();
|
|
||||||
bool parseJsonImpl(const QByteArray &data);
|
|
||||||
QList<int> selectTargetChannels(int currentChannel) const;
|
|
||||||
|
|
||||||
QTableView *m_tableView;
|
|
||||||
QStandardItemModel *m_model;
|
|
||||||
QHash<QString, QString> m_columnToJsonKey; // 列头 -> JSON键名
|
|
||||||
QHash<QString, int> m_jsonKeyToColumn; // 反向映射,用于快速查找列索引
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // DEVICECONFIGVIEW_H
|
|
||||||
|
|
@ -1,333 +0,0 @@
|
||||||
#include "DeviceParameterConfig.h"
|
|
||||||
#include "DeviceParameterConfigList.h"
|
|
||||||
#include "DeviceConfigView.h"
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QTextEdit>
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DeviceParameterConfig::DeviceParameterConfig(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, m_configList(nullptr)
|
|
||||||
, m_configView(nullptr)
|
|
||||||
, m_lineEditFileName(nullptr)
|
|
||||||
, m_textEditRemark(nullptr)
|
|
||||||
, m_checkBoxSaveToDevice(nullptr)
|
|
||||||
, m_btnSave(nullptr)
|
|
||||||
, m_btnSetColumn(nullptr)
|
|
||||||
{
|
|
||||||
setupUi();
|
|
||||||
initColumnMapping(); // 设置默认映射
|
|
||||||
m_configView->setColumnMapping(m_columnToJsonKey);
|
|
||||||
m_configList->loadConfigsFromFolder(); // 加载默认目录下的配置文件
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceParameterConfig::~DeviceParameterConfig()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::setupUi()
|
|
||||||
{
|
|
||||||
// 主布局:左右分栏
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout(this);
|
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
mainLayout->setSpacing(10);
|
|
||||||
|
|
||||||
// 左侧:配置列表
|
|
||||||
m_configList = new DeviceParameterConfigList(this);
|
|
||||||
mainLayout->addWidget(m_configList, 1);
|
|
||||||
|
|
||||||
// 右侧:垂直布局
|
|
||||||
QVBoxLayout *rightLayout = new QVBoxLayout();
|
|
||||||
mainLayout->addLayout(rightLayout, 9);
|
|
||||||
|
|
||||||
// 右侧上部:文件名、保存按钮、备注说明
|
|
||||||
QHBoxLayout *topLayout = new QHBoxLayout();
|
|
||||||
QLabel *labelName = new QLabel(tr("配置命名:"), this);
|
|
||||||
m_lineEditFileName = new QLineEdit(this);
|
|
||||||
m_btnSave = new QPushButton(tr("保存到测量分析"), this);
|
|
||||||
m_checkBoxSaveToDevice = new QCheckBox(tr("保存到设备参数配置管理"), this);
|
|
||||||
topLayout->addWidget(labelName);
|
|
||||||
topLayout->addWidget(m_lineEditFileName, 1);
|
|
||||||
topLayout->addWidget(m_btnSave);
|
|
||||||
topLayout->addWidget(m_checkBoxSaveToDevice);
|
|
||||||
rightLayout->addLayout(topLayout);
|
|
||||||
|
|
||||||
QHBoxLayout *remarkLayout = new QHBoxLayout();
|
|
||||||
QLabel *labelRemark = new QLabel(tr("备注说明:"), this);
|
|
||||||
m_textEditRemark = new QTextEdit(this);
|
|
||||||
m_textEditRemark->setMaximumHeight(80);
|
|
||||||
remarkLayout->addWidget(labelRemark);
|
|
||||||
remarkLayout->addWidget(m_textEditRemark, 1);
|
|
||||||
rightLayout->addLayout(remarkLayout);
|
|
||||||
|
|
||||||
// 右侧中部:设置列按钮
|
|
||||||
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
|
||||||
m_btnSetColumn = new QPushButton(tr("设置列"), this);
|
|
||||||
buttonLayout->addWidget(m_btnSetColumn);
|
|
||||||
buttonLayout->addStretch();
|
|
||||||
rightLayout->addLayout(buttonLayout);
|
|
||||||
|
|
||||||
// 右侧下部:参数表格视图
|
|
||||||
m_configView = new DeviceConfigView(this);
|
|
||||||
rightLayout->addWidget(m_configView, 1);
|
|
||||||
|
|
||||||
// 连接信号槽
|
|
||||||
connect(m_configList, &DeviceParameterConfigList::configSelected,
|
|
||||||
this, &DeviceParameterConfig::onConfigSelected);
|
|
||||||
connect(m_configList, &DeviceParameterConfigList::configDeleted,
|
|
||||||
this, &DeviceParameterConfig::onConfigDeleted);
|
|
||||||
connect(m_btnSave, &QPushButton::clicked,
|
|
||||||
this, &DeviceParameterConfig::onSaveButtonClicked);
|
|
||||||
connect(m_btnSetColumn, &QPushButton::clicked,
|
|
||||||
this, &DeviceParameterConfig::onSetColumnButtonClicked);
|
|
||||||
connect(m_configList, &DeviceParameterConfigList::createNewConfigRequested,
|
|
||||||
this, &DeviceParameterConfig::onCreateNewConfigRequested);
|
|
||||||
connect(m_configView, &DeviceConfigView::dataChanged,
|
|
||||||
this, [this]() {
|
|
||||||
// 数据改变时,在文件名后添加星号表示未保存
|
|
||||||
if (!m_lineEditFileName->text().isEmpty() && !m_lineEditFileName->text().endsWith(" *")) {
|
|
||||||
m_lineEditFileName->setText(m_lineEditFileName->text() + " *");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::initColumnMapping()
|
|
||||||
{
|
|
||||||
// 与原 EquipmentParameterSettingManagement 完全相同的映射
|
|
||||||
m_columnToJsonKey.clear();
|
|
||||||
m_columnToJsonKey[tr("数据传输模式")] = "eTransferModel";
|
|
||||||
m_columnToJsonKey[tr("硬件增益")] = "iDeviceGain";
|
|
||||||
m_columnToJsonKey[tr("硬件增益选择索引")] = "iDeviceGainSelectIndex";
|
|
||||||
m_columnToJsonKey[tr("软件增益")] = "iSoftGain";
|
|
||||||
m_columnToJsonKey[tr("时间常数")] = "dConstTime";
|
|
||||||
m_columnToJsonKey[tr("成形时间")] = "iFormTime";
|
|
||||||
m_columnToJsonKey[tr("快通道触发阈值")] = "iFastChannelTrigerValue";
|
|
||||||
m_columnToJsonKey[tr("多道分辨率")] = "iChannelNum";
|
|
||||||
m_columnToJsonKey[tr("控制功能")] = "";
|
|
||||||
m_columnToJsonKey[tr("幅度提前延迟")] = "";
|
|
||||||
m_columnToJsonKey[tr("积分长度")] = "";
|
|
||||||
m_columnToJsonKey[tr("dcfd缩放倍数")] = "";
|
|
||||||
m_columnToJsonKey[tr("dcfd延迟")] = "";
|
|
||||||
m_columnToJsonKey[tr("直流偏移")] = "iCurrentOffset";
|
|
||||||
m_columnToJsonKey[tr("最大能量范围")] = "iMaxEnergy";
|
|
||||||
m_columnToJsonKey[tr("Am 峰面积寻峰法的面积比例")] = "iAMPeakDiv";
|
|
||||||
m_columnToJsonKey[tr("K40与 Am241的峰位校正系数")] = "iHVDelt";
|
|
||||||
m_columnToJsonKey[tr("高压关断阈值")] = "iHVDelt";
|
|
||||||
m_columnToJsonKey[tr("获取能谱周期")] = "iGetSpecturmPeirod";
|
|
||||||
m_columnToJsonKey[tr("总测量时间")] = "iTotalMeasureTime";
|
|
||||||
m_columnToJsonKey[tr("总测量次数")] = "iTotalMeasureCount";
|
|
||||||
m_columnToJsonKey[tr("滤波参数")] = "iTrapeTopShitBit";
|
|
||||||
m_columnToJsonKey[tr("上升时间")] = "iRiseTime";
|
|
||||||
m_columnToJsonKey[tr("平顶时间")] = "iTopTime";
|
|
||||||
m_columnToJsonKey[tr("ICR 校正使能")] = "bICRCorrect";
|
|
||||||
m_columnToJsonKey[tr("CRZA 值")] = "iCRZAValue";
|
|
||||||
m_columnToJsonKey[tr("ZA 使能值")] = "iZAEnable";
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::setColumnMapping(const QHash<QString, QString> &mapping)
|
|
||||||
{
|
|
||||||
m_columnToJsonKey = mapping;
|
|
||||||
m_configView->setColumnMapping(mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceParameterConfig::loadConfig(const QString &filePath)
|
|
||||||
{
|
|
||||||
if (!m_configView->loadJson(filePath))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_currentFilePath = filePath;
|
|
||||||
QFileInfo info(filePath);
|
|
||||||
m_lineEditFileName->setText(info.fileName());
|
|
||||||
|
|
||||||
// 读取 JSON 中的备注字段
|
|
||||||
QFile file(filePath);
|
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
|
||||||
QByteArray data = file.readAll();
|
|
||||||
file.close();
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
||||||
if (doc.isObject()) {
|
|
||||||
QJsonObject obj = doc.object();
|
|
||||||
if (obj.contains("remark")) {
|
|
||||||
m_textEditRemark->setPlainText(obj["remark"].toString());
|
|
||||||
} else {
|
|
||||||
m_textEditRemark->clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit configLoaded(filePath); // 此信号未在头文件中声明,可添加;若不需要可移除
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceParameterConfig::saveCurrentConfig()
|
|
||||||
{
|
|
||||||
if (m_currentFilePath.isEmpty()) {
|
|
||||||
QMessageBox::warning(this, tr("错误"), tr("没有选中的配置文件"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存表格数据
|
|
||||||
if (!m_configView->saveJson(m_currentFilePath))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// 保存备注到 JSON
|
|
||||||
QFile file(m_currentFilePath);
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
|
||||||
qWarning() << "无法打开文件读取备注:" << file.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QByteArray data = file.readAll();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
||||||
if (!doc.isObject()) {
|
|
||||||
qWarning() << "JSON 不是对象";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QJsonObject root = doc.object();
|
|
||||||
root["remark"] = m_textEditRemark->toPlainText();
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::WriteOnly)) {
|
|
||||||
qWarning() << "无法写入文件:" << file.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file.write(QJsonDocument(root).toJson());
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
// 移除文件名后的星号
|
|
||||||
QString fileName = m_lineEditFileName->text();
|
|
||||||
if (fileName.endsWith(" *"))
|
|
||||||
fileName.chop(2);
|
|
||||||
m_lineEditFileName->setText(fileName);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DeviceParameterConfig::getCurrentFileName() const
|
|
||||||
{
|
|
||||||
return QFileInfo(m_currentFilePath).fileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DeviceParameterConfig::getRemark() const
|
|
||||||
{
|
|
||||||
return m_textEditRemark->toPlainText();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::setRemark(const QString &remark)
|
|
||||||
{
|
|
||||||
m_textEditRemark->setPlainText(remark);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::onConfigSelected(const QString &filePath)
|
|
||||||
{
|
|
||||||
loadConfig(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::onConfigDeleted(const QString &fileName)
|
|
||||||
{
|
|
||||||
if (m_lineEditFileName->text() == fileName) {
|
|
||||||
m_lineEditFileName->clear();
|
|
||||||
m_textEditRemark->clear();
|
|
||||||
m_configView->reset();
|
|
||||||
m_currentFilePath.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::onCreateNewConfigRequested(const QString &fileName)
|
|
||||||
{
|
|
||||||
QString filePath = QDir::currentPath() + "/parameterConfig/" + fileName;
|
|
||||||
if (createDefaultConfigFile(filePath)) {
|
|
||||||
// 刷新列表
|
|
||||||
m_configList->refresh();
|
|
||||||
// 选中新建的文件
|
|
||||||
m_configList->setCurrentFile(fileName);
|
|
||||||
// 自动加载该配置(可选)
|
|
||||||
loadConfig(filePath);
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, tr("错误"), tr("无法创建配置文件:%1").arg(filePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::onSaveButtonClicked()
|
|
||||||
{
|
|
||||||
if (!saveCurrentConfig()) {
|
|
||||||
QMessageBox::warning(this, tr("错误"), tr("保存配置文件失败"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果勾选了“保存到设备参数配置管理”,刷新左侧列表
|
|
||||||
if (m_checkBoxSaveToDevice->isChecked()) {
|
|
||||||
m_configList->refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发出信号,供外部处理(例如将参数发送到测量分析模块)
|
|
||||||
emit saveToMeasurementRequested(m_currentFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfig::onSetColumnButtonClicked()
|
|
||||||
{
|
|
||||||
m_configView->showColumnControlDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceParameterConfig::createDefaultConfigFile(const QString &filePath)
|
|
||||||
{
|
|
||||||
// 创建默认配置文件(含 32 个通道)
|
|
||||||
QJsonObject rootObj;
|
|
||||||
rootObj["command"] = "SET";
|
|
||||||
QJsonArray channelsArray;
|
|
||||||
|
|
||||||
QJsonObject defaultChannel;
|
|
||||||
defaultChannel["eTransferModel"] = "eSpecturmMode";
|
|
||||||
defaultChannel["iDeviceGain"] = 1;
|
|
||||||
defaultChannel["iDeviceGainSelectIndex"] = 1;
|
|
||||||
defaultChannel["iSoftGain"] = 3000;
|
|
||||||
defaultChannel["dConstTime"] = 45.0;
|
|
||||||
defaultChannel["iFormTime"] = 3;
|
|
||||||
defaultChannel["iFastChannelTrigerValue"] = 10.0;
|
|
||||||
defaultChannel["iChannelNum"] = 1024;
|
|
||||||
defaultChannel["iHighVoltage"] = 0;
|
|
||||||
defaultChannel["iInputVoltageDesc"] = 0;
|
|
||||||
defaultChannel["iCRDivMode"] = 0;
|
|
||||||
defaultChannel["iInputSignalPostive"] = 0;
|
|
||||||
defaultChannel["iCurrentOffset"] = 0;
|
|
||||||
defaultChannel["iMaxEnergy"] = 0;
|
|
||||||
defaultChannel["iAMPeakDiv"] = 0;
|
|
||||||
defaultChannel["iHVDelt"] = 0;
|
|
||||||
defaultChannel["iHVCtrl"] = 0;
|
|
||||||
defaultChannel["iGetSpecturmPeirod"] = 1;
|
|
||||||
defaultChannel["iTotalMeasureTime"] = 10;
|
|
||||||
defaultChannel["iTotalMeasureCount"] = 1;
|
|
||||||
defaultChannel["iTrapeTopShitBit"] = 0;
|
|
||||||
defaultChannel["iRiseTime"] = 2;
|
|
||||||
defaultChannel["iTopTime"] = 2;
|
|
||||||
defaultChannel["bICRCorrect"] = false;
|
|
||||||
defaultChannel["iCRZAValue"] = 0;
|
|
||||||
defaultChannel["iZAEnable"] = 30;
|
|
||||||
defaultChannel["reserve"] = QJsonArray();
|
|
||||||
defaultChannel["pUserConfigInfo"] = QJsonObject();
|
|
||||||
|
|
||||||
for (int i = 0; i < 32; ++i) {
|
|
||||||
channelsArray.append(defaultChannel);
|
|
||||||
}
|
|
||||||
rootObj["channels"] = channelsArray;
|
|
||||||
rootObj["remark"] = "";
|
|
||||||
|
|
||||||
QJsonDocument doc(rootObj);
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::WriteOnly))
|
|
||||||
return false;
|
|
||||||
file.write(doc.toJson());
|
|
||||||
file.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
#ifndef DEVICEPARAMETERCONFIG_H
|
|
||||||
#define DEVICEPARAMETERCONFIG_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QHash>
|
|
||||||
|
|
||||||
class DeviceParameterConfigList;
|
|
||||||
class DeviceConfigView;
|
|
||||||
class QLineEdit;
|
|
||||||
class QTextEdit;
|
|
||||||
class QCheckBox;
|
|
||||||
class QPushButton;
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceParameterConfig : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DeviceParameterConfig(QWidget *parent = nullptr);
|
|
||||||
~DeviceParameterConfig();
|
|
||||||
|
|
||||||
|
|
||||||
void setColumnMapping(const QHash<QString, QString> &mapping);
|
|
||||||
|
|
||||||
|
|
||||||
bool loadConfig(const QString &filePath);
|
|
||||||
|
|
||||||
|
|
||||||
bool saveCurrentConfig();
|
|
||||||
|
|
||||||
|
|
||||||
QString getCurrentFileName() const;
|
|
||||||
|
|
||||||
|
|
||||||
QString getRemark() const;
|
|
||||||
|
|
||||||
|
|
||||||
void setRemark(const QString &remark);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void saveToMeasurementRequested(const QString &filePath);
|
|
||||||
|
|
||||||
void configLoaded(QString );
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onConfigSelected(const QString &filePath);
|
|
||||||
void onConfigDeleted(const QString &fileName);
|
|
||||||
void onCreateNewConfigRequested(const QString &fileName);
|
|
||||||
void onSaveButtonClicked();
|
|
||||||
void onSetColumnButtonClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setupUi();
|
|
||||||
bool createDefaultConfigFile(const QString &filePath);
|
|
||||||
void initColumnMapping(); // 初始化默认映射(若外部未调用则使用默认)
|
|
||||||
|
|
||||||
// 子控件
|
|
||||||
DeviceParameterConfigList *m_configList;
|
|
||||||
DeviceConfigView *m_configView;
|
|
||||||
|
|
||||||
// 周边控件
|
|
||||||
QLineEdit *m_lineEditFileName;
|
|
||||||
QTextEdit *m_textEditRemark;
|
|
||||||
QCheckBox *m_checkBoxSaveToDevice;
|
|
||||||
QPushButton *m_btnSave;
|
|
||||||
QPushButton *m_btnSetColumn;
|
|
||||||
|
|
||||||
QString m_currentFilePath;
|
|
||||||
QHash<QString, QString> m_columnToJsonKey; // 列头->JSON键映射
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // DEVICEPARAMETERCONFIG_H
|
|
||||||
|
|
@ -1,214 +0,0 @@
|
||||||
#include "DeviceParameterConfigList.h"
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QLabel>
|
|
||||||
DeviceParameterConfigList::DeviceParameterConfigList(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, m_listWidget(nullptr)
|
|
||||||
, m_btnAdd(nullptr)
|
|
||||||
, m_btnDelete(nullptr)
|
|
||||||
{
|
|
||||||
setupUi();
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceParameterConfigList::~DeviceParameterConfigList()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::setupUi()
|
|
||||||
{
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
|
|
||||||
QLabel *ListWidgetName = new QLabel("设备参数配置列表");
|
|
||||||
mainLayout->addWidget(ListWidgetName);
|
|
||||||
|
|
||||||
m_listWidget = new QListWidget(this);
|
|
||||||
mainLayout->addWidget(m_listWidget);
|
|
||||||
|
|
||||||
QHBoxLayout *btnLayout = new QHBoxLayout();
|
|
||||||
m_btnAdd = new QPushButton(tr("添加"), this);
|
|
||||||
m_btnDelete = new QPushButton(tr("删除"), this);
|
|
||||||
btnLayout->addWidget(m_btnAdd);
|
|
||||||
btnLayout->addWidget(m_btnDelete);
|
|
||||||
btnLayout->addStretch();
|
|
||||||
mainLayout->addLayout(btnLayout);
|
|
||||||
|
|
||||||
connect(m_listWidget, &QListWidget::itemClicked, this, &DeviceParameterConfigList::onItemClicked);
|
|
||||||
connect(m_btnAdd, &QPushButton::clicked, this, &DeviceParameterConfigList::onAddClicked);
|
|
||||||
connect(m_btnDelete, &QPushButton::clicked, this, &DeviceParameterConfigList::onDeleteClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::loadConfigsFromFolder(const QString &folderPath)
|
|
||||||
{
|
|
||||||
if (folderPath.isEmpty()) {
|
|
||||||
m_folderPath = QDir::currentPath() + "/parameterConfig";
|
|
||||||
} else {
|
|
||||||
m_folderPath = folderPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir dir(m_folderPath);
|
|
||||||
if (!dir.exists()) {
|
|
||||||
dir.mkpath(m_folderPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
|
|
||||||
QStringList files = dir.entryList();
|
|
||||||
updateList(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::updateList(const QStringList &fileList)
|
|
||||||
{
|
|
||||||
m_listWidget->clear();
|
|
||||||
for (const QString &file : fileList) {
|
|
||||||
if (file.endsWith(".json", Qt::CaseInsensitive)) {
|
|
||||||
m_listWidget->addItem(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DeviceParameterConfigList::getCurrentFilePath() const
|
|
||||||
{
|
|
||||||
QListWidgetItem *item = m_listWidget->currentItem();
|
|
||||||
if (!item) return QString();
|
|
||||||
return m_folderPath + "/" + item->text();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DeviceParameterConfigList::getCurrentFileName() const
|
|
||||||
{
|
|
||||||
QListWidgetItem *item = m_listWidget->currentItem();
|
|
||||||
return item ? item->text() : QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::setCurrentFile(const QString &fileName)
|
|
||||||
{
|
|
||||||
QList<QListWidgetItem*> items = m_listWidget->findItems(fileName, Qt::MatchExactly);
|
|
||||||
if (!items.isEmpty()) {
|
|
||||||
m_listWidget->setCurrentItem(items.first());
|
|
||||||
emit configSelected(getCurrentFilePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::refresh()
|
|
||||||
{
|
|
||||||
loadConfigsFromFolder(m_folderPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::onItemClicked(QListWidgetItem *item)
|
|
||||||
{
|
|
||||||
if (item) {
|
|
||||||
emit configSelected(m_folderPath + "/" + item->text());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::onAddClicked()
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
QString fileName = QInputDialog::getText(this, tr("新建配置"),
|
|
||||||
tr("请输入配置文件名(无需后缀):"),
|
|
||||||
QLineEdit::Normal,
|
|
||||||
QString("NewConfig_%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss")),
|
|
||||||
&ok);
|
|
||||||
if (!ok || fileName.isEmpty()) return;
|
|
||||||
|
|
||||||
if (!fileName.endsWith(".json", Qt::CaseInsensitive))
|
|
||||||
fileName += ".json";
|
|
||||||
|
|
||||||
QString filePath = m_folderPath + "/" + fileName;
|
|
||||||
if (QFile::exists(filePath)) {
|
|
||||||
QMessageBox::warning(this, tr("错误"), tr("文件已存在,请使用其他名称。"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发出创建请求,由外部(主窗口)决定默认内容
|
|
||||||
emit createNewConfigRequested(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterConfigList::onDeleteClicked()
|
|
||||||
{
|
|
||||||
QListWidgetItem *currentItem = m_listWidget->currentItem();
|
|
||||||
if (!currentItem) {
|
|
||||||
QMessageBox::information(this, tr("提示"), tr("请先选择要删除的配置文件。"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString fileName = currentItem->text();
|
|
||||||
QString filePath = m_folderPath + "/" + fileName;
|
|
||||||
|
|
||||||
int ret = QMessageBox::question(this, tr("确认删除"),
|
|
||||||
tr("确定要删除文件 \"%1\" 吗?").arg(fileName),
|
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
|
||||||
if (ret != QMessageBox::Yes) return;
|
|
||||||
|
|
||||||
QFile file(filePath);
|
|
||||||
if (file.remove()) {
|
|
||||||
delete currentItem;
|
|
||||||
emit configDeleted(fileName);
|
|
||||||
QMessageBox::information(this, tr("成功"), tr("文件已删除。"));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, tr("错误"), tr("无法删除文件:%1").arg(file.errorString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceParameterConfigList::createDefaultConfigFile(const QString &filePath)
|
|
||||||
{
|
|
||||||
// 默认配置内容(与原来保持一致)
|
|
||||||
QJsonObject rootObj;
|
|
||||||
rootObj["command"] = "SET";
|
|
||||||
QJsonArray channelsArray;
|
|
||||||
|
|
||||||
QJsonObject defaultChannel;
|
|
||||||
defaultChannel["eTransferModel"] = "eSpecturmMode";
|
|
||||||
defaultChannel["iDeviceGain"] = 1;
|
|
||||||
defaultChannel["iDeviceGainSelectIndex"] = 1;
|
|
||||||
defaultChannel["iSoftGain"] = 3000;
|
|
||||||
defaultChannel["dConstTime"] = 45.0;
|
|
||||||
defaultChannel["iFormTime"] = 3;
|
|
||||||
defaultChannel["iFastChannelTrigerValue"] = 10.0;
|
|
||||||
defaultChannel["iChannelNum"] = 1024;
|
|
||||||
defaultChannel["iHighVoltage"] = 0;
|
|
||||||
defaultChannel["iInputVoltageDesc"] = 0;
|
|
||||||
defaultChannel["iCRDivMode"] = 0;
|
|
||||||
defaultChannel["iInputSignalPostive"] = 0;
|
|
||||||
defaultChannel["iCurrentOffset"] = 0;
|
|
||||||
defaultChannel["iMaxEnergy"] = 0;
|
|
||||||
defaultChannel["iAMPeakDiv"] = 0;
|
|
||||||
defaultChannel["iHVDelt"] = 0;
|
|
||||||
defaultChannel["iHVCtrl"] = 0;
|
|
||||||
defaultChannel["iGetSpecturmPeirod"] = 1;
|
|
||||||
defaultChannel["iTotalMeasureTime"] = 10;
|
|
||||||
defaultChannel["iTotalMeasureCount"] = 1;
|
|
||||||
defaultChannel["iTrapeTopShitBit"] = 0;
|
|
||||||
defaultChannel["iRiseTime"] = 2;
|
|
||||||
defaultChannel["iTopTime"] = 2;
|
|
||||||
defaultChannel["bICRCorrect"] = false;
|
|
||||||
defaultChannel["iCRZAValue"] = 0;
|
|
||||||
defaultChannel["iZAEnable"] = 30;
|
|
||||||
defaultChannel["reserve"] = QJsonArray();
|
|
||||||
defaultChannel["pUserConfigInfo"] = QJsonObject();
|
|
||||||
|
|
||||||
for (int i = 0; i < 32; ++i) {
|
|
||||||
channelsArray.append(defaultChannel);
|
|
||||||
}
|
|
||||||
rootObj["channels"] = channelsArray;
|
|
||||||
|
|
||||||
QJsonDocument doc(rootObj);
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::WriteOnly)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file.write(doc.toJson());
|
|
||||||
file.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
#ifndef DEVICEPARAMETERCONFIGLIST_H
|
|
||||||
#define DEVICEPARAMETERCONFIGLIST_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QListWidgetItem>
|
|
||||||
|
|
||||||
class QListWidget;
|
|
||||||
class QPushButton;
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceParameterConfigList : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DeviceParameterConfigList(QWidget *parent = nullptr);
|
|
||||||
~DeviceParameterConfigList();
|
|
||||||
|
|
||||||
|
|
||||||
void loadConfigsFromFolder(const QString &folderPath = QString());
|
|
||||||
|
|
||||||
|
|
||||||
QString getCurrentFilePath() const;
|
|
||||||
|
|
||||||
|
|
||||||
QString getCurrentFileName() const;
|
|
||||||
|
|
||||||
|
|
||||||
void setCurrentFile(const QString &fileName);
|
|
||||||
|
|
||||||
void refresh();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
void configSelected(const QString &filePath);
|
|
||||||
|
|
||||||
void configDeleted(const QString &fileName);
|
|
||||||
|
|
||||||
void createNewConfigRequested(const QString &fileName);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onItemClicked(QListWidgetItem *item);
|
|
||||||
void onAddClicked();
|
|
||||||
void onDeleteClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setupUi();
|
|
||||||
void updateList(const QStringList &fileList);
|
|
||||||
bool createDefaultConfigFile(const QString &filePath);
|
|
||||||
|
|
||||||
QListWidget *m_listWidget;
|
|
||||||
QPushButton *m_btnAdd;
|
|
||||||
QPushButton *m_btnDelete;
|
|
||||||
QString m_folderPath;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // DEVICEPARAMETERCONFIGLIST_H
|
|
||||||
|
|
@ -1,384 +0,0 @@
|
||||||
#include "DeviceParameterProxy.h"
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include <QSpinBox>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QToolTip>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QKeyEvent>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QRegularExpressionValidator>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
DeviceParameterProxy::DeviceParameterProxy(QObject *parent) : QStyledItemDelegate(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* DeviceParameterProxy::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
int col = index.column();
|
|
||||||
switch (col)
|
|
||||||
{
|
|
||||||
case 0: // 数据传输模式(枚举)
|
|
||||||
{
|
|
||||||
QComboBox *combo = new QComboBox(parent);
|
|
||||||
combo->addItems(QStringList() << "谱线模式" << "波形模式" << "ADC模式" << "列表模式" << "α/β模式");
|
|
||||||
return combo;
|
|
||||||
}
|
|
||||||
case 1: // 硬件增益(档位)
|
|
||||||
{
|
|
||||||
QComboBox *combo = new QComboBox(parent);
|
|
||||||
combo->addItems(QStringList() << "1" << "2" << "4" << "8" << "16");
|
|
||||||
return combo;
|
|
||||||
}
|
|
||||||
case 2: // 硬件增益选择索引
|
|
||||||
{
|
|
||||||
QComboBox *combo = new QComboBox(parent);
|
|
||||||
combo->addItems(QStringList() << "1" << "2" << "3" << "4" << "5");
|
|
||||||
return combo;
|
|
||||||
}
|
|
||||||
case 3: // 软件增益(32位无符号)
|
|
||||||
{
|
|
||||||
QLineEdit *edit = new QLineEdit(parent);
|
|
||||||
edit->setValidator(new UInt32Validator(edit));
|
|
||||||
edit->setProperty("rangeHint", "0 ~ 4294967295");
|
|
||||||
edit->installEventFilter(const_cast<DeviceParameterProxy*>(this));
|
|
||||||
return edit;
|
|
||||||
}
|
|
||||||
case 4: // 时间常数(double μs)
|
|
||||||
{
|
|
||||||
QDoubleSpinBox *spin = new QDoubleSpinBox(parent);
|
|
||||||
spin->setRange(0.0, 1000.0);
|
|
||||||
spin->setSingleStep(1.0);
|
|
||||||
spin->setDecimals(2);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 5: // 成形时间(int μs)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(1, 10);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 6: // 快通道触发阈值(double 0.1mV)
|
|
||||||
{
|
|
||||||
QDoubleSpinBox *spin = new QDoubleSpinBox(parent);
|
|
||||||
spin->setRange(0.0, 10000.0);
|
|
||||||
spin->setSingleStep(0.1);
|
|
||||||
spin->setDecimals(1);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 7: // 多道分辨率(2的幂)
|
|
||||||
{
|
|
||||||
QComboBox *combo = new QComboBox(parent);
|
|
||||||
combo->addItems(QStringList() << "256" << "512" << "1024" << "2048" << "4096" << "8192" << "16384");
|
|
||||||
return combo;
|
|
||||||
}
|
|
||||||
case 8: // 控制功能(位掩码,暂用十进制输入)
|
|
||||||
{
|
|
||||||
QLineEdit *edit = new QLineEdit(parent);
|
|
||||||
// 允许输入十进制数字,不设范围限制(业务层处理)
|
|
||||||
return edit;
|
|
||||||
}
|
|
||||||
case 9: // 幅度提前延迟(unsigned char)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 255);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 10: // 积分长度(unsigned char)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 255);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 11: // dcfd缩放倍数(unsigned char)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 255);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 12: // dcfd延迟(unsigned char)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 255);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 13: // 直流偏移(mV)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(-1000, 1000);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 14: // 最大能量范围(keV)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 99999);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 15: // Am峰面积寻峰法的面积比例(%)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 100);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 16: // K40与Am241的峰位校正系数(short)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(-32768, 32767);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 17: // 高压关断阈值(short)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(-32768, 32767);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 18: // 获取能谱周期(秒)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 86400); // 一天
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 19: // 总测量时间(__int64,64位)
|
|
||||||
{
|
|
||||||
QLineEdit *edit = new QLineEdit(parent);
|
|
||||||
edit->setValidator(new Int64Validator(edit));
|
|
||||||
edit->setProperty("rangeHint", "0 ~ 9223372036854775807");
|
|
||||||
edit->installEventFilter(const_cast<DeviceParameterProxy*>(this));
|
|
||||||
return edit;
|
|
||||||
}
|
|
||||||
case 20: // 总测量次数
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 1000000); // 可调大
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 21: // 滤波参数
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 3);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 22: // 上升时间(μs)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(1, 255);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 23: // 平顶时间(μs)
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(1, 255);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 24: // ICR校正使能(布尔)
|
|
||||||
{
|
|
||||||
QComboBox *combo = new QComboBox(parent);
|
|
||||||
combo->addItems(QStringList() << "关闭" << "启用");
|
|
||||||
return combo;
|
|
||||||
}
|
|
||||||
case 25: // CRZA值
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 1000000); // 合理范围
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
case 26: // ZA使能值
|
|
||||||
{
|
|
||||||
QSpinBox *spin = new QSpinBox(parent);
|
|
||||||
spin->setRange(0, 100);
|
|
||||||
return spin;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return new QLineEdit(parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterProxy::setEditorData(QWidget *editor, const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
QVariant value = index.data(Qt::EditRole);
|
|
||||||
int col = index.column();
|
|
||||||
|
|
||||||
switch (col)
|
|
||||||
{
|
|
||||||
case 0: // QComboBox
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 7:
|
|
||||||
case 24:
|
|
||||||
{
|
|
||||||
QComboBox *combo = qobject_cast<QComboBox*>(editor);
|
|
||||||
if (combo) {
|
|
||||||
int idx = combo->findText(value.toString());
|
|
||||||
if (idx >= 0) combo->setCurrentIndex(idx);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // QLineEdit(软件增益)
|
|
||||||
case 8: // QLineEdit(控制功能)
|
|
||||||
case 19: // QLineEdit(总测量时间)
|
|
||||||
{
|
|
||||||
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
|
||||||
if (edit) edit->setText(value.toString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: // QDoubleSpinBox
|
|
||||||
case 6:
|
|
||||||
{
|
|
||||||
QDoubleSpinBox *spin = qobject_cast<QDoubleSpinBox*>(editor);
|
|
||||||
if (spin) spin->setValue(value.toDouble());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5: // QSpinBox
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
case 11:
|
|
||||||
case 12:
|
|
||||||
case 13:
|
|
||||||
case 14:
|
|
||||||
case 15:
|
|
||||||
case 16:
|
|
||||||
case 17:
|
|
||||||
case 18:
|
|
||||||
case 20:
|
|
||||||
case 21:
|
|
||||||
case 22:
|
|
||||||
case 23:
|
|
||||||
case 25:
|
|
||||||
case 26:
|
|
||||||
{
|
|
||||||
QSpinBox *spin = qobject_cast<QSpinBox*>(editor);
|
|
||||||
if (spin) spin->setValue(value.toInt());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
|
||||||
if (edit) edit->setText(value.toString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterProxy::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
int col = index.column();
|
|
||||||
|
|
||||||
switch (col)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
case 7:
|
|
||||||
case 24:
|
|
||||||
{
|
|
||||||
QComboBox *combo = qobject_cast<QComboBox*>(editor);
|
|
||||||
if (combo) model->setData(index, combo->currentText());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // 软件增益(字符串存储,因为可能超出int范围)
|
|
||||||
case 8: // 控制功能(字符串存储)
|
|
||||||
case 19: // 总测量时间(字符串存储)
|
|
||||||
{
|
|
||||||
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
|
||||||
// if (edit) model->setData(index, edit->text());
|
|
||||||
if (edit) {
|
|
||||||
// 提交前再次验证(防止通过回车提交无效数据)
|
|
||||||
QString text = edit->text();
|
|
||||||
int pos = 0;
|
|
||||||
if (edit->validator() && edit->validator()->validate(text, pos) == QValidator::Acceptable) {
|
|
||||||
model->setData(index, text);
|
|
||||||
} else {
|
|
||||||
// 无效数据不写入模型,并显示提示
|
|
||||||
QString rangeHint = edit->property("rangeHint").toString();
|
|
||||||
QPoint pos = edit->mapToGlobal(edit->rect().topRight());
|
|
||||||
QToolTip::showText(pos, QString("取值范围: %1").arg(rangeHint), edit);
|
|
||||||
// 焦点留在编辑器(但此时编辑器即将销毁,所以需要延迟重新打开?)
|
|
||||||
// 实际上 setModelData 被调用时编辑器即将销毁,我们无法阻止。
|
|
||||||
// 因此更好的方法是在事件过滤器中拦截回车,避免走到这里。
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
case 6:
|
|
||||||
{
|
|
||||||
QDoubleSpinBox *spin = qobject_cast<QDoubleSpinBox*>(editor);
|
|
||||||
if (spin) model->setData(index, spin->value());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5:
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
case 11:
|
|
||||||
case 12:
|
|
||||||
case 13:
|
|
||||||
case 14:
|
|
||||||
case 15:
|
|
||||||
case 16:
|
|
||||||
case 17:
|
|
||||||
case 18:
|
|
||||||
case 20:
|
|
||||||
case 21:
|
|
||||||
case 22:
|
|
||||||
case 23:
|
|
||||||
case 25:
|
|
||||||
case 26:
|
|
||||||
{
|
|
||||||
QSpinBox *spin = qobject_cast<QSpinBox*>(editor);
|
|
||||||
if (spin) model->setData(index, spin->value());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
|
||||||
if (edit) model->setData(index, edit->text());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceParameterProxy::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
editor->setGeometry(option.rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceParameterProxy::eventFilter(QObject *obj, QEvent *event)
|
|
||||||
{
|
|
||||||
QLineEdit *edit = qobject_cast<QLineEdit*>(obj);
|
|
||||||
if (!edit || !edit->validator())
|
|
||||||
return QStyledItemDelegate::eventFilter(obj, event);
|
|
||||||
|
|
||||||
if (event->type() == QEvent::FocusOut) {
|
|
||||||
QString text = edit->text();
|
|
||||||
int pos = 0;
|
|
||||||
if (edit->validator()->validate(text, pos) != QValidator::Acceptable) {
|
|
||||||
QString rangeHint = edit->property("rangeHint").toString();
|
|
||||||
QPoint pos = edit->mapToGlobal(edit->rect().topRight());
|
|
||||||
QToolTip::showText(pos, QString("取值范围: %1").arg(rangeHint), edit);
|
|
||||||
// 延迟重新获得焦点
|
|
||||||
QTimer::singleShot(0, edit, SLOT(setFocus()));
|
|
||||||
return true; // 阻止焦点离开
|
|
||||||
} else {
|
|
||||||
QToolTip::hideText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type() == QEvent::KeyPress) {
|
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
|
||||||
if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
|
|
||||||
QString text = edit->text();
|
|
||||||
int pos = 0;
|
|
||||||
if (edit->validator()->validate(text, pos) != QValidator::Acceptable) {
|
|
||||||
QString rangeHint = edit->property("rangeHint").toString();
|
|
||||||
QPoint pos = edit->mapToGlobal(edit->rect().topRight());
|
|
||||||
QToolTip::showText(pos, QString("取值范围: %1").arg(rangeHint), edit);
|
|
||||||
return true; // 拦截回车,不提交
|
|
||||||
} else {
|
|
||||||
QToolTip::hideText();
|
|
||||||
// 允许回车提交,Qt 会正常处理
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QStyledItemDelegate::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
#ifndef DEVICEPARAMETERPROXY_H
|
|
||||||
#define DEVICEPARAMETERPROXY_H
|
|
||||||
|
|
||||||
#include <QStyledItemDelegate>
|
|
||||||
#include <QIntValidator>
|
|
||||||
#include <QLineEdit>
|
|
||||||
|
|
||||||
// ==================== 自定义验证器 ====================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 无符号32位整数验证器(范围 0 ~ 4294967295)
|
|
||||||
*/
|
|
||||||
class UInt32Validator : public QValidator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UInt32Validator(QObject *parent = nullptr) : QValidator(parent) {}
|
|
||||||
|
|
||||||
State validate(QString &input, int &pos) const override
|
|
||||||
{
|
|
||||||
if (input.isEmpty())
|
|
||||||
return Intermediate;
|
|
||||||
|
|
||||||
bool ok;
|
|
||||||
quint64 value = input.toULongLong(&ok);
|
|
||||||
if (!ok)
|
|
||||||
return Invalid;
|
|
||||||
|
|
||||||
if (value <= 4294967295ULL)
|
|
||||||
return Acceptable;
|
|
||||||
|
|
||||||
return Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fixup(QString &input) const override
|
|
||||||
{
|
|
||||||
input.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 有符号64位整数验证器(范围 0 ~ 9223372036854775807)
|
|
||||||
* 用于总测量时间(__int64)
|
|
||||||
*/
|
|
||||||
class Int64Validator : public QValidator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Int64Validator(QObject *parent = nullptr) : QValidator(parent) {}
|
|
||||||
|
|
||||||
State validate(QString &input, int &pos) const override
|
|
||||||
{
|
|
||||||
if (input.isEmpty())
|
|
||||||
return Intermediate;
|
|
||||||
|
|
||||||
bool ok;
|
|
||||||
qint64 value = input.toLongLong(&ok);
|
|
||||||
if (!ok)
|
|
||||||
return Invalid;
|
|
||||||
|
|
||||||
if (value >= 0 && value <= 9223372036854775807LL)
|
|
||||||
return Acceptable;
|
|
||||||
|
|
||||||
return Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fixup(QString &input) const override
|
|
||||||
{
|
|
||||||
input.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 设备参数表格的代理类,用于自定义单元格的编辑器
|
|
||||||
*
|
|
||||||
* 根据不同的列(参数类型)提供不同的编辑控件,例如下拉框、数字输入框等。
|
|
||||||
*/
|
|
||||||
class DeviceParameterProxy : public QStyledItemDelegate
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DeviceParameterProxy(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 创建编辑器控件,根据列索引返回不同的编辑器
|
|
||||||
* @param parent 父窗口
|
|
||||||
* @param option 样式选项
|
|
||||||
* @param index 当前单元格的索引
|
|
||||||
* @return 返回对应列的编辑器控件指针
|
|
||||||
*/
|
|
||||||
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将模型中的数据设置到编辑器中
|
|
||||||
* @param editor 编辑器控件
|
|
||||||
* @param index 当前单元格的索引
|
|
||||||
*/
|
|
||||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将编辑器中的数据写回模型
|
|
||||||
* @param editor 编辑器控件
|
|
||||||
* @param model 数据模型
|
|
||||||
* @param index 当前单元格的索引
|
|
||||||
*/
|
|
||||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 更新编辑器的几何位置
|
|
||||||
* @param editor 编辑器控件
|
|
||||||
* @param option 样式选项
|
|
||||||
* @param index 当前单元格的索引
|
|
||||||
*/
|
|
||||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool eventFilter(QObject *obj, QEvent *event) override; // 事件过滤器,用于验证输入和显示提示
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // DEVICEPARAMETERPROXY_H
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
#include "MeasureAnalysisView.h"
|
#include "MeasureAnalysisView.h"
|
||||||
#include "MeasureAnalysisTreeView.h"
|
#include "MeasureAnalysisTreeView.h"
|
||||||
#include "GlobalDefine.h"
|
#include "GlobalDefine.h"
|
||||||
#include "DeviceParameterConfig.h"
|
|
||||||
using namespace ads;
|
using namespace ads;
|
||||||
|
|
||||||
MainWindow* MainWindow::_s_main_win = nullptr;
|
MainWindow* MainWindow::_s_main_win = nullptr;
|
||||||
|
|
@ -223,8 +223,7 @@ void MainWindow::initAction()
|
||||||
device_cfg_mrg_dlg.setObjectName("MeasureDeviceParamsCfgFormDlg");
|
device_cfg_mrg_dlg.setObjectName("MeasureDeviceParamsCfgFormDlg");
|
||||||
device_cfg_mrg_dlg.setWindowTitle(QStringLiteral(u"测量设备参数配置管理"));
|
device_cfg_mrg_dlg.setWindowTitle(QStringLiteral(u"测量设备参数配置管理"));
|
||||||
device_cfg_mrg_dlg.setWindowFlags(device_cfg_mrg_dlg.windowFlags() | Qt::WindowMaximizeButtonHint);
|
device_cfg_mrg_dlg.setWindowFlags(device_cfg_mrg_dlg.windowFlags() | Qt::WindowMaximizeButtonHint);
|
||||||
// MeasureDeviceParamsCfgForm* measure_dev_params_cfg_form = new MeasureDeviceParamsCfgForm(&device_cfg_mrg_dlg);
|
MeasureDeviceParamsCfgForm* measure_dev_params_cfg_form = new MeasureDeviceParamsCfgForm(&device_cfg_mrg_dlg);
|
||||||
DeviceParameterConfig * measure_dev_params_cfg_form = new DeviceParameterConfig(&device_cfg_mrg_dlg);
|
|
||||||
QHBoxLayout* hlayout = new QHBoxLayout;
|
QHBoxLayout* hlayout = new QHBoxLayout;
|
||||||
hlayout->addWidget(measure_dev_params_cfg_form);
|
hlayout->addWidget(measure_dev_params_cfg_form);
|
||||||
device_cfg_mrg_dlg.setLayout(hlayout);
|
device_cfg_mrg_dlg.setLayout(hlayout);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>892</width>
|
<width>892</width>
|
||||||
<height>23</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_measurement_analysis">
|
<widget class="QMenu" name="menu_measurement_analysis">
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,7 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
if (!_model->GetNodeStatus(item)) {
|
if (!_model->GetNodeStatus(item)) {
|
||||||
QVariant analysis_type_data = _model->GetNodeUserData(item, ProjectList::NodeType);
|
return;
|
||||||
if (!analysis_type_data.isValid())
|
|
||||||
return;
|
|
||||||
AnalysisType analysis_type = analysis_type_data.value<AnalysisType>();
|
|
||||||
if(analysis_type != AnalysisType::DeviceParamsCfg)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const QString& item_text = item->text();
|
const QString& item_text = item->text();
|
||||||
QVariant project_name_data = _model->GetNodeUserData(item, ProjectList::ProjectName);
|
QVariant project_name_data = _model->GetNodeUserData(item, ProjectList::ProjectName);
|
||||||
|
|
@ -237,17 +232,6 @@ void MeasureAnalysisTreeView::onNodeDoubleClicked(const QModelIndex& index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case AnalysisType::DeviceParamsCfg: {
|
|
||||||
MeasureAnalysisProjectModel* project_model = _model->GetProjectModel(project_name);
|
|
||||||
if (project_model) {
|
|
||||||
QString file_name = project_model->GetMeasureDeviceParamsCfgFilename();
|
|
||||||
if (!file_name.isEmpty()) {
|
|
||||||
data_files_set[QStringLiteral(u"设备参数配置")] = file_name;
|
|
||||||
} else {
|
|
||||||
data_files_set[QStringLiteral(u"设备参数配置")] = QString("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
#include "ParticleTimePoorView.h"
|
#include "ParticleTimePoorView.h"
|
||||||
#include "ConformityAnalysis.h"
|
#include "ConformityAnalysis.h"
|
||||||
#include "EnergyCountPeakFitView.h"
|
#include "EnergyCountPeakFitView.h"
|
||||||
#include "DeviceConfigView.h"
|
|
||||||
MeasureAnalysisView *MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
|
MeasureAnalysisView *MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
|
||||||
{
|
{
|
||||||
MeasureAnalysisView* new_view = nullptr;
|
MeasureAnalysisView* new_view = nullptr;
|
||||||
|
|
@ -18,8 +18,8 @@ MeasureAnalysisView *MeasureAnalysisView::NewAnalyzeView(AnalysisType view_type)
|
||||||
// new_view->setDeleteOnClose(true);
|
// new_view->setDeleteOnClose(true);
|
||||||
} break;
|
} break;
|
||||||
case AnalysisType::DeviceParamsCfg: {
|
case AnalysisType::DeviceParamsCfg: {
|
||||||
new_view = new DeviceConfigView;
|
// new_view = new MeasureAnalysisDataTableView;
|
||||||
new_view->setDeleteOnClose(true);
|
// new_view->setDeleteOnClose(true);
|
||||||
} break;
|
} break;
|
||||||
case AnalysisType::EnergyScale: {
|
case AnalysisType::EnergyScale: {
|
||||||
// new_view = new MeasureAnalysisDataTableView;
|
// new_view = new MeasureAnalysisDataTableView;
|
||||||
|
|
|
||||||
19
src/src.pro
19
src/src.pro
|
|
@ -40,9 +40,7 @@ INCLUDEPATH += \
|
||||||
$${PWD}/ThreeDimensionalConformityAnalysisView \
|
$${PWD}/ThreeDimensionalConformityAnalysisView \
|
||||||
$${PWD}/EnergyCountPeakFitView \
|
$${PWD}/EnergyCountPeakFitView \
|
||||||
$${PWD}/MeasureAnalysisDataTableView \
|
$${PWD}/MeasureAnalysisDataTableView \
|
||||||
$${PWD}/MeasureAnalysisHistoryForm \
|
$${PWD}/MeasureAnalysisHistoryForm
|
||||||
$${PWD}/DeviceParameterConfig
|
|
||||||
|
|
||||||
|
|
||||||
DEPENDPATH += \
|
DEPENDPATH += \
|
||||||
$${PWD}/MeasureAnalysisParticleCountPlotView \
|
$${PWD}/MeasureAnalysisParticleCountPlotView \
|
||||||
|
|
@ -54,18 +52,13 @@ DEPENDPATH += \
|
||||||
$${PWD}/ThreeDimensionalConformityAnalysisView \
|
$${PWD}/ThreeDimensionalConformityAnalysisView \
|
||||||
$${PWD}/EnergyCountPeakFitView \
|
$${PWD}/EnergyCountPeakFitView \
|
||||||
$${PWD}/MeasureAnalysisDataTableView \
|
$${PWD}/MeasureAnalysisDataTableView \
|
||||||
$${PWD}/MeasureAnalysisHistoryForm \
|
$${PWD}/MeasureAnalysisHistoryForm
|
||||||
$${PWD}/DeviceParameterConfig
|
|
||||||
|
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
AboutDlg.cpp \
|
AboutDlg.cpp \
|
||||||
CountRateAnalysisView/CountRateAnalysisView.cpp \
|
CountRateAnalysisView/CountRateAnalysisView.cpp \
|
||||||
CustomQwtPlot.cpp \
|
CustomQwtPlot.cpp \
|
||||||
DataProcessWorkPool.cpp \
|
DataProcessWorkPool.cpp \
|
||||||
DeviceParameterConfig/DeviceConfigView.cpp \
|
|
||||||
DeviceParameterConfig/DeviceParameterConfig.cpp \
|
|
||||||
DeviceParameterConfig/DeviceParameterConfigList.cpp \
|
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
||||||
EnergyCountPlotView/EnergyCountPlotView.cpp \
|
EnergyCountPlotView/EnergyCountPlotView.cpp \
|
||||||
EnergyScaleDataModel.cpp \
|
EnergyScaleDataModel.cpp \
|
||||||
|
|
@ -92,7 +85,6 @@ SOURCES += \
|
||||||
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.cpp \
|
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.cpp \
|
||||||
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.cpp \
|
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.cpp \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
||||||
DeviceParameterConfig/DeviceParameterProxy.cpp \
|
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
|
@ -101,9 +93,6 @@ HEADERS += \
|
||||||
CountRateAnalysisView/CountRateAnalysisView.h \
|
CountRateAnalysisView/CountRateAnalysisView.h \
|
||||||
CustomQwtPlot.h \
|
CustomQwtPlot.h \
|
||||||
DataProcessWorkPool.h \
|
DataProcessWorkPool.h \
|
||||||
DeviceParameterConfig/DeviceConfigView.h \
|
|
||||||
DeviceParameterConfig/DeviceParameterConfig.h \
|
|
||||||
DeviceParameterConfig/DeviceParameterConfigList.h \
|
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
||||||
EnergyCountPlotView/EnergyCountPlotView.h \
|
EnergyCountPlotView/EnergyCountPlotView.h \
|
||||||
EnergyScaleDataModel.h \
|
EnergyScaleDataModel.h \
|
||||||
|
|
@ -131,9 +120,7 @@ HEADERS += \
|
||||||
ThreeDimensionalConformityAnalysisView/DetectorStatusSummary.h \
|
ThreeDimensionalConformityAnalysisView/DetectorStatusSummary.h \
|
||||||
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.h \
|
ThreeDimensionalConformityAnalysisView/ParticleDataStatistics.h \
|
||||||
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \
|
ThreeDimensionalConformityAnalysisView/ThreeDDisplay.h \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.h
|
||||||
DeviceParameterConfig/DeviceParameterProxy.h
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user