rendered paste body#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!"));}