1065 lines
42 KiB
C++
1065 lines
42 KiB
C++
#include "dialogconfigtree.h"
|
||
#include "ui_dialogconfigtree.h"
|
||
#include "dialogcameralevel.h"
|
||
#include "GrabBagPresenter.h"
|
||
#include "HandEyeCalibMatrixLoader.h"
|
||
#include "StyledMessageBox.h"
|
||
#include <QInputDialog>
|
||
#include <QFileDialog>
|
||
#include <QFont>
|
||
#include <QColor>
|
||
#include <QPalette>
|
||
#include <QComboBox>
|
||
|
||
enum TreeItemType {
|
||
TYPE_ROOT = 0,
|
||
TYPE_WORKPOS = 1,
|
||
TYPE_CAMERA = 2,
|
||
TYPE_PACKAGE = 3
|
||
};
|
||
|
||
DialogConfigTree::DialogConfigTree(ConfigResult* configResult,
|
||
const std::vector<std::pair<std::string, IVrEyeDevice*>>& deviceList,
|
||
GrabBagPresenter* presenter,
|
||
QWidget *parent) :
|
||
QDialog(parent),
|
||
ui(new Ui::DialogConfigTree),
|
||
m_configResult(configResult),
|
||
m_deviceList(deviceList),
|
||
m_presenter(presenter)
|
||
{
|
||
ui->setupUi(this);
|
||
// setWindowFlags(Qt::FramelessWindowHint);
|
||
|
||
// 设置树形控件支持取消选中
|
||
ui->treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||
|
||
// 设置选中项的背景颜色(浅蓝色)
|
||
QPalette palette = ui->treeWidget->palette();
|
||
palette.setColor(QPalette::Highlight, QColor(135, 206, 235)); // 浅蓝色
|
||
palette.setColor(QPalette::HighlightedText, Qt::black);
|
||
ui->treeWidget->setPalette(palette);
|
||
|
||
connect(ui->treeWidget, &QTreeWidget::itemClicked, this, &DialogConfigTree::onTreeItemClicked);
|
||
connect(ui->btnAdd, &QPushButton::clicked, this, &DialogConfigTree::onAddClicked);
|
||
connect(ui->btnDelete, &QPushButton::clicked, this, &DialogConfigTree::onDeleteClicked);
|
||
connect(ui->btnSetDefault, &QPushButton::clicked, this, &DialogConfigTree::onSetDefaultClicked);
|
||
connect(ui->btnSave, &QPushButton::clicked, this, &DialogConfigTree::onSaveClicked);
|
||
connect(ui->btnCancel, &QPushButton::clicked, this, &DialogConfigTree::onCancelClicked);
|
||
|
||
// 连接相机页面的按钮
|
||
connect(ui->btnDoLevelCalib, &QPushButton::clicked, this, &DialogConfigTree::onCameraLevelClicked);
|
||
connect(ui->btnHeSave, &QPushButton::clicked, this, &DialogConfigTree::onHandEyeCalibSaveClicked);
|
||
connect(ui->btnHeLoadFromFile, &QPushButton::clicked, this, &DialogConfigTree::onHandEyeCalibLoadClicked);
|
||
|
||
// 连接工位配置按钮
|
||
connect(ui->btnUpdateWpName, &QPushButton::clicked, this, &DialogConfigTree::onUpdateWpNameClicked);
|
||
|
||
// 连接包裹配置按钮
|
||
connect(ui->btnSavePkgParam, &QPushButton::clicked, this, &DialogConfigTree::onSavePkgParamClicked);
|
||
|
||
initTree();
|
||
}
|
||
|
||
DialogConfigTree::~DialogConfigTree()
|
||
{
|
||
delete ui;
|
||
}
|
||
|
||
void DialogConfigTree::initTree()
|
||
{
|
||
ui->treeWidget->clear();
|
||
|
||
// 使用 ConfigResult 中的默认ID
|
||
std::string defaultWpId = m_configResult->defaultWorkPositionId;
|
||
std::string defaultCamId = m_configResult->defaultCameraId;
|
||
std::string defaultPkgId = m_configResult->defaultPackageId;
|
||
|
||
// 构建三级树:工位 -> 相机 -> 包裹
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
QTreeWidgetItem* wpItem = new QTreeWidgetItem(ui->treeWidget);
|
||
QString wpName = QString::fromStdString(wp.name);
|
||
// 检查该工位是否是默认工位
|
||
if (wp.id == defaultWpId) {
|
||
wpName += " [默认]";
|
||
}
|
||
wpItem->setText(0, wpName);
|
||
wpItem->setData(0, Qt::UserRole, TYPE_WORKPOS);
|
||
wpItem->setData(0, Qt::UserRole + 1, QString::fromStdString(wp.id));
|
||
|
||
// 相机节点
|
||
for (auto& cam : wp.cameras) {
|
||
QTreeWidgetItem* camItem = new QTreeWidgetItem(wpItem);
|
||
|
||
// 显示相机名称
|
||
QString camName = QString::fromStdString(cam.cameraName);
|
||
|
||
// 检查该相机是否是默认相机
|
||
if (cam.id == defaultCamId && wp.id == defaultWpId) {
|
||
camName += " [默认]";
|
||
}
|
||
camItem->setText(0, camName);
|
||
camItem->setData(0, Qt::UserRole, TYPE_CAMERA);
|
||
camItem->setData(0, Qt::UserRole + 1, QString::fromStdString(wp.id)); // 工位ID
|
||
camItem->setData(0, Qt::UserRole + 2, QString::fromStdString(cam.id)); // 相机ID
|
||
|
||
// 包裹节点
|
||
for (auto& pkg : cam.packages) {
|
||
QTreeWidgetItem* pkgItem = new QTreeWidgetItem(camItem);
|
||
|
||
// 从包裹ID中提取数字编号(格式:pkg_1 -> 1)
|
||
QString pkgIdStr = QString::fromStdString(pkg.id);
|
||
QString pkgNumber = pkgIdStr;
|
||
if (pkgIdStr.startsWith("pkg_")) {
|
||
pkgNumber = pkgIdStr.mid(4); // 提取 "pkg_" 后面的数字
|
||
}
|
||
|
||
// 显示格式:包裹名称 (ID编号)
|
||
QString pkgName = QString("%1 (%2)")
|
||
.arg(QString::fromStdString(pkg.name))
|
||
.arg(pkgNumber);
|
||
|
||
if (pkg.id == defaultPkgId && cam.id == defaultCamId && wp.id == defaultWpId) {
|
||
pkgName += " [默认]";
|
||
}
|
||
pkgItem->setText(0, pkgName);
|
||
pkgItem->setData(0, Qt::UserRole, TYPE_PACKAGE);
|
||
pkgItem->setData(0, Qt::UserRole + 1, QString::fromStdString(wp.id)); // 工位ID
|
||
pkgItem->setData(0, Qt::UserRole + 2, QString::fromStdString(cam.id)); // 相机ID
|
||
pkgItem->setData(0, Qt::UserRole + 3, QString::fromStdString(pkg.id)); // 包裹ID
|
||
}
|
||
}
|
||
}
|
||
|
||
ui->treeWidget->expandAll();
|
||
// 默认不选中任何项
|
||
ui->treeWidget->clearSelection();
|
||
m_currentItem = nullptr;
|
||
updateConfigPanel(nullptr);
|
||
}
|
||
|
||
void DialogConfigTree::onTreeItemClicked(QTreeWidgetItem* item, int column)
|
||
{
|
||
Q_UNUSED(column);
|
||
|
||
// 检查是否点击的是当前已选中的项,如果是则取消选中
|
||
if (m_currentItem == item) {
|
||
// 再次点击同一项,取消选中
|
||
ui->treeWidget->clearSelection();
|
||
m_currentItem = nullptr;
|
||
updateConfigPanel(nullptr);
|
||
} else {
|
||
// 点击了不同的项,保存当前配置并选中新项
|
||
saveCurrentConfig();
|
||
m_currentItem = item;
|
||
// 确保项被选中并显示背景颜色
|
||
ui->treeWidget->setCurrentItem(item);
|
||
updateConfigPanel(item);
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::updateConfigPanel(QTreeWidgetItem* item)
|
||
{
|
||
if (!item) {
|
||
ui->stackedWidget->setCurrentWidget(ui->emptyPage);
|
||
m_currentWorkPos = nullptr;
|
||
m_currentCamera = nullptr;
|
||
m_currentPackage = nullptr;
|
||
return;
|
||
}
|
||
|
||
int type = item->data(0, Qt::UserRole).toInt();
|
||
|
||
if (type == TYPE_WORKPOS) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
showWorkPositionConfig(&wp);
|
||
m_currentWorkPos = ℘
|
||
m_currentCamera = nullptr;
|
||
m_currentPackage = nullptr;
|
||
break;
|
||
}
|
||
}
|
||
} else if (type == TYPE_CAMERA) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
CameraConfig* cam = wp.GetCamera(camId.toStdString());
|
||
if (cam) {
|
||
// 确保相机参数已初始化
|
||
if (!cam->planeCalibParam.cameraIndex) {
|
||
cam->planeCalibParam.cameraIndex = cam->cameraIndex;
|
||
cam->planeCalibParam.cameraName = cam->cameraName;
|
||
cam->planeCalibParam.isCalibrated = false;
|
||
for (int i = 0; i < 9; i++) {
|
||
cam->planeCalibParam.planeCalib[i] = (i % 4 == 0) ? 1.0 : 0.0;
|
||
cam->planeCalibParam.invRMatrix[i] = (i % 4 == 0) ? 1.0 : 0.0;
|
||
}
|
||
}
|
||
|
||
if (!cam->handEyeCalibParam.cameraIndex) {
|
||
cam->handEyeCalibParam.cameraIndex = cam->cameraIndex;
|
||
cam->handEyeCalibParam.cameraName = cam->cameraName;
|
||
cam->handEyeCalibParam.isCalibrated = false;
|
||
for (int i = 0; i < 16; i++) {
|
||
cam->handEyeCalibParam.transformMatrix[i] = (i % 5 == 0) ? 1.0 : 0.0;
|
||
}
|
||
}
|
||
|
||
showCameraConfig(&wp, cam);
|
||
m_currentWorkPos = ℘
|
||
m_currentCamera = cam;
|
||
m_currentPackage = nullptr;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
} else if (type == TYPE_PACKAGE) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
QString pkgId = item->data(0, Qt::UserRole + 3).toString();
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
CameraConfig* cam = wp.GetCamera(camId.toStdString());
|
||
if (cam) {
|
||
PackageTypeConfig* pkg = cam->GetPackage(pkgId.toStdString());
|
||
if (pkg) {
|
||
showPackageConfig(&wp, cam, pkg);
|
||
m_currentWorkPos = ℘
|
||
m_currentCamera = cam;
|
||
m_currentPackage = pkg;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
ui->stackedWidget->setCurrentWidget(ui->emptyPage);
|
||
m_currentWorkPos = nullptr;
|
||
m_currentCamera = nullptr;
|
||
m_currentPackage = nullptr;
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::showWorkPositionConfig(const WorkPositionConfig* config)
|
||
{
|
||
ui->editWpName->setText(QString::fromStdString(config->name));
|
||
ui->stackedWidget->setCurrentWidget(ui->workPosPage);
|
||
}
|
||
|
||
void DialogConfigTree::showCameraConfig(const WorkPositionConfig* wpConfig, const CameraConfig* camConfig)
|
||
{
|
||
Q_UNUSED(wpConfig);
|
||
|
||
// 显示相机名称
|
||
ui->editCameraName->setText(QString::fromStdString(camConfig->cameraName));
|
||
|
||
// 从ConfigResult的cameraList中查找相机IP地址
|
||
QString cameraIP = "未配置";
|
||
if (m_configResult) {
|
||
for (const auto& camera : m_configResult->cameraList) {
|
||
if (camera.name == camConfig->cameraName) {
|
||
cameraIP = QString::fromStdString(camera.ip);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 显示相机IP
|
||
ui->editCameraIP->setText(cameraIP);
|
||
|
||
// 显示调平状态
|
||
if (camConfig->planeCalibParam.isCalibrated) {
|
||
ui->labelLevelStatus->setText("标定状态: 已标定");
|
||
} else {
|
||
ui->labelLevelStatus->setText("标定状态: 未标定");
|
||
}
|
||
|
||
// 显示手眼标定状态
|
||
if (camConfig->handEyeCalibParam.isCalibrated) {
|
||
ui->labelHandEyeStatus->setText("标定状态: 已标定");
|
||
} else {
|
||
ui->labelHandEyeStatus->setText("标定状态: 未标定");
|
||
}
|
||
|
||
// 显示手眼标定矩阵
|
||
const double* matrix = camConfig->handEyeCalibParam.transformMatrix;
|
||
ui->edit_he_m00->setText(QString::number(matrix[0], 'f', 6));
|
||
ui->edit_he_m01->setText(QString::number(matrix[1], 'f', 6));
|
||
ui->edit_he_m02->setText(QString::number(matrix[2], 'f', 6));
|
||
ui->edit_he_m03->setText(QString::number(matrix[3], 'f', 6));
|
||
|
||
ui->edit_he_m10->setText(QString::number(matrix[4], 'f', 6));
|
||
ui->edit_he_m11->setText(QString::number(matrix[5], 'f', 6));
|
||
ui->edit_he_m12->setText(QString::number(matrix[6], 'f', 6));
|
||
ui->edit_he_m13->setText(QString::number(matrix[7], 'f', 6));
|
||
|
||
ui->edit_he_m20->setText(QString::number(matrix[8], 'f', 6));
|
||
ui->edit_he_m21->setText(QString::number(matrix[9], 'f', 6));
|
||
ui->edit_he_m22->setText(QString::number(matrix[10], 'f', 6));
|
||
ui->edit_he_m23->setText(QString::number(matrix[11], 'f', 6));
|
||
|
||
ui->edit_he_m30->setText(QString::number(matrix[12], 'f', 6));
|
||
ui->edit_he_m31->setText(QString::number(matrix[13], 'f', 6));
|
||
ui->edit_he_m32->setText(QString::number(matrix[14], 'f', 6));
|
||
ui->edit_he_m33->setText(QString::number(matrix[15], 'f', 6));
|
||
|
||
ui->stackedWidget->setCurrentWidget(ui->cameraPage);
|
||
}
|
||
|
||
void DialogConfigTree::showPackageConfig(const WorkPositionConfig* wpConfig,
|
||
const CameraConfig* camConfig,
|
||
const PackageTypeConfig* pkgConfig)
|
||
{
|
||
Q_UNUSED(wpConfig);
|
||
|
||
// 包裹名称
|
||
ui->editPkgName->setText(QString::fromStdString(pkgConfig->name));
|
||
|
||
// 包裹尺寸参数 - 使用ConfigResult中的默认值
|
||
if (pkgConfig->bagParam.bagL == 0.0 && pkgConfig->bagParam.bagW == 0.0 && pkgConfig->bagParam.bagH == 0.0) {
|
||
// 未初始化,使用ConfigResult中的默认值
|
||
ui->spinBagL->setValue(m_configResult->algorithmParams.bagParam.bagL);
|
||
ui->spinBagW->setValue(m_configResult->algorithmParams.bagParam.bagW);
|
||
ui->spinBagH->setValue(m_configResult->algorithmParams.bagParam.bagH);
|
||
} else {
|
||
ui->spinBagL->setValue(pkgConfig->bagParam.bagL);
|
||
ui->spinBagW->setValue(pkgConfig->bagParam.bagW);
|
||
ui->spinBagH->setValue(pkgConfig->bagParam.bagH);
|
||
}
|
||
|
||
// 垛尺寸参数 - 使用ConfigResult中的默认值
|
||
if (pkgConfig->pileParam.pileL == 0.0 && pkgConfig->pileParam.pileW == 0.0 && pkgConfig->pileParam.pileH == 0.0) {
|
||
// 未初始化,使用ConfigResult中的默认值
|
||
ui->spinPileL->setValue(m_configResult->algorithmParams.pileParam.pileL);
|
||
ui->spinPileW->setValue(m_configResult->algorithmParams.pileParam.pileW);
|
||
ui->spinPileH->setValue(m_configResult->algorithmParams.pileParam.pileH);
|
||
} else {
|
||
ui->spinPileL->setValue(pkgConfig->pileParam.pileL);
|
||
ui->spinPileW->setValue(pkgConfig->pileParam.pileW);
|
||
ui->spinPileH->setValue(pkgConfig->pileParam.pileH);
|
||
}
|
||
|
||
// 相机参数(如果存在)
|
||
const VrCameraParams* camParams = pkgConfig->GetCameraParam(camConfig->cameraIndex);
|
||
if (camParams) {
|
||
ui->spinExposure->setValue(camParams->exposure);
|
||
ui->spinGain->setValue(camParams->gain);
|
||
ui->spinFrameRate->setValue(camParams->frameRate);
|
||
ui->spinSwingSpeed->setValue(camParams->swingSpeed);
|
||
ui->spinSwingStartAngle->setValue(camParams->swingStartAngle);
|
||
ui->spinSwingStopAngle->setValue(camParams->swingStopAngle);
|
||
} else {
|
||
// 使用VrCameraParams结构的默认值
|
||
VrCameraParams defaultParams;
|
||
ui->spinExposure->setValue(defaultParams.exposure);
|
||
ui->spinGain->setValue(defaultParams.gain);
|
||
ui->spinFrameRate->setValue(defaultParams.frameRate);
|
||
ui->spinSwingSpeed->setValue(defaultParams.swingSpeed);
|
||
ui->spinSwingStartAngle->setValue(defaultParams.swingStartAngle);
|
||
ui->spinSwingStopAngle->setValue(defaultParams.swingStopAngle);
|
||
}
|
||
|
||
ui->stackedWidget->setCurrentWidget(ui->packagePage);
|
||
}
|
||
|
||
void DialogConfigTree::saveCurrentConfig()
|
||
{
|
||
if (!m_currentItem) return;
|
||
|
||
int type = m_currentItem->data(0, Qt::UserRole).toInt();
|
||
|
||
// 验证指针有效性 - 检查指针是否仍然指向有效的对象
|
||
bool isWorkPosValid = false;
|
||
bool isCameraValid = false;
|
||
bool isPackageValid = false;
|
||
|
||
if (type == TYPE_WORKPOS && m_currentWorkPos) {
|
||
for (const auto& wp : m_configResult->workPositions) {
|
||
if (&wp == m_currentWorkPos) {
|
||
isWorkPosValid = true;
|
||
break;
|
||
}
|
||
}
|
||
if (isWorkPosValid) {
|
||
saveWorkPositionConfig(m_currentWorkPos);
|
||
}
|
||
} else if (type == TYPE_CAMERA && m_currentWorkPos && m_currentCamera) {
|
||
// 验证工位有效性
|
||
for (const auto& wp : m_configResult->workPositions) {
|
||
if (&wp == m_currentWorkPos) {
|
||
isWorkPosValid = true;
|
||
// 再验证相机有效性
|
||
for (const auto& cam : wp.cameras) {
|
||
if (&cam == m_currentCamera) {
|
||
isCameraValid = true;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (isCameraValid) {
|
||
saveCameraConfig(m_currentWorkPos, m_currentCamera);
|
||
}
|
||
} else if (type == TYPE_PACKAGE && m_currentWorkPos && m_currentCamera && m_currentPackage) {
|
||
// 验证工位、相机、包裹有效性
|
||
for (const auto& wp : m_configResult->workPositions) {
|
||
if (&wp == m_currentWorkPos) {
|
||
isWorkPosValid = true;
|
||
for (const auto& cam : wp.cameras) {
|
||
if (&cam == m_currentCamera) {
|
||
isCameraValid = true;
|
||
for (const auto& pkg : cam.packages) {
|
||
if (&pkg == m_currentPackage) {
|
||
isPackageValid = true;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (isPackageValid) {
|
||
savePackageConfig(m_currentWorkPos, m_currentCamera, m_currentPackage);
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::saveWorkPositionConfig(WorkPositionConfig* config)
|
||
{
|
||
config->name = ui->editWpName->text().toStdString();
|
||
}
|
||
|
||
void DialogConfigTree::saveCameraConfig(WorkPositionConfig* wpConfig, CameraConfig* camConfig)
|
||
{
|
||
Q_UNUSED(wpConfig);
|
||
Q_UNUSED(camConfig);
|
||
// 相机级别的配置主要通过按钮(调平、手眼标定)进行,这里不需要保存
|
||
}
|
||
|
||
void DialogConfigTree::savePackageConfig(WorkPositionConfig* wpConfig,
|
||
CameraConfig* camConfig,
|
||
PackageTypeConfig* pkgConfig)
|
||
{
|
||
Q_UNUSED(wpConfig);
|
||
|
||
// 保存包裹名称
|
||
pkgConfig->name = ui->editPkgName->text().toStdString();
|
||
|
||
// 保存包裹尺寸参数
|
||
pkgConfig->bagParam.bagL = ui->spinBagL->value();
|
||
pkgConfig->bagParam.bagW = ui->spinBagW->value();
|
||
pkgConfig->bagParam.bagH = ui->spinBagH->value();
|
||
|
||
// 保存垛尺寸参数
|
||
pkgConfig->pileParam.pileL = ui->spinPileL->value();
|
||
pkgConfig->pileParam.pileW = ui->spinPileW->value();
|
||
pkgConfig->pileParam.pileH = ui->spinPileH->value();
|
||
|
||
// 保存相机参数
|
||
VrCameraParams camParams;
|
||
camParams.cameraIndex = camConfig->cameraIndex;
|
||
camParams.exposure = ui->spinExposure->value();
|
||
camParams.gain = ui->spinGain->value();
|
||
camParams.frameRate = ui->spinFrameRate->value();
|
||
camParams.swingSpeed = ui->spinSwingSpeed->value();
|
||
camParams.swingStartAngle = ui->spinSwingStartAngle->value();
|
||
camParams.swingStopAngle = ui->spinSwingStopAngle->value();
|
||
pkgConfig->SetCameraParam(camParams);
|
||
}
|
||
|
||
void DialogConfigTree::onAddClicked()
|
||
{
|
||
// 使用 m_currentItem 而不是 currentItem(),因为 m_currentItem 是我们跟踪的有效选择
|
||
QTreeWidgetItem* item = m_currentItem;
|
||
|
||
if (!item) {
|
||
// 没有选中项,添加工位
|
||
QInputDialog dialog(this);
|
||
dialog.setInputMode(QInputDialog::TextInput);
|
||
dialog.setWindowTitle("添加工位");
|
||
dialog.setLabelText("工位名称:");
|
||
|
||
// 设置对话框和所有子控件的字体
|
||
QFont font("", 16);
|
||
dialog.setFont(font);
|
||
|
||
// 设置样式表确保字体生效
|
||
dialog.setStyleSheet("QLabel { font-size: 16pt; } "
|
||
"QLineEdit { font-size: 16pt; } "
|
||
"QPushButton { font-size: 16pt; }");
|
||
|
||
if (dialog.exec() == QDialog::Accepted) {
|
||
QString name = dialog.textValue();
|
||
if (!name.isEmpty()) {
|
||
addWorkPosition(name);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
int type = item->data(0, Qt::UserRole).toInt();
|
||
|
||
if (type == TYPE_WORKPOS) {
|
||
// 选中工位,添加相机
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
|
||
// 检查是否有已配置的相机(从ConfigResult的cameraList读取)
|
||
if (!m_configResult || m_configResult->cameraList.empty()) {
|
||
StyledMessageBox::warning(this, "提示",
|
||
"尚未配置相机IP!\n请先在【相机配置】中添加相机IP地址。");
|
||
return;
|
||
}
|
||
|
||
// 构建相机名称列表(从ConfigResult的cameraList中)
|
||
QStringList cameraNames;
|
||
for (const auto& camera : m_configResult->cameraList) {
|
||
// 显示格式:相机名称 (IP地址)
|
||
QString displayName = QString("%1 (%2)")
|
||
.arg(QString::fromStdString(camera.name))
|
||
.arg(QString::fromStdString(camera.ip));
|
||
cameraNames << displayName;
|
||
}
|
||
|
||
// 使用下拉框选择相机
|
||
QInputDialog dialog(this);
|
||
dialog.setWindowTitle("添加相机");
|
||
dialog.setLabelText("请选择相机:");
|
||
dialog.setComboBoxItems(cameraNames);
|
||
dialog.setComboBoxEditable(false);
|
||
|
||
// 设置对话框和所有子控件的字体
|
||
QFont font("", 16);
|
||
dialog.setFont(font);
|
||
|
||
// 设置样式表确保字体生效
|
||
dialog.setStyleSheet("QLabel { font-size: 16pt; } "
|
||
"QComboBox { font-size: 16pt; padding: 5px; } "
|
||
"QPushButton { font-size: 16pt; }");
|
||
|
||
// 查找ComboBox控件并设置其下拉列表的显示属性
|
||
QComboBox* comboBox = dialog.findChild<QComboBox*>();
|
||
if (comboBox) {
|
||
// 设置下拉列表的样式,增加行高和间距
|
||
comboBox->setStyleSheet(
|
||
"QComboBox { font-size: 16pt; padding: 5px; } "
|
||
"QComboBox QAbstractItemView { font-size: 16pt; } "
|
||
"QComboBox QAbstractItemView::item { height: 45px; padding: 10px; }"
|
||
);
|
||
// 设置下拉列表最大可见项数
|
||
comboBox->setMaxVisibleItems(10);
|
||
}
|
||
|
||
if (dialog.exec() == QDialog::Accepted) {
|
||
QString selectedCamera = dialog.textValue();
|
||
if (!selectedCamera.isEmpty()) {
|
||
// 获取用户选择的索引(在cameraNames列表中的位置)
|
||
int selectedIndex = cameraNames.indexOf(selectedCamera);
|
||
if (selectedIndex >= 0) {
|
||
// 从显示格式中提取相机名称
|
||
// 格式: "相机1 (192.168.1.100)"
|
||
int bracketIndex = selectedCamera.indexOf(" (");
|
||
QString cameraName = (bracketIndex > 0) ? selectedCamera.left(bracketIndex).trimmed() : selectedCamera;
|
||
|
||
// 传递相机名称和索引(索引+1就是cameraIndex)
|
||
addCamera(wpId, cameraName, selectedIndex + 1);
|
||
}
|
||
}
|
||
}
|
||
} else if (type == TYPE_CAMERA) {
|
||
// 选中相机,添加包裹
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
QInputDialog dialog(this);
|
||
dialog.setInputMode(QInputDialog::TextInput);
|
||
dialog.setWindowTitle("添加包裹");
|
||
dialog.setLabelText("包裹名称:");
|
||
|
||
// 设置对话框和所有子控件的字体
|
||
QFont font("", 16);
|
||
dialog.setFont(font);
|
||
|
||
// 设置样式表确保字体生效
|
||
dialog.setStyleSheet("QLabel { font-size: 16pt; } "
|
||
"QLineEdit { font-size: 16pt; } "
|
||
"QPushButton { font-size: 16pt; }");
|
||
|
||
if (dialog.exec() == QDialog::Accepted) {
|
||
QString name = dialog.textValue();
|
||
if (!name.isEmpty()) {
|
||
addPackage(wpId, camId, name);
|
||
}
|
||
}
|
||
} else if (type == TYPE_PACKAGE) {
|
||
// 选中包裹,在其父相机下添加包裹
|
||
QTreeWidgetItem* camItem = item->parent();
|
||
if (camItem) {
|
||
QString wpId = camItem->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = camItem->data(0, Qt::UserRole + 2).toString();
|
||
QInputDialog dialog(this);
|
||
dialog.setInputMode(QInputDialog::TextInput);
|
||
dialog.setWindowTitle("添加包裹");
|
||
dialog.setLabelText("包裹名称:");
|
||
|
||
// 设置对话框和所有子控件的字体
|
||
QFont font("", 16);
|
||
dialog.setFont(font);
|
||
|
||
// 设置样式表确保字体生效
|
||
dialog.setStyleSheet("QLabel { font-size: 16pt; } "
|
||
"QLineEdit { font-size: 16pt; } "
|
||
"QPushButton { font-size: 16pt; }");
|
||
|
||
if (dialog.exec() == QDialog::Accepted) {
|
||
QString name = dialog.textValue();
|
||
if (!name.isEmpty()) {
|
||
addPackage(wpId, camId, name);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::addWorkPosition(const QString& name)
|
||
{
|
||
WorkPositionConfig wp;
|
||
wp.id = "wp_" + std::to_string(m_configResult->workPositions.size() + 1);
|
||
wp.name = name.toStdString();
|
||
m_configResult->workPositions.push_back(wp);
|
||
|
||
initTree();
|
||
}
|
||
|
||
void DialogConfigTree::addCamera(const QString& wpId, const QString& name, int cameraIndex)
|
||
{
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
// 检查该工位下是否已存在同名相机
|
||
std::string cameraName = name.toStdString();
|
||
for (const auto& existingCam : wp.cameras) {
|
||
if (existingCam.cameraName == cameraName) {
|
||
StyledMessageBox::warning(this, "提示",
|
||
QString("该工位下已存在相机【%1】,不能重复添加!").arg(name));
|
||
return;
|
||
}
|
||
}
|
||
|
||
CameraConfig cam;
|
||
cam.id = "cam_" + std::to_string(wp.cameras.size() + 1);
|
||
cam.cameraName = cameraName;
|
||
cam.cameraIndex = cameraIndex; // 直接使用传入的cameraIndex(选择的下标+1)
|
||
|
||
// 初始化调平参数
|
||
cam.planeCalibParam.cameraIndex = cam.cameraIndex;
|
||
cam.planeCalibParam.cameraName = cam.cameraName;
|
||
cam.planeCalibParam.isCalibrated = false;
|
||
cam.planeCalibParam.planeHeight = 0.0;
|
||
// 初始化为单位矩阵
|
||
for (int i = 0; i < 9; i++) {
|
||
cam.planeCalibParam.planeCalib[i] = (i % 4 == 0) ? 1.0 : 0.0;
|
||
cam.planeCalibParam.invRMatrix[i] = (i % 4 == 0) ? 1.0 : 0.0;
|
||
}
|
||
|
||
// 初始化手眼标定参数
|
||
cam.handEyeCalibParam.cameraIndex = cam.cameraIndex;
|
||
cam.handEyeCalibParam.cameraName = cam.cameraName;
|
||
cam.handEyeCalibParam.isCalibrated = false;
|
||
// 初始化为单位矩阵
|
||
for (int i = 0; i < 16; i++) {
|
||
cam.handEyeCalibParam.transformMatrix[i] = (i % 5 == 0) ? 1.0 : 0.0;
|
||
}
|
||
|
||
wp.cameras.push_back(cam);
|
||
|
||
initTree();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::addPackage(const QString& wpId, const QString& camId, const QString& name)
|
||
{
|
||
// 计算全局包裹ID(遍历所有工位、所有相机下的所有包裹)
|
||
int maxPkgId = 0;
|
||
for (const auto& wp : m_configResult->workPositions) {
|
||
for (const auto& cam : wp.cameras) {
|
||
for (const auto& pkg : cam.packages) {
|
||
// 从包裹ID中提取数字部分(格式:pkg_1, pkg_2, ...)
|
||
std::string pkgIdStr = pkg.id;
|
||
if (pkgIdStr.find("pkg_") == 0) {
|
||
int pkgNum = std::stoi(pkgIdStr.substr(4));
|
||
if (pkgNum > maxPkgId) {
|
||
maxPkgId = pkgNum;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
CameraConfig* cam = wp.GetCamera(camId.toStdString());
|
||
if (cam) {
|
||
PackageTypeConfig pkg;
|
||
// 使用全局唯一的包裹ID
|
||
pkg.id = "pkg_" + std::to_string(maxPkgId + 1);
|
||
pkg.name = name.toStdString();
|
||
|
||
// 使用ConfigResult中的默认值初始化包裹参数
|
||
pkg.bagParam = m_configResult->algorithmParams.bagParam;
|
||
pkg.pileParam = m_configResult->algorithmParams.pileParam;
|
||
|
||
// 使用VrCameraParams结构的默认值初始化相机参数
|
||
VrCameraParams camParams;
|
||
camParams.cameraIndex = cam->cameraIndex;
|
||
// 其他参数已通过结构的默认值初始化
|
||
pkg.cameraParams.push_back(camParams);
|
||
|
||
cam->packages.push_back(pkg);
|
||
|
||
initTree();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::onDeleteClicked()
|
||
{
|
||
QTreeWidgetItem* item = ui->treeWidget->currentItem();
|
||
if (!item) return;
|
||
|
||
int type = item->data(0, Qt::UserRole).toInt();
|
||
|
||
if (type == TYPE_WORKPOS) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
auto& wps = m_configResult->workPositions;
|
||
wps.erase(std::remove_if(wps.begin(), wps.end(),
|
||
[&wpId](const WorkPositionConfig& wp) { return wp.id == wpId.toStdString(); }), wps.end());
|
||
initTree();
|
||
} else if (type == TYPE_CAMERA) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
auto& cams = wp.cameras;
|
||
cams.erase(std::remove_if(cams.begin(), cams.end(),
|
||
[&camId](const CameraConfig& cam) { return cam.id == camId.toStdString(); }), cams.end());
|
||
initTree();
|
||
break;
|
||
}
|
||
}
|
||
} else if (type == TYPE_PACKAGE) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
QString pkgId = item->data(0, Qt::UserRole + 3).toString();
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
if (wp.id == wpId.toStdString()) {
|
||
CameraConfig* cam = wp.GetCamera(camId.toStdString());
|
||
if (cam) {
|
||
auto& pkgs = cam->packages;
|
||
pkgs.erase(std::remove_if(pkgs.begin(), pkgs.end(),
|
||
[&pkgId](const PackageTypeConfig& pkg) { return pkg.id == pkgId.toStdString(); }), pkgs.end());
|
||
initTree();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::onSetDefaultClicked()
|
||
{
|
||
QTreeWidgetItem* item = ui->treeWidget->currentItem();
|
||
if (!item) return;
|
||
|
||
int type = item->data(0, Qt::UserRole).toInt();
|
||
|
||
if (type == TYPE_WORKPOS) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
m_configResult->defaultWorkPositionId = wpId.toStdString();
|
||
initTree();
|
||
saveConfigToFile();
|
||
StyledMessageBox::information(this, "成功", "默认工位已设置");
|
||
} else if (type == TYPE_CAMERA) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
m_configResult->defaultWorkPositionId = wpId.toStdString();
|
||
m_configResult->defaultCameraId = camId.toStdString();
|
||
initTree();
|
||
saveConfigToFile();
|
||
StyledMessageBox::information(this, "成功", "默认工位和相机已设置");
|
||
} else if (type == TYPE_PACKAGE) {
|
||
QString wpId = item->data(0, Qt::UserRole + 1).toString();
|
||
QString camId = item->data(0, Qt::UserRole + 2).toString();
|
||
QString pkgId = item->data(0, Qt::UserRole + 3).toString();
|
||
m_configResult->defaultWorkPositionId = wpId.toStdString();
|
||
m_configResult->defaultCameraId = camId.toStdString();
|
||
m_configResult->defaultPackageId = pkgId.toStdString();
|
||
initTree();
|
||
saveConfigToFile();
|
||
StyledMessageBox::information(this, "成功", "默认工位、相机和包裹已设置");
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::onSaveClicked()
|
||
{
|
||
saveCurrentConfig();
|
||
accept();
|
||
}
|
||
|
||
void DialogConfigTree::onCancelClicked()
|
||
{
|
||
reject();
|
||
}
|
||
|
||
void DialogConfigTree::onHandEyeCalibSaveClicked()
|
||
{
|
||
if (!m_currentCamera) {
|
||
StyledMessageBox::warning(this, "错误", "请先选择相机");
|
||
return;
|
||
}
|
||
|
||
// 从UI读取矩阵
|
||
double matrix[16];
|
||
matrix[0] = ui->edit_he_m00->text().toDouble();
|
||
matrix[1] = ui->edit_he_m01->text().toDouble();
|
||
matrix[2] = ui->edit_he_m02->text().toDouble();
|
||
matrix[3] = ui->edit_he_m03->text().toDouble();
|
||
|
||
matrix[4] = ui->edit_he_m10->text().toDouble();
|
||
matrix[5] = ui->edit_he_m11->text().toDouble();
|
||
matrix[6] = ui->edit_he_m12->text().toDouble();
|
||
matrix[7] = ui->edit_he_m13->text().toDouble();
|
||
|
||
matrix[8] = ui->edit_he_m20->text().toDouble();
|
||
matrix[9] = ui->edit_he_m21->text().toDouble();
|
||
matrix[10] = ui->edit_he_m22->text().toDouble();
|
||
matrix[11] = ui->edit_he_m23->text().toDouble();
|
||
|
||
matrix[12] = ui->edit_he_m30->text().toDouble();
|
||
matrix[13] = ui->edit_he_m31->text().toDouble();
|
||
matrix[14] = ui->edit_he_m32->text().toDouble();
|
||
matrix[15] = ui->edit_he_m33->text().toDouble();
|
||
|
||
// 保存到相机配置
|
||
for (int i = 0; i < 16; i++) {
|
||
m_currentCamera->handEyeCalibParam.transformMatrix[i] = matrix[i];
|
||
}
|
||
m_currentCamera->handEyeCalibParam.isCalibrated = true;
|
||
m_currentCamera->handEyeCalibParam.cameraIndex = m_currentCamera->cameraIndex;
|
||
m_currentCamera->handEyeCalibParam.cameraName = m_currentCamera->cameraName;
|
||
|
||
StyledMessageBox::information(this, "成功", "手眼标定矩阵已保存");
|
||
}
|
||
|
||
void DialogConfigTree::onHandEyeCalibLoadClicked()
|
||
{
|
||
if (!m_currentCamera) {
|
||
StyledMessageBox::warning(this, "错误", "请先选择相机");
|
||
return;
|
||
}
|
||
|
||
QString fileName = QFileDialog::getOpenFileName(this,
|
||
"选择手眼标定矩阵文件",
|
||
"./config",
|
||
"INI Files (*.ini);;All Files (*)");
|
||
|
||
if (fileName.isEmpty()) {
|
||
return;
|
||
}
|
||
|
||
// 使用 HandEyeCalibMatrixLoader 加载矩阵
|
||
std::string filePath = fileName.toStdString();
|
||
HandEyeCalibMatrixInfo matrixInfo;
|
||
|
||
if (HandEyeCalibMatrixLoader::LoadMatrixByIndex(filePath, 0, matrixInfo)) {
|
||
// 显示加载的矩阵
|
||
ui->edit_he_m00->setText(QString::number(matrixInfo.calibMatrix[0], 'f', 6));
|
||
ui->edit_he_m01->setText(QString::number(matrixInfo.calibMatrix[1], 'f', 6));
|
||
ui->edit_he_m02->setText(QString::number(matrixInfo.calibMatrix[2], 'f', 6));
|
||
ui->edit_he_m03->setText(QString::number(matrixInfo.calibMatrix[3], 'f', 6));
|
||
|
||
ui->edit_he_m10->setText(QString::number(matrixInfo.calibMatrix[4], 'f', 6));
|
||
ui->edit_he_m11->setText(QString::number(matrixInfo.calibMatrix[5], 'f', 6));
|
||
ui->edit_he_m12->setText(QString::number(matrixInfo.calibMatrix[6], 'f', 6));
|
||
ui->edit_he_m13->setText(QString::number(matrixInfo.calibMatrix[7], 'f', 6));
|
||
|
||
ui->edit_he_m20->setText(QString::number(matrixInfo.calibMatrix[8], 'f', 6));
|
||
ui->edit_he_m21->setText(QString::number(matrixInfo.calibMatrix[9], 'f', 6));
|
||
ui->edit_he_m22->setText(QString::number(matrixInfo.calibMatrix[10], 'f', 6));
|
||
ui->edit_he_m23->setText(QString::number(matrixInfo.calibMatrix[11], 'f', 6));
|
||
|
||
ui->edit_he_m30->setText(QString::number(matrixInfo.calibMatrix[12], 'f', 6));
|
||
ui->edit_he_m31->setText(QString::number(matrixInfo.calibMatrix[13], 'f', 6));
|
||
ui->edit_he_m32->setText(QString::number(matrixInfo.calibMatrix[14], 'f', 6));
|
||
ui->edit_he_m33->setText(QString::number(matrixInfo.calibMatrix[15], 'f', 6));
|
||
|
||
StyledMessageBox::information(this, "成功", "矩阵加载成功!");
|
||
} else {
|
||
// 如果按索引加载失败,尝试加载所有矩阵并使用第一个
|
||
std::vector<HandEyeCalibMatrixInfo> matrices;
|
||
if (HandEyeCalibMatrixLoader::LoadFromIniFile(filePath, matrices) && !matrices.empty()) {
|
||
// 显示第一个矩阵
|
||
const double* matrix = matrices[0].calibMatrix;
|
||
ui->edit_he_m00->setText(QString::number(matrix[0], 'f', 6));
|
||
ui->edit_he_m01->setText(QString::number(matrix[1], 'f', 6));
|
||
ui->edit_he_m02->setText(QString::number(matrix[2], 'f', 6));
|
||
ui->edit_he_m03->setText(QString::number(matrix[3], 'f', 6));
|
||
|
||
ui->edit_he_m10->setText(QString::number(matrix[4], 'f', 6));
|
||
ui->edit_he_m11->setText(QString::number(matrix[5], 'f', 6));
|
||
ui->edit_he_m12->setText(QString::number(matrix[6], 'f', 6));
|
||
ui->edit_he_m13->setText(QString::number(matrix[7], 'f', 6));
|
||
|
||
ui->edit_he_m20->setText(QString::number(matrix[8], 'f', 6));
|
||
ui->edit_he_m21->setText(QString::number(matrix[9], 'f', 6));
|
||
ui->edit_he_m22->setText(QString::number(matrix[10], 'f', 6));
|
||
ui->edit_he_m23->setText(QString::number(matrix[11], 'f', 6));
|
||
|
||
ui->edit_he_m30->setText(QString::number(matrix[12], 'f', 6));
|
||
ui->edit_he_m31->setText(QString::number(matrix[13], 'f', 6));
|
||
ui->edit_he_m32->setText(QString::number(matrix[14], 'f', 6));
|
||
ui->edit_he_m33->setText(QString::number(matrix[15], 'f', 6));
|
||
|
||
StyledMessageBox::information(this, "成功",
|
||
QString("矩阵加载成功!共加载 %1 个标定矩阵,使用第一个。").arg(matrices.size()));
|
||
} else {
|
||
StyledMessageBox::warning(this, "错误", "矩阵加载失败,请检查文件格式!");
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::onCameraLevelClicked()
|
||
{
|
||
if (!m_currentCamera) {
|
||
StyledMessageBox::warning(this, "错误", "请先选择相机节点");
|
||
return;
|
||
}
|
||
|
||
if (!m_presenter) {
|
||
StyledMessageBox::warning(this, "错误", "Presenter未初始化");
|
||
return;
|
||
}
|
||
|
||
// 在对话框中执行调平(模态对话框)
|
||
DialogCameraLevel dlg(this);
|
||
dlg.setCameraList(m_deviceList, m_presenter);
|
||
dlg.setConfig(m_presenter->GetConfig(), m_configResult);
|
||
|
||
// 将对话框显示在父窗口(DialogConfigTree)的中间
|
||
QRect parentGeometry = this->geometry();
|
||
int x = parentGeometry.left() + (parentGeometry.width() - dlg.width()) / 2;
|
||
int y = parentGeometry.top() + (parentGeometry.height() - dlg.height()) / 2;
|
||
dlg.move(x, y);
|
||
|
||
dlg.exec();
|
||
|
||
// 对话框关闭后,重新加载配置文件
|
||
IVrConfig* vrConfig = m_presenter->GetConfig();
|
||
if (vrConfig) {
|
||
ConfigResult newConfig = vrConfig->LoadConfig(PathManager::GetInstance().GetConfigFilePath().toStdString());
|
||
*m_configResult = newConfig;
|
||
}
|
||
|
||
// 遍历所有工位的所有相机,刷新配置显示
|
||
for (auto& wp : m_configResult->workPositions) {
|
||
for (auto& cam : wp.cameras) {
|
||
showCameraConfig(&wp, &cam);
|
||
}
|
||
}
|
||
}
|
||
|
||
void DialogConfigTree::displayHandEyeCalibInline()
|
||
{
|
||
if (!m_currentCamera) {
|
||
return;
|
||
}
|
||
|
||
// 更新标定状态
|
||
if (m_currentCamera->handEyeCalibParam.isCalibrated) {
|
||
ui->labelHandEyeStatus->setText("标定状态: 已标定");
|
||
} else {
|
||
ui->labelHandEyeStatus->setText("标定状态: 未标定");
|
||
}
|
||
|
||
// 显示矩阵
|
||
const double* matrix = m_currentCamera->handEyeCalibParam.transformMatrix;
|
||
ui->edit_he_m00->setText(QString::number(matrix[0], 'f', 6));
|
||
ui->edit_he_m01->setText(QString::number(matrix[1], 'f', 6));
|
||
ui->edit_he_m02->setText(QString::number(matrix[2], 'f', 6));
|
||
ui->edit_he_m03->setText(QString::number(matrix[3], 'f', 6));
|
||
|
||
ui->edit_he_m10->setText(QString::number(matrix[4], 'f', 6));
|
||
ui->edit_he_m11->setText(QString::number(matrix[5], 'f', 6));
|
||
ui->edit_he_m12->setText(QString::number(matrix[6], 'f', 6));
|
||
ui->edit_he_m13->setText(QString::number(matrix[7], 'f', 6));
|
||
|
||
ui->edit_he_m20->setText(QString::number(matrix[8], 'f', 6));
|
||
ui->edit_he_m21->setText(QString::number(matrix[9], 'f', 6));
|
||
ui->edit_he_m22->setText(QString::number(matrix[10], 'f', 6));
|
||
ui->edit_he_m23->setText(QString::number(matrix[11], 'f', 6));
|
||
|
||
ui->edit_he_m30->setText(QString::number(matrix[12], 'f', 6));
|
||
ui->edit_he_m31->setText(QString::number(matrix[13], 'f', 6));
|
||
ui->edit_he_m32->setText(QString::number(matrix[14], 'f', 6));
|
||
ui->edit_he_m33->setText(QString::number(matrix[15], 'f', 6));
|
||
|
||
// 内容已直接显示在相机页面上,无需切换页面
|
||
}
|
||
|
||
void DialogConfigTree::onUpdateWpNameClicked()
|
||
{
|
||
if (!m_currentWorkPos) {
|
||
StyledMessageBox::warning(this, "错误", "请先选择工位");
|
||
return;
|
||
}
|
||
|
||
// 保存工位名称
|
||
saveWorkPositionConfig(m_currentWorkPos);
|
||
initTree();
|
||
|
||
// 重新选中当前工位
|
||
m_currentItem = nullptr;
|
||
updateConfigPanel(nullptr);
|
||
|
||
StyledMessageBox::information(this, "成功", "工位名称已更新");
|
||
}
|
||
|
||
void DialogConfigTree::onSavePkgParamClicked()
|
||
{
|
||
if (!m_currentWorkPos || !m_currentCamera || !m_currentPackage) {
|
||
StyledMessageBox::warning(this, "错误", "请先选择包裹");
|
||
return;
|
||
}
|
||
|
||
// 保存包裹配置
|
||
savePackageConfig(m_currentWorkPos, m_currentCamera, m_currentPackage);
|
||
initTree();
|
||
|
||
// 重新选中当前包裹
|
||
m_currentItem = nullptr;
|
||
updateConfigPanel(nullptr);
|
||
|
||
StyledMessageBox::information(this, "成功", "包裹参数已保存");
|
||
}
|
||
|
||
void DialogConfigTree::saveConfigToFile()
|
||
{
|
||
if (!m_presenter || !m_configResult) {
|
||
return;
|
||
}
|
||
|
||
// 获取配置接口并保存到文件
|
||
IVrConfig* vrConfig = m_presenter->GetConfig();
|
||
if (vrConfig) {
|
||
vrConfig->SaveConfig(PathManager::GetInstance().GetConfigFilePath().toStdString(), *m_configResult);
|
||
}
|
||
}
|
||
|