385 lines
12 KiB
C++
385 lines
12 KiB
C++
#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);
|
||
}
|