跳到主内容
paste
bin
.ca
type · paste · share
⌘
K
系列
bin 系列
pastebin.ca
中心
Share text and code with expiry and privacy controls.
imagebin.ca
Upload and share images with direct links.
filebin.ca
Drop a file and get a shareable link.
notebin.ca
Write Markdown notes with durable links.
turl.ca
Short, reputation-checked links.
attn.ca
Notifications and alerts for your services.
voicebin.ca
Record and share short voice clips.
dnsbin.ca
Inspect DNS and debug records.
文档
登录
?
← 返回文本
›
编辑 / 分支
无标题文本
#4QGQdn3SfJ
public / public
新版本
由 @amber-zebra-8262
已创建 25 days ago
永不过期
48.4 KB
语法:
text
你的更改会创建一个链接到此文本的新文本 — 原始文本不变。
新版本
你的更改会创建一个链接到此文本的新文本 — 原始文本不变。
标题(可选)
文件名
语法
text
text
bash
c
cpp
css
diff
dockerfile
go
html
ini
java
javascript
json
kotlin
lua
makefile
markdown
nginx
php
python
ruby
rust
shellscript
sql
swift
toml
typescript
xml
yaml
可见性
公开动态
访问
public
过期
7 天
10 分钟
1 小时
1 天
7 天
30 天
90 天
自定义…
自定义过期
变更备注
(可选)
此文本会显示在公开动态中。如果只想通过链接分享,请更改可见性。
创建新版本
取消
粘贴或输入…
#include "view_configGenerator.h" #include <QCheckBox> #include <QComboBox> #include <QFileDialog> #include <QFormLayout> #include <QGroupBox> #include <QHeaderView> #include <QLabel> #include <QLineEdit> #include <QMessageBox> #include <QPushButton> #include <QSpinBox> #include <QTableWidget> #include <QListWidget> #include <QTabWidget> #include <QJsonDocument> #include <QFile> #include "e3d_configManager_equipment.h" view_configGenerator::view_configGenerator(QWidget *parent) : QWidget(parent), currentData(new data_equipment) , ui(new Ui::e3d_configGenaraterClass()) { ui->setupUi(this); if (this->layout()) { delete this->layout(); } initUI(); } view_configGenerator::~view_configGenerator() { delete currentData; delete ui; } void view_configGenerator::initUI() { auto *mainLayout = new QVBoxLayout(this); // 1. 顶部文件操作栏 auto *gb_file = new QGroupBox(tr("Config File Operations"), this); auto *hl_file = new QHBoxLayout(gb_file); le_configPath = new QLineEdit(gb_file); pb_loadConfig = new QPushButton(tr("Load Config File"), gb_file); pb_saveConfigToFile = new QPushButton(tr("Save Config to File"), gb_file); pb_saveConfigToTemp = new QPushButton(tr("Save to Memory"), gb_file); hl_file->addWidget(le_configPath); hl_file->addWidget(pb_loadConfig); hl_file->addWidget(pb_saveConfigToFile); hl_file->addWidget(pb_saveConfigToTemp); mainLayout->addWidget(gb_file); // 2. Tab 页面容器 auto *tabWidget = new QTabWidget(this); tabWidget->addTab(createMotionControllerTab(), tr("Motion Controllers & I/O / Axes")); tabWidget->addTab(createCommsTab(), tr("Comms Config")); tabWidget->addTab(createHeightSensorTab(), tr("Height Sensor Config")); tabWidget->addTab(createDispenserTab(), tr("Dispenser Config")); tabWidget->addTab(createExternalDeviceTab(), tr("Global External Devices")); tabWidget->addTab(createToolheadTab(), tr("Toolhead Config")); tabWidget->addTab(createCommonTab(), tr("Common Config")); mainLayout->addWidget(tabWidget); // 3. 信号槽绑定 connect(pb_loadConfig, &QPushButton::clicked, this, &view_configGenerator::onLoadConfigFromFile); connect(pb_saveConfigToFile, &QPushButton::clicked, this, &view_configGenerator::onSaveConfigToFile); connect(pb_saveConfigToTemp, &QPushButton::clicked, this, &view_configGenerator::onSaveTempClicked); // 初始化右侧面板状态(为空时不可编辑) updateControllerRightPanel(); updateToolheadRightPanel(); } void view_configGenerator::updateTableRows(QTableWidget *table, int targetCount) { int current = table->rowCount(); if (targetCount > current) { for (int i = current; i < targetCount; ++i) { table->insertRow(i); } } else if (targetCount < current) { for (int i = current - 1; i >= targetCount; --i) { table->removeRow(i); } } } // ============================================================================ // 1. 控制卡 Master-Detail 页面构建 // ============================================================================ QWidget* view_configGenerator::createMotionControllerTab() { auto *widget = new QWidget(); auto *mainLayout = new QHBoxLayout(widget); auto *leftGroup = new QGroupBox(tr("Controller List"), widget); auto *leftLayout = new QVBoxLayout(leftGroup); m_cardListWidget = new QListWidget(leftGroup); auto *btnLayout = new QHBoxLayout(); auto *btnAddCard = new QPushButton(tr("Add Card"), leftGroup); auto *btnDelCard = new QPushButton(tr("Delete Card"), leftGroup); btnLayout->addWidget(btnAddCard); btnLayout->addWidget(btnDelCard); leftLayout->addWidget(m_cardListWidget); leftLayout->addLayout(btnLayout); // 使用成员变量管理右侧面板 GroupBox m_controllerRightGroup = new QGroupBox(tr("Controller Properties & Sub-Devices"), widget); auto *rightLayout = new QVBoxLayout(m_controllerRightGroup); auto *formLayout = new QFormLayout(); m_editCardName = new QLineEdit(); m_comboBrand = new QComboBox(); m_comboBrand->addItem("ZMOTION","ZMOTION"); m_comboBrand->addItem("ACS","ACS"); m_editIP = new QLineEdit("127.0.0.1"); m_spinPort = new QSpinBox(); m_spinPort->setRange(1, 65535); m_spinPort->setValue(8080); m_editAllAxisHomePath = new QLineEdit("AllAxisHomePath"); m_showSub = new QCheckBox(); formLayout->addRow(tr("Controller Name (userName):"), m_editCardName); formLayout->addRow(tr("Brand:"), m_comboBrand); formLayout->addRow(tr("IP Address:"), m_editIP); formLayout->addRow(tr("Port:"), m_spinPort); formLayout->addRow(tr("AllAxisHomePath:"), m_editAllAxisHomePath); formLayout->addRow(tr("showSub:"), m_showSub); rightLayout->addLayout(formLayout); m_subConfigTab = new QTabWidget(m_controllerRightGroup); auto *axisTabWidget = new QWidget(); auto *axisLayout = new QVBoxLayout(axisTabWidget); m_axisTable = new QTableWidget(0, 9); m_axisTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_axisTable->setSelectionMode(QAbstractItemView::SingleSelection); m_axisTable->setHorizontalHeaderLabels({ tr("Axis Name (userName)"), tr("Axis No"), tr("Left Limit"), tr("Right Limit"), tr("Acc"), tr("Dec"), tr("Fast Dec"), tr("Enable Left Limit"), tr("Enable Right Limit") }); m_axisTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); auto *axisBtnLayout = new QHBoxLayout(); auto *btnAddAxis = new QPushButton(tr("Add Axis")); auto *btnDelAxis = new QPushButton(tr("Delete Axis")); axisBtnLayout->addWidget(btnAddAxis); axisBtnLayout->addWidget(btnDelAxis); axisBtnLayout->addStretch(); axisLayout->addLayout(axisBtnLayout); axisLayout->addWidget(m_axisTable); m_subConfigTab->addTab(axisTabWidget, tr("Axes (AxisInfo)")); auto createIOTab = [this](QTableWidget*& table, const QString& title, bool isDigital) { auto *w = new QWidget(); auto *ly = new QVBoxLayout(w); table = new QTableWidget(0, isDigital ? 3 : 2); table->setSelectionBehavior(QAbstractItemView::SelectRows); table->setSelectionMode(QAbstractItemView::SingleSelection); if (isDigital) { table->setHorizontalHeaderLabels({ tr("IO Name (userName)"), tr("Main IO (Port)"), tr("Sub IO (Pin)") }); } else { table->setHorizontalHeaderLabels({ tr("IO Name (userName)"), tr("Address") }); } table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); auto *bLy = new QHBoxLayout(); auto *bAdd = new QPushButton(tr("Add IO")); auto *bDel = new QPushButton(tr("Delete IO")); bLy->addWidget(bAdd); bLy->addWidget(bDel); bLy->addStretch(); ly->addLayout(bLy); ly->addWidget(table); connect(bAdd, &QPushButton::clicked, this, [this, table]() { onAddIO(table); }); connect(bDel, &QPushButton::clicked, this, [this, table]() { onDeleteIO(table); }); m_subConfigTab->addTab(w, title); }; createIOTab(m_dinTable, tr("Digital Input (DIN)"), true); createIOTab(m_doutTable, tr("Digital Output (DOUT)"), true); createIOTab(m_ainTable, tr("Analog Input (AIN)"), false); createIOTab(m_aoutTable, tr("Analog Output (AOUT)"), false); rightLayout->addWidget(m_subConfigTab); mainLayout->addWidget(leftGroup, 1); mainLayout->addWidget(m_controllerRightGroup, 3); connect(btnAddCard, &QPushButton::clicked, this, &view_configGenerator::onAddController); connect(btnDelCard, &QPushButton::clicked, this, &view_configGenerator::onDeleteController); connect(m_cardListWidget, &QListWidget::currentRowChanged, this, &view_configGenerator::onControllerSelected); connect(btnAddAxis, &QPushButton::clicked, this, &view_configGenerator::onAddAxis); connect(btnDelAxis, &QPushButton::clicked, this, &view_configGenerator::onDeleteAxis); return widget; } // ============================================================================ // 2. 通讯模块页构建 (Comms Config) // ============================================================================ QWidget* view_configGenerator::createCommsTab() { auto *widget = new QWidget(); auto *layout = new QVBoxLayout(widget); auto *hl_comms = new QHBoxLayout(); auto *btnAdd = new QPushButton(tr("Add Comms Module"), widget); auto *btnDel = new QPushButton(tr("Delete Selected"), widget); hl_comms->addWidget(btnAdd); hl_comms->addWidget(btnDel); hl_comms->addSpacing(20); hl_comms->addWidget(new QLabel(tr("Comms Module Count:"))); sb_count_Comms = new QSpinBox(); sb_count_Comms->setRange(0, 50); hl_comms->addWidget(sb_count_Comms); hl_comms->addStretch(); layout->addLayout(hl_comms); tw_Comms = new QTableWidget(0, 12); tw_Comms->setSelectionBehavior(QAbstractItemView::SelectRows); tw_Comms->setSelectionMode(QAbstractItemView::SingleSelection); tw_Comms->setHorizontalHeaderLabels({ tr("Comms Name"), tr("Type"), tr("Port Name"), tr("Baud Rate"), tr("Parity"), tr("Data Bits"), tr("Stop Bits"), tr("IP Address"), tr("TCP Port"), tr("Slave Addr"), tr("Timeout(ms)"), tr("Retry Times") }); tw_Comms->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); layout->addWidget(tw_Comms); auto addCommsRow = [this](int r) { tw_Comms->setItem(r, 0, new QTableWidgetItem(QString("Comms_%1").arg(r + 1))); auto *cbType = new QComboBox(); cbType->addItems(toStringList<data_CommsConfig::CommsType>()); tw_Comms->setCellWidget(r, 1, cbType); tw_Comms->setItem(r, 2, new QTableWidgetItem("COM1")); tw_Comms->setItem(r, 3, new QTableWidgetItem("115200")); tw_Comms->setItem(r, 4, new QTableWidgetItem("N")); tw_Comms->setItem(r, 5, new QTableWidgetItem("8")); tw_Comms->setItem(r, 6, new QTableWidgetItem("1")); tw_Comms->setItem(r, 7, new QTableWidgetItem("192.168.1.100")); tw_Comms->setItem(r, 8, new QTableWidgetItem("8080")); tw_Comms->setItem(r, 9, new QTableWidgetItem("1")); tw_Comms->setItem(r, 10, new QTableWidgetItem("1000")); tw_Comms->setItem(r, 11, new QTableWidgetItem("2")); }; connect(btnAdd, &QPushButton::clicked, [this, addCommsRow]() { int r = tw_Comms->rowCount(); tw_Comms->insertRow(r); addCommsRow(r); sb_count_Comms->blockSignals(true); sb_count_Comms->setValue(tw_Comms->rowCount()); sb_count_Comms->blockSignals(false); }); connect(btnDel, &QPushButton::clicked, [this]() { int r = tw_Comms->currentRow(); if (r >= 0) { tw_Comms->removeRow(r); sb_count_Comms->blockSignals(true); sb_count_Comms->setValue(tw_Comms->rowCount()); sb_count_Comms->blockSignals(false); } }); connect(sb_count_Comms, QOverload<int>::of(&QSpinBox::valueChanged), [this, addCommsRow](int val) { int oldRow = tw_Comms->rowCount(); updateTableRows(tw_Comms, val); for (int i = oldRow; i < val; ++i) { addCommsRow(i); } }); return widget; } // ============================================================================ // 3. 测距传感器配置页构建 (Height Sensor Config) - 新增 m_commsChannelName 列 // ============================================================================ QWidget* view_configGenerator::createHeightSensorTab() { auto *widget = new QWidget(); auto *layout = new QVBoxLayout(widget); auto *hl = new QHBoxLayout(); auto *btnAdd = new QPushButton(tr("Add Height Sensor"), widget); auto *btnDel = new QPushButton(tr("Delete Selected"), widget); hl->addWidget(btnAdd); hl->addWidget(btnDel); hl->addSpacing(20); hl->addWidget(new QLabel(tr("Height Sensor Count:"))); sb_count_HeightSensor = new QSpinBox(); sb_count_HeightSensor->setRange(0, 20); hl->addWidget(sb_count_HeightSensor); hl->addStretch(); layout->addLayout(hl); tw_HeightSensor = new QTableWidget(0, 9); tw_HeightSensor->setSelectionBehavior(QAbstractItemView::SelectRows); tw_HeightSensor->setSelectionMode(QAbstractItemView::SingleSelection); tw_HeightSensor->setHorizontalHeaderLabels({ tr("Sensor Name"), tr("Comms Channel Name"), tr("Comm Type"), tr("MSR Addr (Hex/Dec)"), tr("Status Addr (Hex/Dec)"), tr("Same Dir with Axis"), tr("Min Range"), tr("Max Range"), tr("Offset") }); tw_HeightSensor->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); layout->addWidget(tw_HeightSensor); auto addSensorRow = [this](int r) { tw_HeightSensor->setItem(r, 0, new QTableWidgetItem(QString("HeightSensor_%1").arg(r + 1))); tw_HeightSensor->setItem(r, 1, new QTableWidgetItem("COM_Channel_1")); auto *cbComm = new QComboBox(); cbComm->addItems(toStringList<data_HeightSensorConfig::HeightSensorType>()); tw_HeightSensor->setCellWidget(r, 2, cbComm); tw_HeightSensor->setItem(r, 3, new QTableWidgetItem("0x6000")); tw_HeightSensor->setItem(r, 4, new QTableWidgetItem("0x6001")); auto *chk = new QCheckBox(); auto *pContainer = new QWidget(); auto *pLayout = new QHBoxLayout(pContainer); pLayout->addWidget(chk); pLayout->setAlignment(Qt::AlignCenter); pLayout->setContentsMargins(0, 0, 0, 0); tw_HeightSensor->setCellWidget(r, 5, pContainer); tw_HeightSensor->setItem(r, 6, new QTableWidgetItem("0.0")); tw_HeightSensor->setItem(r, 7, new QTableWidgetItem("100.0")); tw_HeightSensor->setItem(r, 8, new QTableWidgetItem("0.0")); }; connect(btnAdd, &QPushButton::clicked, [this, addSensorRow]() { int r = tw_HeightSensor->rowCount(); tw_HeightSensor->insertRow(r); addSensorRow(r); sb_count_HeightSensor->blockSignals(true); sb_count_HeightSensor->setValue(tw_HeightSensor->rowCount()); sb_count_HeightSensor->blockSignals(false); }); connect(btnDel, &QPushButton::clicked, [this]() { int r = tw_HeightSensor->currentRow(); if (r >= 0) { tw_HeightSensor->removeRow(r); sb_count_HeightSensor->blockSignals(true); sb_count_HeightSensor->setValue(tw_HeightSensor->rowCount()); sb_count_HeightSensor->blockSignals(false); } }); connect(sb_count_HeightSensor, QOverload<int>::of(&QSpinBox::valueChanged), [this, addSensorRow](int val) { int oldRow = tw_HeightSensor->rowCount(); updateTableRows(tw_HeightSensor, val); for (int i = oldRow; i < val; ++i) { addSensorRow(i); } }); return widget; } // ============================================================================ // 4. 点胶机配置页构建 (Dispenser Config) - 新增 m_commsChannelName 列 // ============================================================================ QWidget* view_configGenerator::createDispenserTab() { auto *widget = new QWidget(); auto *layout = new QVBoxLayout(widget); auto *hl = new QHBoxLayout(); auto *btnAdd = new QPushButton(tr("Add Dispenser"), widget); auto *btnDel = new QPushButton(tr("Delete Selected"), widget); hl->addWidget(btnAdd); hl->addWidget(btnDel); hl->addSpacing(20); hl->addWidget(new QLabel(tr("Dispenser Count:"))); sb_count_Dispenser = new QSpinBox(); sb_count_Dispenser->setRange(0, 20); hl->addWidget(sb_count_Dispenser); hl->addStretch(); layout->addLayout(hl); tw_Dispenser = new QTableWidget(0, 17); tw_Dispenser->setSelectionBehavior(QAbstractItemView::SelectRows); tw_Dispenser->setSelectionMode(QAbstractItemView::SingleSelection); tw_Dispenser->setHorizontalHeaderLabels({ tr("Dispenser Name"), tr("Comms Channel/Controller Name"), tr("CommType"), tr("Port"), tr("BaudRate"), tr("Parity"), tr("DataBits"), tr("StopBits"), tr("Analog Addr"), tr("Min Pressure"), tr("Max Pressure"), tr("Default Pressure"), tr("Default Time(s)"), tr("Switch IO"), tr("Switch State"), tr("MainIO OpenGas"), tr("SubIO OpenGas") }); tw_Dispenser->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); layout->addWidget(tw_Dispenser); auto addDispenserRow = [this](int r) { int i = 0; tw_Dispenser->setItem(r, i++, new QTableWidgetItem("Dispenser1")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("ZMOTION_1")); auto *cbComm = new QComboBox(); cbComm->addItems(toStringList<data_DispenserConfig::DispenserType>()); tw_Dispenser->setCellWidget(r, i++, cbComm); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("COM1")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("9600")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("N")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("8")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("1")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("0")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("0.0")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("100.0")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("0.2")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("0.5")); tw_Dispenser->setItem(r, i++, new QTableWidgetItem("0")); auto *chk = new QCheckBox(); auto *pContainer = new QWidget(); auto *pLayout = new QHBoxLayout(pContainer); pLayout->addWidget(chk); pLayout->setAlignment(Qt::AlignCenter); pLayout->setContentsMargins(0, 0, 0, 0); tw_Dispenser->setCellWidget(r, i++, pContainer); tw_Dispenser->setItem(r,i++, new QTableWidgetItem("0")); tw_Dispenser->setItem(r,i++, new QTableWidgetItem("0")); }; connect(btnAdd, &QPushButton::clicked, [this, addDispenserRow]() { int r = tw_Dispenser->rowCount(); tw_Dispenser->insertRow(r); addDispenserRow(r); sb_count_Dispenser->blockSignals(true); sb_count_Dispenser->setValue(tw_Dispenser->rowCount()); sb_count_Dispenser->blockSignals(false); }); connect(btnDel, &QPushButton::clicked, [this]() { int r = tw_Dispenser->currentRow(); if (r >= 0) { tw_Dispenser->removeRow(r); sb_count_Dispenser->blockSignals(true); sb_count_Dispenser->setValue(tw_Dispenser->rowCount()); sb_count_Dispenser->blockSignals(false); } }); connect(sb_count_Dispenser, QOverload<int>::of(&QSpinBox::valueChanged), [this, addDispenserRow](int val) { int oldRow = tw_Dispenser->rowCount(); updateTableRows(tw_Dispenser, val); for (int i = oldRow; i < val; ++i) { addDispenserRow(i); } }); return widget; } // ============================================================================ // 5. 全局外设配置页构建 (External Device Config) - 追加 m_commsChannelName 列 // ============================================================================ QWidget* view_configGenerator::createExternalDeviceTab() { auto *widget = new QWidget(); auto *layout = new QVBoxLayout(widget); auto *hl = new QHBoxLayout(); auto *btnAdd = new QPushButton(tr("Add External Device"), widget); auto *btnDel = new QPushButton(tr("Delete Selected"), widget); hl->addWidget(btnAdd); hl->addWidget(btnDel); hl->addSpacing(20); hl->addWidget(new QLabel(tr("External Device Count:"))); sb_count_ExternalDevice = new QSpinBox(); sb_count_ExternalDevice->setRange(0, 50); hl->addWidget(sb_count_ExternalDevice); hl->addStretch(); layout->addLayout(hl); tw_ExternalDevice = new QTableWidget(0, 6); tw_ExternalDevice->setSelectionBehavior(QAbstractItemView::SelectRows); tw_ExternalDevice->setSelectionMode(QAbstractItemView::SingleSelection); tw_ExternalDevice->setHorizontalHeaderLabels({ tr("Device Name (userName)"), tr("Device Type"), tr("Comms Channel Name"), tr("Pos X"), tr("Pos Y"), tr("Pos Z") }); tw_ExternalDevice->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); layout->addWidget(tw_ExternalDevice); auto addExtDevRow = [this](int r) { tw_ExternalDevice->setItem(r, 0, new QTableWidgetItem(QString("ExtDevice_%1").arg(r + 1))); tw_ExternalDevice->setItem(r, 1, new QTableWidgetItem("HeightSensor")); tw_ExternalDevice->setItem(r, 2, new QTableWidgetItem("Comms_Channel_1")); tw_ExternalDevice->setItem(r, 3, new QTableWidgetItem("0.0")); tw_ExternalDevice->setItem(r, 4, new QTableWidgetItem("0.0")); tw_ExternalDevice->setItem(r, 5, new QTableWidgetItem("0.0")); }; connect(btnAdd, &QPushButton::clicked, [this, addExtDevRow]() { int r = tw_ExternalDevice->rowCount(); tw_ExternalDevice->insertRow(r); addExtDevRow(r); sb_count_ExternalDevice->blockSignals(true); sb_count_ExternalDevice->setValue(tw_ExternalDevice->rowCount()); sb_count_ExternalDevice->blockSignals(false); }); connect(btnDel, &QPushButton::clicked, [this]() { int r = tw_ExternalDevice->currentRow(); if (r >= 0) { tw_ExternalDevice->removeRow(r); sb_count_ExternalDevice->blockSignals(true); sb_count_ExternalDevice->setValue(tw_ExternalDevice->rowCount()); sb_count_ExternalDevice->blockSignals(false); } }); connect(sb_count_ExternalDevice, QOverload<int>::of(&QSpinBox::valueChanged), [this, addExtDevRow](int val) { int oldRow = tw_ExternalDevice->rowCount(); updateTableRows(tw_ExternalDevice, val); for (int i = oldRow; i < val; ++i) { addExtDevRow(i); } }); return widget; } // ============================================================================ // 6. 工作头配置页构建 (Toolhead Config) // ============================================================================ QWidget* view_configGenerator::createToolheadTab() { auto *widget = new QWidget(); auto *mainLayout = new QHBoxLayout(widget); auto *leftGroup = new QGroupBox(tr("Toolhead List"), widget); auto *leftLayout = new QVBoxLayout(leftGroup); m_toolheadListWidget = new QListWidget(leftGroup); auto *btnLayout = new QHBoxLayout(); auto *btnAddToolhead = new QPushButton(tr("Add Toolhead"), leftGroup); auto *btnDelToolhead = new QPushButton(tr("Delete Toolhead"), leftGroup); btnLayout->addWidget(btnAddToolhead); btnLayout->addWidget(btnDelToolhead); leftLayout->addWidget(m_toolheadListWidget); leftLayout->addLayout(btnLayout); m_toolheadRightGroup = new QGroupBox(tr("Toolhead Properties & Mounted Devices"), widget); auto *rightLayout = new QVBoxLayout(m_toolheadRightGroup); auto *formLayout = new QFormLayout(); m_editToolheadName = new QLineEdit(); m_chkIsVirtualToolhead = new QCheckBox(tr("Is Virtual Toolhead (Z-axis does not move)")); m_editBindMotionGroup = new QLineEdit("XY_Stage_1"); m_editBindZAxis = new QLineEdit("Z_Axis_1"); formLayout->addRow(tr("Toolhead Name (userName):"), m_editToolheadName); formLayout->addRow(tr("Virtual Flag:"), m_chkIsVirtualToolhead); formLayout->addRow(tr("Bind Motion Group (XY Stage):"), m_editBindMotionGroup); formLayout->addRow(tr("Bind Z Axis Name:"), m_editBindZAxis); rightLayout->addLayout(formLayout); auto *gbMountedDevs = new QGroupBox(tr("Mounted Devices List (mountedDevices)"), m_toolheadRightGroup); auto *mountedLayout = new QVBoxLayout(gbMountedDevs); m_mountedDevicesTable = new QTableWidget(0, 3); m_mountedDevicesTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_mountedDevicesTable->setSelectionMode(QAbstractItemView::SingleSelection); m_mountedDevicesTable->setHorizontalHeaderLabels({ tr("Device Name (userName)"), tr("Device Type"), tr("Comms Channel Name") }); m_mountedDevicesTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); auto *mDevBtnLayout = new QHBoxLayout(); auto *btnAddMDev = new QPushButton(tr("Add Mounted Device")); auto *btnDelMDev = new QPushButton(tr("Delete Mounted Device")); mDevBtnLayout->addWidget(btnAddMDev); mDevBtnLayout->addWidget(btnDelMDev); mDevBtnLayout->addStretch(); mountedLayout->addLayout(mDevBtnLayout); mountedLayout->addWidget(m_mountedDevicesTable); rightLayout->addWidget(gbMountedDevs); mainLayout->addWidget(leftGroup, 1); mainLayout->addWidget(m_toolheadRightGroup, 3); connect(btnAddToolhead, &QPushButton::clicked, this, &view_configGenerator::onAddToolhead); connect(btnDelToolhead, &QPushButton::clicked, this, &view_configGenerator::onDeleteToolhead); connect(m_toolheadListWidget, &QListWidget::currentRowChanged, this, &view_configGenerator::onToolheadSelected); connect(btnAddMDev, &QPushButton::clicked, this, &view_configGenerator::onAddMountedDevice); connect(btnDelMDev, &QPushButton::clicked, this, &view_configGenerator::onDeleteMountedDevice); return widget; } // ============================================================================ // 7. 通用配置页构建 (Common Config) // ============================================================================ QWidget* view_configGenerator::createCommonTab() { auto *widget = new QWidget(); auto *layout = new QFormLayout(widget); le_softwareName = new QLineEdit("ConfigGeneratorApp", widget); layout->addRow(tr("Software Name:"), le_softwareName); return widget; } // ============================================================================ // 控制卡 UI 交互槽实现 // ============================================================================ void view_configGenerator::onAddController() { saveCurrentControllerFromUI(); data_motion_controller newCard; newCard.m_userName = QString("Card_%1").arg(m_controllerList.size() + 1); m_controllerList.append(newCard); m_cardListWidget->addItem(newCard.m_userName); m_cardListWidget->setCurrentRow(m_controllerList.size() - 1); } void view_configGenerator::onDeleteController() { int row = m_cardListWidget->currentRow(); if (row < 0 || row >= m_controllerList.size()) return; m_controllerList.removeAt(row); delete m_cardListWidget->takeItem(row); m_currentCardIndex = -1; if (!m_controllerList.isEmpty()) { int nextRow = qMin(row, m_controllerList.size() - 1); m_cardListWidget->setCurrentRow(nextRow); } else { updateControllerRightPanel(); } } void view_configGenerator::onControllerSelected(int currentRow) { if (currentRow == m_currentCardIndex) return; saveCurrentControllerFromUI(); m_currentCardIndex = currentRow; updateControllerRightPanel(); } void view_configGenerator::saveCurrentControllerFromUI() { if (m_currentCardIndex < 0 || m_currentCardIndex >= m_controllerList.size()) return; data_motion_controller &card = m_controllerList[m_currentCardIndex]; card.m_userName = m_editCardName->text().trimmed(); card.motionControllerType = toEnum<data_motion_controller::MotionControllerType>(m_comboBrand->currentData().toString()); card.ipAddress = m_editIP->text().trimmed(); card.port = m_spinPort->value(); card.homePath_total = m_editAllAxisHomePath->text().trimmed(); card.b_showSub = m_showSub->isChecked(); if (auto *item = m_cardListWidget->item(m_currentCardIndex)) { item->setText(card.m_userName); } card.data_axisInfo.clear(); for (int r = 0; r < m_axisTable->rowCount(); ++r) { data_AxisInfo axis; axis.m_userName = m_axisTable->item(r, 0) ? m_axisTable->item(r, 0)->text() : ""; axis.axisNo = m_axisTable->item(r, 1) ? m_axisTable->item(r, 1)->text().toInt() : 0; axis.soft_leftLimit = m_axisTable->item(r, 2) ? m_axisTable->item(r, 2)->text().toDouble() : 0; axis.soft_rightLimit = m_axisTable->item(r, 3) ? m_axisTable->item(r, 3)->text().toDouble() : 0; axis.acc = m_axisTable->item(r, 4) ? m_axisTable->item(r, 4)->text().toDouble() : 500; axis.dec = m_axisTable->item(r, 5) ? m_axisTable->item(r, 5)->text().toDouble() : 500; axis.fastDec = m_axisTable->item(r, 6) ? m_axisTable->item(r, 6)->text().toDouble() : 500; if (auto *chkL = qobject_cast<QCheckBox*>(m_axisTable->cellWidget(r, 7))) axis.enable_leftSoftWareLimit = chkL->isChecked(); if (auto *chkR = qobject_cast<QCheckBox*>(m_axisTable->cellWidget(r, 8))) axis.enable_rightSoftWareLimit = chkR->isChecked(); axis.currentControllerName = card.m_userName; card.data_axisInfo.append(axis); } auto saveDigitalIO = [&](QTableWidget* table, QList<data_DoInfo>& list) { list.clear(); for (int r = 0; r < table->rowCount(); ++r) { data_DoInfo io; io.m_userName = table->item(r, 0) ? table->item(r, 0)->text() : ""; io.mainIO = table->item(r, 1) ? table->item(r, 1)->text().toInt() : 0; io.subIO = table->item(r, 2) ? table->item(r, 2)->text().toInt() : 0; io.currentControllerName = card.m_userName; io.showSub = card.b_showSub; list.append(io); } }; saveDigitalIO(m_dinTable, card.data_Din); saveDigitalIO(m_doutTable, card.data_Dout); auto saveAnalogIO = [&](QTableWidget* table, QList<data_AoInfo>& list) { list.clear(); for (int r = 0; r < table->rowCount(); ++r) { data_AoInfo io; io.m_userName = table->item(r, 0) ? table->item(r, 0)->text() : ""; io.address = table->item(r, 1) ? table->item(r, 1)->text().toInt() : 0; io.currentControllerName = card.m_userName; io.showSub = card.b_showSub; list.append(io); } }; saveAnalogIO(m_ainTable, card.data_Ain); saveAnalogIO(m_aoutTable, card.data_Aout); } void view_configGenerator::clearControllerRightPanel() { m_editCardName->clear(); m_editIP->clear(); m_spinPort->setValue(8080); m_axisTable->setRowCount(0); m_dinTable->setRowCount(0); m_doutTable->setRowCount(0); m_ainTable->setRowCount(0); m_aoutTable->setRowCount(0); } void view_configGenerator::updateControllerRightPanel() { if (m_currentCardIndex < 0 || m_currentCardIndex >= m_controllerList.size()) { m_controllerRightGroup->setEnabled(false); clearControllerRightPanel(); return; } m_controllerRightGroup->setEnabled(true); const data_motion_controller &card = m_controllerList[m_currentCardIndex]; m_editCardName->setText(card.m_userName); int brandIdx = m_comboBrand->findData(toString(card.motionControllerType)); m_comboBrand->setCurrentIndex(brandIdx >= 0 ? brandIdx : 0); m_editIP->setText(card.ipAddress); m_spinPort->setValue(card.port); m_editAllAxisHomePath->setText(card.homePath_total); m_showSub->setChecked(card.b_showSub); m_axisTable->setRowCount(0); for (const auto& axis : card.data_axisInfo) { int r = m_axisTable->rowCount(); m_axisTable->insertRow(r); m_axisTable->setItem(r, 0, new QTableWidgetItem(axis.m_userName)); m_axisTable->setItem(r, 1, new QTableWidgetItem(QString::number(axis.axisNo))); m_axisTable->setItem(r, 2, new QTableWidgetItem(QString::number(axis.soft_leftLimit))); m_axisTable->setItem(r, 3, new QTableWidgetItem(QString::number(axis.soft_rightLimit))); m_axisTable->setItem(r, 4, new QTableWidgetItem(QString::number(axis.acc))); m_axisTable->setItem(r, 5, new QTableWidgetItem(QString::number(axis.dec))); m_axisTable->setItem(r, 6, new QTableWidgetItem(QString::number(axis.fastDec))); auto *chkL = new QCheckBox(); chkL->setChecked(axis.enable_leftSoftWareLimit); m_axisTable->setCellWidget(r, 7, chkL); auto *chkR = new QCheckBox(); chkR->setChecked(axis.enable_rightSoftWareLimit); m_axisTable->setCellWidget(r, 8, chkR); } auto fillDigitalIO = [](QTableWidget* table, const QList<data_DoInfo>& list) { table->setRowCount(0); for (const auto& io : list) { int r = table->rowCount(); table->insertRow(r); table->setItem(r, 0, new QTableWidgetItem(io.m_userName)); table->setItem(r, 1, new QTableWidgetItem(QString::number(io.mainIO))); table->setItem(r, 2, new QTableWidgetItem(QString::number(io.subIO))); } }; fillDigitalIO(m_dinTable, card.data_Din); fillDigitalIO(m_doutTable, card.data_Dout); auto fillAnalogIO = [](QTableWidget* table, const QList<data_AoInfo>& list) { table->setRowCount(0); for (const auto& io : list) { int r = table->rowCount(); table->insertRow(r); table->setItem(r, 0, new QTableWidgetItem(io.m_userName)); table->setItem(r, 1, new QTableWidgetItem(QString::number(io.address))); } }; fillAnalogIO(m_ainTable, card.data_Ain); fillAnalogIO(m_aoutTable, card.data_Aout); } void view_configGenerator::onAddAxis() { int r = m_axisTable->rowCount(); m_axisTable->insertRow(r); m_axisTable->setItem(r, 0, new QTableWidgetItem(QString("Axis_%1").arg(r + 1))); m_axisTable->setItem(r, 1, new QTableWidgetItem(QString::number(r))); m_axisTable->setItem(r, 2, new QTableWidgetItem("-1000.0")); m_axisTable->setItem(r, 3, new QTableWidgetItem("1000.0")); m_axisTable->setItem(r, 4, new QTableWidgetItem("500.0")); m_axisTable->setItem(r, 5, new QTableWidgetItem("500.0")); m_axisTable->setItem(r, 6, new QTableWidgetItem("1000.0")); m_axisTable->setCellWidget(r, 7, new QCheckBox()); m_axisTable->setCellWidget(r, 8, new QCheckBox()); } void view_configGenerator::onDeleteAxis() { int r = m_axisTable->currentRow(); if (r >= 0) m_axisTable->removeRow(r); } void view_configGenerator::onAddIO(QTableWidget* table) { int r = table->rowCount(); table->insertRow(r); table->setItem(r, 0, new QTableWidgetItem(QString("IO_%1").arg(r + 1))); table->setItem(r, 1, new QTableWidgetItem("0")); if (table->columnCount() > 2) { table->setItem(r, 2, new QTableWidgetItem("0")); } } void view_configGenerator::onDeleteIO(QTableWidget* table) { int r = table->currentRow(); if (r >= 0) table->removeRow(r); } // ============================================================================ // 工作头 (Toolhead) Master-Detail UI 交互槽实现 // ============================================================================ void view_configGenerator::onAddToolhead() { saveCurrentToolheadFromUI(); data_ToolheadConfig newToolhead; newToolhead.m_userName = QString("Toolhead_%1").arg(m_toolheadList.size() + 1); m_toolheadList.append(newToolhead); m_toolheadListWidget->addItem(newToolhead.m_userName); m_toolheadListWidget->setCurrentRow(m_toolheadList.size() - 1); } void view_configGenerator::onDeleteToolhead() { int row = m_toolheadListWidget->currentRow(); if (row < 0 || row >= m_toolheadList.size()) return; m_toolheadList.removeAt(row); delete m_toolheadListWidget->takeItem(row); m_currentToolheadIndex = -1; if (!m_toolheadList.isEmpty()) { int nextRow = qMin(row, m_toolheadList.size() - 1); m_toolheadListWidget->setCurrentRow(nextRow); } else { updateToolheadRightPanel(); } } void view_configGenerator::onToolheadSelected(int currentRow) { if (currentRow == m_currentToolheadIndex) return; saveCurrentToolheadFromUI(); m_currentToolheadIndex = currentRow; updateToolheadRightPanel(); } void view_configGenerator::saveCurrentToolheadFromUI() { if (m_currentToolheadIndex < 0 || m_currentToolheadIndex >= m_toolheadList.size()) return; data_ToolheadConfig &th = m_toolheadList[m_currentToolheadIndex]; th.m_userName = m_editToolheadName->text().trimmed(); th.b_isVirtual = m_chkIsVirtualToolhead->isChecked(); th.bindMotionGroup = m_editBindMotionGroup->text().trimmed(); th.bindZAxisName = m_editBindZAxis->text().trimmed(); if (auto *item = m_toolheadListWidget->item(m_currentToolheadIndex)) { item->setText(th.m_userName); } th.mountedDevices.clear(); for (int r = 0; r < m_mountedDevicesTable->rowCount(); ++r) { data_externalDevice dev; dev.m_userName = m_mountedDevicesTable->item(r, 0) ? m_mountedDevicesTable->item(r, 0)->text() : ""; dev.m_deviceType = toEnum<data_externalDevice::ExternalDeviceType>( m_mountedDevicesTable->item(r, 1) ? m_mountedDevicesTable->item(r, 1)->text() : ""); dev.m_commsChannelName = m_mountedDevicesTable->item(r, 2) ? m_mountedDevicesTable->item(r, 2)->text() : ""; th.mountedDevices.append(dev); } } void view_configGenerator::clearToolheadRightPanel() { m_editToolheadName->clear(); m_chkIsVirtualToolhead->setChecked(false); m_editBindMotionGroup->clear(); m_editBindZAxis->clear(); m_mountedDevicesTable->setRowCount(0); } void view_configGenerator::updateToolheadRightPanel() { if (m_currentToolheadIndex < 0 || m_currentToolheadIndex >= m_toolheadList.size()) { m_toolheadRightGroup->setEnabled(false); clearToolheadRightPanel(); return; } m_toolheadRightGroup->setEnabled(true); const data_ToolheadConfig &th = m_toolheadList[m_currentToolheadIndex]; m_editToolheadName->setText(th.m_userName); m_chkIsVirtualToolhead->setChecked(th.b_isVirtual); m_editBindMotionGroup->setText(th.bindMotionGroup); m_editBindZAxis->setText(th.bindZAxisName); m_mountedDevicesTable->setRowCount(0); for (const auto& dev : th.mountedDevices) { int r = m_mountedDevicesTable->rowCount(); m_mountedDevicesTable->insertRow(r); m_mountedDevicesTable->setItem(r, 0, new QTableWidgetItem(dev.m_userName)); m_mountedDevicesTable->setItem(r, 1, new QTableWidgetItem(toString( dev.m_deviceType))); m_mountedDevicesTable->setItem(r, 2, new QTableWidgetItem(dev.m_commsChannelName)); } } void view_configGenerator::onAddMountedDevice() { int r = m_mountedDevicesTable->rowCount(); m_mountedDevicesTable->insertRow(r); m_mountedDevicesTable->setItem(r, 0, new QTableWidgetItem(QString("MountedDev_%1").arg(r + 1))); m_mountedDevicesTable->setItem(r, 1, new QTableWidgetItem("DispenserNozzle")); m_mountedDevicesTable->setItem(r, 2, new QTableWidgetItem("Comms_Channel_1")); } void view_configGenerator::onDeleteMountedDevice() { int r = m_mountedDevicesTable->currentRow(); if (r >= 0) m_mountedDevicesTable->removeRow(r); } // ============================================================================ // 数据同步与 JSON 序列化读写 // ============================================================================ QJsonObject view_configGenerator::saveToTempJson() { saveCurrentControllerFromUI(); saveCurrentToolheadFromUI(); data_equipment config; config.deviceName = le_softwareName->text().trimmed(); // 1. 读取 Motion Controller 列表 config.data_motion_controller_configs = m_controllerList; // 2. 读取 通讯模块 列表 for (int i = 0; i < tw_Comms->rowCount(); ++i) { data_CommsConfig comm; comm.m_userName = tw_Comms->item(i, 0) ? tw_Comms->item(i, 0)->text() : ""; if (auto *cbType = qobject_cast<QComboBox*>(tw_Comms->cellWidget(i, 1))) { comm.commsType =toEnum<data_CommsConfig::CommsType>(cbType->currentText()) ; } comm.portName = tw_Comms->item(i, 2) ? tw_Comms->item(i, 2)->text() : "COM1"; comm.baudRate = tw_Comms->item(i, 3) ? tw_Comms->item(i, 3)->text().toInt() : 115200; QString parityStr = tw_Comms->item(i, 4) ? tw_Comms->item(i, 4)->text() : "N"; comm.parity = parityStr.isEmpty() ? 'N' : parityStr.at(0).toLatin1(); comm.dataBits = tw_Comms->item(i, 5) ? tw_Comms->item(i, 5)->text().toInt() : 8; comm.stopBits = tw_Comms->item(i, 6) ? tw_Comms->item(i, 6)->text().toInt() : 1; comm.ip = tw_Comms->item(i, 7) ? tw_Comms->item(i, 7)->text() : "192.168.1.100"; comm.tcpPort = tw_Comms->item(i, 8) ? tw_Comms->item(i, 8)->text().toInt() : 8080; comm.slaveAddress = tw_Comms->item(i, 9) ? tw_Comms->item(i, 9)->text().toInt() : 1; comm.timeoutMs = tw_Comms->item(i, 10) ? tw_Comms->item(i, 10)->text().toInt() : 1000; comm.retryTimes = tw_Comms->item(i, 11) ? tw_Comms->item(i, 11)->text().toInt() : 2; config.data_comms_configs.append(comm); } // 3. 读取 测距传感器 列表 (Height Sensor) for (int i = 0; i < tw_HeightSensor->rowCount(); ++i) { data_HeightSensorConfig sensor; sensor.m_userName = tw_HeightSensor->item(i, 0) ? tw_HeightSensor->item(i, 0)->text() : ""; sensor.m_commsChannelName = tw_HeightSensor->item(i, 1) ? tw_HeightSensor->item(i, 1)->text() : ""; sensor.m_deviceType =data_externalDevice::HEIGHT_SENSOR; if (auto *cbComm = qobject_cast<QComboBox*>(tw_HeightSensor->cellWidget(i, 2))) { sensor.commType = cbComm->currentText(); } QString msrAddrStr = tw_HeightSensor->item(i, 3) ? tw_HeightSensor->item(i, 3)->text() : "0x6000"; bool ok = false; sensor.msrAddress = msrAddrStr.toUInt(&ok, 0); QString statusAddrStr = tw_HeightSensor->item(i, 4) ? tw_HeightSensor->item(i, 4)->text() : "0x6001"; sensor.statusAddress = statusAddrStr.toUInt(&ok, 0); if (auto *pContainer = tw_HeightSensor->cellWidget(i, 5)) { if (auto *chk = pContainer->findChild<QCheckBox*>()) { sensor.b_same_direction_with_axis = chk->isChecked(); } } sensor.minRange = tw_HeightSensor->item(i, 6) ? tw_HeightSensor->item(i, 6)->text().toDouble() : 0.0; sensor.maxRange = tw_HeightSensor->item(i, 7) ? tw_HeightSensor->item(i, 7)->text().toDouble() : 0.0; sensor.offset = tw_HeightSensor->item(i, 8) ? tw_HeightSensor->item(i, 8)->text().toDouble() : 0.0; config.data_heightSensor_configs.append(sensor); } // 4. 读取 Dispenser 列表 for (int i = 0; i < tw_Dispenser->rowCount(); ++i) { data_DispenserConfig disp; int j = 0; disp.m_userName = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text() : ""; j++; disp.m_commsChannelName = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text() : ""; j++; disp.m_deviceType = data_externalDevice::ExternalDeviceType::DISPENSOR; if (auto *cbComm = qobject_cast<QComboBox*>(tw_Dispenser->cellWidget(i, j))) { disp.commType = cbComm->currentText(); } j++; disp.port = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text() : "COM1"; j++; disp.baudRate = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toInt() : 9600; j++; QString parityStr = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text() : "N"; disp.parity = parityStr.isEmpty() ? 'N' : parityStr.at(0).toLatin1(); j++; disp.dataBits = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toInt() : 8; j++; disp.stopBits = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toInt() : 1; j++; disp.analogAddress = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toInt() : 0; j++; disp.minPressure = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toFloat() : 0.0f; j++; disp.maxPressure = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toFloat() : 100.0f; j++; disp.defaultPressure = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toDouble() : 0.2; j++; disp.defaultDispenseTime = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toDouble() : 0.5; j++; disp.outputSwitchIO = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toInt() : 0; j++; if (auto *pContainer = tw_Dispenser->cellWidget(i, j)) { if (auto *chk = pContainer->findChild<QCheckBox*>()) { disp.state_outputSwitch = chk->isChecked(); } } j++; disp.mainIO_openGas = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i, j)->text().toInt() : 0; j++; disp.subIO_openGas = tw_Dispenser->item(i, j) ? tw_Dispenser->item(i,j)->text().toInt() : 0; j++; config.data_dispenser_configs.append(disp); } // 5. 读取 External Devices 全局外设列表 for (int i = 0; i < tw_ExternalDevice->rowCount(); ++i) { data_externalDevice dev; dev.m_userName = tw_ExternalDevice->item(i, 0) ? tw_ExternalDevice->item(i, 0)->text() : ""; dev.m_deviceType =toEnum<data_externalDevice::ExternalDeviceType>( tw_ExternalDevice->item(i, 1) ? tw_ExternalDevice->item(i, 1)->text() : ""); dev.m_commsChannelName = tw_ExternalDevice->item(i, 2) ? tw_ExternalDevice->item(i, 2)->text() : ""; dev.pos_x = tw_ExternalDevice->item(i, 3) ? tw_ExternalDevice->item(i, 3)->text().toDouble() : 0.0; dev.pos_y = tw_ExternalDevice->item(i, 4) ? tw_ExternalDevice->item(i, 4)->text().toDouble() : 0.0; dev.pos_z = tw_ExternalDevice->item(i, 5) ? tw_ExternalDevice->item(i, 5)->text().toDouble() : 0.0; config.data_external_device_configs.append(dev); } // 6. 读取 Toolhead 工作头列表 config.data_toolhead_configs = m_toolheadList; *currentData = config; return config.toJson(); } void view_configGenerator::loadFromTempJson(const QJsonObject& json) { data_equipment config; config.fromJson(json); *currentData = config; le_softwareName->setText(config.deviceName); // 1. 加载 Motion Controller 数组 m_controllerList = config.data_motion_controller_configs; m_cardListWidget->clear(); for (const auto& card : m_controllerList) { m_cardListWidget->addItem(card.m_userName); } m_currentCardIndex = -1; if (!m_controllerList.isEmpty()) { m_cardListWidget->setCurrentRow(0); } else { updateControllerRightPanel(); } // 2. 加载 通讯模块 sb_count_Comms->setValue(config.data_comms_configs.size()); for (int i = 0; i < config.data_comms_configs.size(); ++i) { const auto &comm = config.data_comms_configs[i]; tw_Comms->setItem(i, 0, new QTableWidgetItem(comm.m_userName)); if (auto *cbType = qobject_cast<QComboBox*>(tw_Comms->cellWidget(i, 1))) { cbType->setCurrentText(toString(comm.commsType) ); } tw_Comms->setItem(i, 2, new QTableWidgetItem(comm.portName)); tw_Comms->setItem(i, 3, new QTableWidgetItem(QString::number(comm.baudRate))); tw_Comms->setItem(i, 4, new QTableWidgetItem(QString(comm.parity))); tw_Comms->setItem(i, 5, new QTableWidgetItem(QString::number(comm.dataBits))); tw_Comms->setItem(i, 6, new QTableWidgetItem(QString::number(comm.stopBits))); tw_Comms->setItem(i, 7, new QTableWidgetItem(comm.ip)); tw_Comms->setItem(i, 8, new QTableWidgetItem(QString::number(comm.tcpPort))); tw_Comms->setItem(i, 9, new QTableWidgetItem(QString::number(comm.slaveAddress))); tw_Comms->setItem(i, 10, new QTableWidgetItem(QString::number(comm.timeoutMs))); tw_Comms->setItem(i, 11, new QTableWidgetItem(QString::number(comm.retryTimes))); } // 3. 加载 测距传感器 (Height Sensor) sb_count_HeightSensor->setValue(config.data_heightSensor_configs.size()); for (int i = 0; i < config.data_heightSensor_configs.size(); ++i) { const auto &sensor = config.data_heightSensor_configs[i]; tw_HeightSensor->setItem(i, 0, new QTableWidgetItem(sensor.m_userName)); tw_HeightSensor->setItem(i, 1, new QTableWidgetItem(sensor.m_commsChannelName)); if (auto *cbComm = qobject_cast<QComboBox*>(tw_HeightSensor->cellWidget(i, 2))) { cbComm->setCurrentText(sensor.commType); } tw_HeightSensor->setItem(i, 3, new QTableWidgetItem(QString("0x%1").arg(sensor.msrAddress, 4, 16, QChar('0')))); tw_HeightSensor->setItem(i, 4, new QTableWidgetItem(QString("0x%1").arg(sensor.statusAddress, 4, 16, QChar('0')))); if (auto *pContainer = tw_HeightSensor->cellWidget(i, 5)) { if (auto *chk = pContainer->findChild<QCheckBox*>()) { chk->setChecked(sensor.b_same_direction_with_axis); } } tw_HeightSensor->setItem(i, 6, new QTableWidgetItem(QString::number(sensor.minRange))); tw_HeightSensor->setItem(i, 7, new QTableWidgetItem(QString::number(sensor.maxRange))); tw_HeightSensor->setItem(i, 8, new QTableWidgetItem(QString::number(sensor.offset))); } // 4. 加载 Dispenser sb_count_Dispenser->setValue(config.data_dispenser_configs.size()); for (int i = 0; i < config.data_dispenser_configs.size(); ++i) { const auto &disp = config.data_dispenser_configs[i]; int j = 0; tw_Dispenser->setItem(i, j++, new QTableWidgetItem(disp.m_userName)); tw_Dispenser->setItem(i, j++, new QTableWidgetItem(disp.m_commsChannelName)); if (auto *cbComm = qobject_cast<QComboBox*>(tw_Dispenser->cellWidget(i, j++))) { cbComm->setCurrentText(disp.commType); } tw_Dispenser->setItem(i,j++, new QTableWidgetItem(disp.port)); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.baudRate))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString(disp.parity))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.dataBits))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.stopBits))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.analogAddress))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.minPressure))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.maxPressure))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.defaultPressure))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.defaultDispenseTime))); tw_Dispenser->setItem(i,j++, new QTableWidgetItem(QString::number(disp.outputSwitchIO))); if (auto *pContainer = tw_Dispenser->cellWidget(i, j++)) { if (auto *chk = pContainer->findChild<QCheckBox*>()) { chk->setChecked(disp.state_outputSwitch); } } tw_Dispenser->setItem(i, j++, new QTableWidgetItem(QString::number(disp.mainIO_openGas))); tw_Dispenser->setItem(i, j++, new QTableWidgetItem(QString::number(disp.subIO_openGas))); } // 5. 加载 External Devices 全局外设 sb_count_ExternalDevice->setValue(config.data_external_device_configs.size()); for (int i = 0; i < config.data_external_device_configs.size(); ++i) { const auto &dev = config.data_external_device_configs[i]; tw_ExternalDevice->setItem(i, 0, new QTableWidgetItem(dev.m_userName)); tw_ExternalDevice->setItem(i, 1, new QTableWidgetItem(dev.m_deviceType)); tw_ExternalDevice->setItem(i, 2, new QTableWidgetItem(dev.m_commsChannelName)); tw_ExternalDevice->setItem(i, 3, new QTableWidgetItem(QString::number(dev.pos_x))); tw_ExternalDevice->setItem(i, 4, new QTableWidgetItem(QString::number(dev.pos_y))); tw_ExternalDevice->setItem(i, 5, new QTableWidgetItem(QString::number(dev.pos_z))); } // 6. 加载 Toolhead 工作头数组 m_toolheadList = config.data_toolhead_configs; m_toolheadListWidget->clear(); for (const auto& th : m_toolheadList) { m_toolheadListWidget->addItem(th.m_userName); } m_currentToolheadIndex = -1; if (!m_toolheadList.isEmpty()) { m_toolheadListWidget->setCurrentRow(0); } else { updateToolheadRightPanel(); } } // 文件加载与保存槽函数 void view_configGenerator::onLoadConfigFromFile() { QString path = QFileDialog::getOpenFileName(this, tr("Open Config File"), "", tr("e3d Files (*.e3d *.json)")); if (path.isEmpty()) return; QFile file(path); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::critical(this, tr("Error"), tr("Failed to open configuration file!")); return; } QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); file.close(); le_configPath->setText(path); loadFromTempJson(doc.object()); QMessageBox::information(this, tr("Information"), tr("Configuration file loaded successfully!")); } void view_configGenerator::onSaveConfigToFile() { saveToTempJson(); if (!e3d_configManager_Equipment::Instance()->saveToFile_dialog(currentData)) { return; } } void view_configGenerator::onSaveTempClicked() { saveToTempJson(); QMessageBox::information(this, tr("Information"), tr("Configuration saved to temporary memory!")); }