saltar al contenido principal
paste
bin
.ca
type · paste · share
⌘
K
Familia
La familia bin
pastebin.ca
centro
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.
Docs
Iniciar sesión
?
← volver a la publicación
›
Editar / bifurcar
Publicación sin título
#4QGQdn3SfJ
public / public
nueva versión
por @amber-zebra-8262
creado 25 days ago
sin caducidad
48.4 KB
sintaxis:
text
Tus cambios crean una nueva publicación enlazada a esta — la original no se toca.
nueva versión
Tus cambios crean una nueva publicación enlazada a esta — la original no se toca.
Título (opcional)
Nombre de archivo
Sintaxis
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
Visibilidad
Feed público
Acceso
public
Caduca
7 días
10 min
1 hora
1 día
7 días
30 días
90 días
personalizada…
Caducidad personalizada
Nota de cambio
(opcional)
Esta publicación aparecerá en el feed público. Cambia Visibilidad si solo quieres compartirla por enlace.
Crear nueva versión
Cancelar
Pegar o escribir…
#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!")); }