first commit

This commit is contained in:
2026-01-02 19:20:35 +09:00
commit a10cb30c4a
94 changed files with 28609 additions and 0 deletions

View File

@@ -0,0 +1,618 @@
#include "signaltrimwidget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QScrollArea>
#include <QFrame>
#include <cmath>
static const char *GROUP_STYLE = R"(
QGroupBox {
background-color: white;
border: 1px solid #e0e0e0;
border-radius: 12px;
margin-top: 8px;
padding: 16px;
font-size: 14px;
font-weight: 600;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 16px;
padding: 0 8px;
color: #333;
}
)";
static const char *BUTTON_STYLE = R"(
QPushButton {
background-color: #2196F3;
color: white;
border: none;
border-radius: 8px;
padding: 12px 32px;
font-size: 14px;
font-weight: 600;
}
QPushButton:hover {
background-color: #1976D2;
}
QPushButton:pressed {
background-color: #1565C0;
}
QPushButton:disabled {
background-color: #BDBDBD;
}
)";
static const char *TRIM_BUTTON_STYLE = R"(
QPushButton {
background-color: #ff9800;
color: white;
border: none;
border-radius: 8px;
padding: 12px 20px;
font-size: 28px;
font-weight: bold;
min-width: 60px;
min-height: 50px;
}
QPushButton:hover {
background-color: #f57c00;
}
QPushButton:pressed {
background-color: #ef6c00;
}
)";
SignalTrimWidget::SignalTrimWidget(QWidget *parent)
: QWidget(parent), m_currentValue(0), m_minValue(-100), m_maxValue(100), m_decimals(4)
{
setupUI();
updateTotalValue();
}
void SignalTrimWidget::setupUI()
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
// 标题栏
mainLayout->addWidget(createTitleBar());
// 内容区域
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidgetResizable(true);
scrollArea->setFrameShape(QFrame::NoFrame);
scrollArea->setStyleSheet("QScrollArea { background-color: #f5f5f5; }");
QWidget *contentWidget = new QWidget;
contentWidget->setStyleSheet("background-color: #f5f5f5;");
QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
contentLayout->setContentsMargins(20, 20, 20, 20);
contentLayout->setSpacing(16);
// 信号选择面板
contentLayout->addWidget(createSignalSelectPanel());
// 粗调面板
contentLayout->addWidget(createCoarseAdjustPanel());
// 微调面板
contentLayout->addWidget(createFineAdjustPanel());
// 输出面板
contentLayout->addWidget(createOutputPanel());
contentLayout->addStretch();
scrollArea->setWidget(contentWidget);
mainLayout->addWidget(scrollArea, 1);
}
QWidget *SignalTrimWidget::createTitleBar()
{
QWidget *titleBar = new QWidget;
titleBar->setFixedHeight(60);
titleBar->setStyleSheet("background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #1976D2, stop:1 #1565C0);");
QHBoxLayout *layout = new QHBoxLayout(titleBar);
layout->setContentsMargins(16, 0, 16, 0);
// 返回按钮
m_backBtn = new QPushButton("← 返回");
m_backBtn->setCursor(Qt::PointingHandCursor);
m_backBtn->setStyleSheet(R"(
QPushButton {
background: rgba(255,255,255,0.2);
color: white;
border: none;
border-radius: 6px;
padding: 8px 16px;
font-size: 14px;
}
QPushButton:hover {
background: rgba(255,255,255,0.3);
}
)");
connect(m_backBtn, &QPushButton::clicked, this, &SignalTrimWidget::backRequested);
layout->addWidget(m_backBtn);
// 标题(居中)
m_titleLabel = new QLabel("信号微调");
m_titleLabel->setStyleSheet("color: white; font-size: 18px; font-weight: bold;");
m_titleLabel->setAlignment(Qt::AlignCenter);
layout->addWidget(m_titleLabel, 1);
// 右侧占位,保持标题居中
QWidget *spacer = new QWidget;
spacer->setFixedWidth(m_backBtn->sizeHint().width());
layout->addWidget(spacer);
return titleBar;
}
QWidget *SignalTrimWidget::createSignalSelectPanel()
{
QGroupBox *group = new QGroupBox("信号选择");
group->setStyleSheet(GROUP_STYLE);
QHBoxLayout *layout = new QHBoxLayout(group);
layout->setContentsMargins(16, 24, 16, 16);
layout->setSpacing(24);
// 信号类型
QVBoxLayout *typeLayout = new QVBoxLayout;
QLabel *typeLabel = new QLabel("信号类型");
typeLabel->setStyleSheet("color: #666; font-size: 12px; font-weight: normal;");
m_signalTypeCombo = new QComboBox;
m_signalTypeCombo->addItems({"直流电压 (DC V)",
"直流电流 (DC mA)",
"交流电压 (AC V)",
"电阻 (Ω)",
"热电偶 (°C)",
"热电阻 (°C)",
"频率 (Hz)"});
m_signalTypeCombo->setStyleSheet(R"(
QComboBox {
background: white;
border: 1px solid #ddd;
border-radius: 6px;
padding: 10px 16px;
min-width: 180px;
font-size: 14px;
}
)");
connect(m_signalTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SignalTrimWidget::onSignalTypeChanged);
typeLayout->addWidget(typeLabel);
typeLayout->addWidget(m_signalTypeCombo);
layout->addLayout(typeLayout);
// 单位选择
QVBoxLayout *unitLayout = new QVBoxLayout;
QLabel *unitLabel = new QLabel("单位");
unitLabel->setStyleSheet("color: #666; font-size: 12px; font-weight: normal;");
m_unitCombo = new QComboBox;
m_unitCombo->addItems({"V", "mV", "µV"});
m_unitCombo->setStyleSheet(R"(
QComboBox {
background: white;
border: 1px solid #ddd;
border-radius: 6px;
padding: 10px 16px;
min-width: 100px;
font-size: 14px;
}
)");
unitLayout->addWidget(unitLabel);
unitLayout->addWidget(m_unitCombo);
layout->addLayout(unitLayout);
layout->addStretch();
return group;
}
QWidget *SignalTrimWidget::createCoarseAdjustPanel()
{
QGroupBox *group = new QGroupBox("粗调");
group->setStyleSheet(GROUP_STYLE);
QHBoxLayout *layout = new QHBoxLayout(group);
layout->setContentsMargins(16, 24, 16, 16);
layout->setSpacing(16);
QLabel *valueLabel = new QLabel("设定值:");
valueLabel->setStyleSheet("font-size: 16px; font-weight: 600;");
layout->addWidget(valueLabel);
m_coarseValueSpin = new QDoubleSpinBox;
m_coarseValueSpin->setRange(m_minValue, m_maxValue);
m_coarseValueSpin->setValue(0);
m_coarseValueSpin->setDecimals(m_decimals);
m_coarseValueSpin->setSingleStep(1.0);
m_coarseValueSpin->setStyleSheet(R"(
QDoubleSpinBox {
padding: 12px 16px;
border: 2px solid #2196F3;
border-radius: 8px;
background: white;
font-size: 24px;
font-weight: bold;
font-family: monospace;
min-width: 200px;
}
QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
subcontrol-origin: border;
width: 32px;
border-left: 2px solid #2196F3;
background: #e3f2fd;
}
QDoubleSpinBox::up-button { subcontrol-position: top right; border-top-right-radius: 6px; }
QDoubleSpinBox::down-button { subcontrol-position: bottom right; border-bottom-right-radius: 6px; }
QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover { background: #bbdefb; }
QDoubleSpinBox::up-arrow { image: url(:/icons/arrow_up.svg); width: 14px; height: 14px; }
QDoubleSpinBox::down-arrow { image: url(:/icons/arrow_down.svg); width: 14px; height: 14px; }
)");
connect(m_coarseValueSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &SignalTrimWidget::onCoarseValueChanged);
layout->addWidget(m_coarseValueSpin);
m_coarseUnitLabel = new QLabel("V");
m_coarseUnitLabel->setStyleSheet("font-size: 20px; font-weight: bold; color: #2196F3;");
layout->addWidget(m_coarseUnitLabel);
layout->addStretch();
// 快捷设置按钮
QVBoxLayout *presetLayout = new QVBoxLayout;
QLabel *presetLabel = new QLabel("快捷设置:");
presetLabel->setStyleSheet("color: #666; font-size: 12px;");
presetLayout->addWidget(presetLabel);
QHBoxLayout *presetBtnLayout = new QHBoxLayout;
QStringList presets = {"0", "1", "5", "10", "20"};
for (const QString &preset : presets)
{
QPushButton *btn = new QPushButton(preset);
btn->setStyleSheet(R"(
QPushButton {
background-color: #e3f2fd;
color: #1976D2;
border: 1px solid #90caf9;
border-radius: 6px;
padding: 8px 16px;
font-weight: 600;
}
QPushButton:hover {
background-color: #bbdefb;
}
)");
btn->setCursor(Qt::PointingHandCursor);
connect(btn, &QPushButton::clicked, this, [this, preset]()
{ m_coarseValueSpin->setValue(preset.toDouble()); });
presetBtnLayout->addWidget(btn);
}
presetLayout->addLayout(presetBtnLayout);
layout->addLayout(presetLayout);
return group;
}
QWidget *SignalTrimWidget::createFineAdjustPanel()
{
QGroupBox *group = new QGroupBox("微调");
group->setStyleSheet(GROUP_STYLE);
QVBoxLayout *mainLayout = new QVBoxLayout(group);
mainLayout->setContentsMargins(16, 24, 16, 16);
mainLayout->setSpacing(16);
// 步进选择
QHBoxLayout *stepLayout = new QHBoxLayout;
QLabel *stepLabel = new QLabel("微调步进:");
stepLabel->setStyleSheet("font-weight: 600;");
stepLayout->addWidget(stepLabel);
m_stepSizeCombo = new QComboBox;
m_stepSizeCombo->addItems({"0.0001", "0.001", "0.01", "0.1", "1"});
m_stepSizeCombo->setCurrentIndex(1); // 默认 0.001
m_stepSizeCombo->setStyleSheet(R"(
QComboBox {
background: white;
border: 1px solid #ddd;
border-radius: 6px;
padding: 8px 12px;
min-width: 100px;
}
)");
connect(m_stepSizeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this](int)
{ updateSliderRange(); });
stepLayout->addWidget(m_stepSizeCombo);
stepLayout->addStretch();
mainLayout->addLayout(stepLayout);
// 微调控制
QHBoxLayout *trimLayout = new QHBoxLayout;
trimLayout->setSpacing(16);
// 减少按钮
m_decrementBtn = new QPushButton("-");
m_decrementBtn->setStyleSheet(TRIM_BUTTON_STYLE);
m_decrementBtn->setCursor(Qt::PointingHandCursor);
connect(m_decrementBtn, &QPushButton::clicked, this, &SignalTrimWidget::onDecrementClicked);
trimLayout->addWidget(m_decrementBtn);
// 微调值显示
m_fineValueSpin = new QDoubleSpinBox;
m_fineValueSpin->setRange(-10, 10);
m_fineValueSpin->setValue(0);
m_fineValueSpin->setDecimals(4);
m_fineValueSpin->setSingleStep(0.001);
m_fineValueSpin->setPrefix("微调: ");
m_fineValueSpin->setStyleSheet(R"(
QDoubleSpinBox {
padding: 12px 16px;
border: 2px solid #ff9800;
border-radius: 8px;
background: #fff3e0;
font-size: 18px;
font-weight: bold;
font-family: monospace;
min-width: 180px;
}
QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
subcontrol-origin: border;
width: 28px;
border-left: 2px solid #ff9800;
background: #ffe0b2;
}
QDoubleSpinBox::up-button { subcontrol-position: top right; border-top-right-radius: 6px; }
QDoubleSpinBox::down-button { subcontrol-position: bottom right; border-bottom-right-radius: 6px; }
QDoubleSpinBox::up-button:hover, QDoubleSpinBox::down-button:hover { background: #ffcc80; }
QDoubleSpinBox::up-arrow { image: url(:/icons/arrow_up.svg); width: 12px; height: 12px; }
QDoubleSpinBox::down-arrow { image: url(:/icons/arrow_down.svg); width: 12px; height: 12px; }
)");
connect(m_fineValueSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
this, &SignalTrimWidget::onFineValueChanged);
trimLayout->addWidget(m_fineValueSpin);
// 增加按钮
m_incrementBtn = new QPushButton("+");
m_incrementBtn->setStyleSheet(TRIM_BUTTON_STYLE);
m_incrementBtn->setCursor(Qt::PointingHandCursor);
connect(m_incrementBtn, &QPushButton::clicked, this, &SignalTrimWidget::onIncrementClicked);
trimLayout->addWidget(m_incrementBtn);
trimLayout->addStretch();
mainLayout->addLayout(trimLayout);
// 滑块微调
QHBoxLayout *sliderLayout = new QHBoxLayout;
QLabel *minLabel = new QLabel("-1.000");
minLabel->setStyleSheet("color: #666; font-family: monospace;");
sliderLayout->addWidget(minLabel);
m_fineSlider = new QSlider(Qt::Horizontal);
m_fineSlider->setRange(-1000, 1000);
m_fineSlider->setValue(0);
m_fineSlider->setStyleSheet(R"(
QSlider::groove:horizontal {
border: 1px solid #bbb;
background: #e0e0e0;
height: 8px;
border-radius: 4px;
}
QSlider::handle:horizontal {
background: #ff9800;
border: 2px solid #f57c00;
width: 24px;
margin: -8px 0;
border-radius: 12px;
}
QSlider::handle:horizontal:hover {
background: #ffa726;
}
QSlider::sub-page:horizontal {
background: #ffcc80;
border-radius: 4px;
}
)");
connect(m_fineSlider, &QSlider::valueChanged, this, &SignalTrimWidget::onSliderChanged);
sliderLayout->addWidget(m_fineSlider, 1);
QLabel *maxLabel = new QLabel("+1.000");
maxLabel->setStyleSheet("color: #666; font-family: monospace;");
sliderLayout->addWidget(maxLabel);
mainLayout->addLayout(sliderLayout);
return group;
}
QWidget *SignalTrimWidget::createOutputPanel()
{
QGroupBox *group = new QGroupBox("最终输出");
group->setStyleSheet(GROUP_STYLE);
QHBoxLayout *layout = new QHBoxLayout(group);
layout->setContentsMargins(16, 24, 16, 16);
layout->setSpacing(24);
// 总值显示
m_totalValueLabel = new QLabel("0.0000 V");
m_totalValueLabel->setStyleSheet(R"(
QLabel {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #1a1a2e, stop:1 #16213e);
color: #00ff88;
border: 2px solid #00aa55;
border-radius: 12px;
padding: 20px 40px;
font-size: 36px;
font-weight: bold;
font-family: 'Courier New', monospace;
min-width: 300px;
}
)");
m_totalValueLabel->setAlignment(Qt::AlignCenter);
layout->addWidget(m_totalValueLabel);
layout->addStretch();
// 控制按钮
QVBoxLayout *btnLayout = new QVBoxLayout;
btnLayout->setSpacing(12);
m_applyBtn = new QPushButton("应用输出");
m_applyBtn->setStyleSheet(BUTTON_STYLE);
m_applyBtn->setCursor(Qt::PointingHandCursor);
connect(m_applyBtn, &QPushButton::clicked, this, &SignalTrimWidget::onApplyOutput);
btnLayout->addWidget(m_applyBtn);
m_resetBtn = new QPushButton("重置归零");
m_resetBtn->setStyleSheet(R"(
QPushButton {
background-color: #757575;
color: white;
border: none;
border-radius: 8px;
padding: 12px 32px;
font-size: 14px;
font-weight: 600;
}
QPushButton:hover {
background-color: #616161;
}
)");
m_resetBtn->setCursor(Qt::PointingHandCursor);
connect(m_resetBtn, &QPushButton::clicked, this, &SignalTrimWidget::onResetValue);
btnLayout->addWidget(m_resetBtn);
layout->addLayout(btnLayout);
return group;
}
void SignalTrimWidget::onSignalTypeChanged(int index)
{
// 根据信号类型更新单位选项
m_unitCombo->clear();
switch (index)
{
case 0: // DC V
m_unitCombo->addItems({"V", "mV", "µV"});
m_coarseUnitLabel->setText("V");
m_minValue = -100;
m_maxValue = 100;
m_decimals = 4;
break;
case 1: // DC mA
m_unitCombo->addItems({"mA", "µA"});
m_coarseUnitLabel->setText("mA");
m_minValue = -30;
m_maxValue = 30;
m_decimals = 4;
break;
case 2: // AC V
m_unitCombo->addItems({"V", "mV"});
m_coarseUnitLabel->setText("V");
m_minValue = 0;
m_maxValue = 300;
m_decimals = 3;
break;
case 3: // Ω
m_unitCombo->addItems({"Ω", "", ""});
m_coarseUnitLabel->setText("Ω");
m_minValue = 0;
m_maxValue = 10000;
m_decimals = 2;
break;
case 4: // 热电偶
case 5: // 热电阻
m_unitCombo->addItems({"°C"});
m_coarseUnitLabel->setText("°C");
m_minValue = -200;
m_maxValue = 1800;
m_decimals = 2;
break;
case 6: // Hz
m_unitCombo->addItems({"Hz", "kHz", "MHz"});
m_coarseUnitLabel->setText("Hz");
m_minValue = 0;
m_maxValue = 100000;
m_decimals = 2;
break;
}
m_coarseValueSpin->setRange(m_minValue, m_maxValue);
m_coarseValueSpin->setDecimals(m_decimals);
updateTotalValue();
}
void SignalTrimWidget::onCoarseValueChanged(double value)
{
Q_UNUSED(value)
updateTotalValue();
}
void SignalTrimWidget::onFineValueChanged(double value)
{
// 更新滑块位置
m_fineSlider->blockSignals(true);
double step = m_stepSizeCombo->currentText().toDouble();
m_fineSlider->setValue(static_cast<int>(value / step));
m_fineSlider->blockSignals(false);
updateTotalValue();
}
void SignalTrimWidget::onSliderChanged(int value)
{
double step = m_stepSizeCombo->currentText().toDouble();
m_fineValueSpin->setValue(value * step);
}
void SignalTrimWidget::onIncrementClicked()
{
double step = m_stepSizeCombo->currentText().toDouble();
m_fineValueSpin->setValue(m_fineValueSpin->value() + step);
}
void SignalTrimWidget::onDecrementClicked()
{
double step = m_stepSizeCombo->currentText().toDouble();
m_fineValueSpin->setValue(m_fineValueSpin->value() - step);
}
void SignalTrimWidget::onApplyOutput()
{
// 应用输出值到设备
m_currentValue = m_coarseValueSpin->value() + m_fineValueSpin->value();
// TODO: 发送到硬件
}
void SignalTrimWidget::onResetValue()
{
m_coarseValueSpin->setValue(0);
m_fineValueSpin->setValue(0);
m_fineSlider->setValue(0);
}
void SignalTrimWidget::updateTotalValue()
{
double total = m_coarseValueSpin->value() + m_fineValueSpin->value();
QString unit = m_coarseUnitLabel->text();
m_totalValueLabel->setText(QString("%1 %2").arg(total, 0, 'f', m_decimals).arg(unit));
}
void SignalTrimWidget::updateSliderRange()
{
double step = m_stepSizeCombo->currentText().toDouble();
int range = static_cast<int>(1.0 / step);
m_fineSlider->setRange(-range, range);
m_fineValueSpin->setSingleStep(step);
}