diff --git a/include/interface.h b/include/interface.h index cd614da..de56579 100644 --- a/include/interface.h +++ b/include/interface.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -78,7 +78,7 @@ public slots: virtual void triggerAndCaptureImage(std::string cameraName, std::vector* mats) = 0; virtual void getCameraNames(std::vector* cameraNames) = 0; virtual void getAllParams(std::vector>* params) = 0; - virtual void editParam(QString name, QVariant value) = 0; + virtual void editParam(QString group, QString name, QVariant value) = 0; }; extern "C" { diff --git a/src/core/backendInterface.h b/src/core/backendInterface.h index 60544a1..0960e74 100644 --- a/src/core/backendInterface.h +++ b/src/core/backendInterface.h @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -63,8 +63,8 @@ public: return backendJson; } public slots: - void editParam(QString name, QVariant value) { - _paramSyncManager->edit(name, value); + void editParam(QString group, QString name, QVariant value) { + _paramSyncManager->edit(group, name, value); qDebug() << name << "更改为" << value; } void getAllParams(std::vector>* params) { diff --git a/src/core/service/imgSaveThreadManager.h b/src/core/service/imgSaveThreadManager.h index bfb5318..d26cdeb 100644 --- a/src/core/service/imgSaveThreadManager.h +++ b/src/core/service/imgSaveThreadManager.h @@ -254,19 +254,19 @@ public: imgSaveThreadManager(std::string pathIn, paramSyncManager* paramSyncManagerIn) { _ImageSavePathFormatter.rootDir = QString::fromStdString(pathIn); _paramSyncManager = paramSyncManagerIn; - saveOri = _paramSyncManager->get("存储原图", true).toBool(); - saveRes = _paramSyncManager->get("存储结果图", true).toBool(); - saveSeg = _paramSyncManager->get("存储Seg图", true).toBool(); - saveCls = _paramSyncManager->get("存储Cls图", true).toBool(); + saveOri = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储原图", true).toBool(); + saveRes = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储结果图", true).toBool(); + saveSeg = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Seg图", true).toBool(); + saveCls = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Cls图", true).toBool(); } ~imgSaveThreadManager() {}; imgSaveThread saveThread; void saveImage(std::shared_ptr data) { if (getParamTimer.elapsed() > 5000) { - saveOri = _paramSyncManager->get("存储原图", true).toBool(); - saveRes = _paramSyncManager->get("存储结果图", true).toBool(); - saveSeg = _paramSyncManager->get("存储Seg图", true).toBool(); - saveCls = _paramSyncManager->get("存储Cls图", true).toBool(); + saveOri = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储原图", true).toBool(); + saveRes = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储结果图", true).toBool(); + saveSeg = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Seg图", true).toBool(); + saveCls = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Cls图", true).toBool(); getParamTimer.restart(); } diff --git a/src/core/service/paramSyncManager.h b/src/core/service/paramSyncManager.h index bad3cea..9ba2fd8 100644 --- a/src/core/service/paramSyncManager.h +++ b/src/core/service/paramSyncManager.h @@ -14,48 +14,55 @@ class paramSyncManager :public QObject{ Q_OBJECT public: + std::vector missionKey; // 构造函数:从JSON数据初始化参数 explicit paramSyncManager(bSignalHub* _signalHub,const nlohmann::ordered_json& json = nlohmann::ordered_json::object() ):_signalHub(_signalHub){ loadFromJson(json); } - // 获取参数值,如果不存在则返回默认值 - QVariant get(QString name, QVariant defaultValue) { + //获取参数值,如果不存在则返回默认值 + QVariant get(QString group, QString name, QVariant defaultValue) { + QString fullKey; { QMutexLocker locker(&globalMutex); - if (map.contains(name)) { - return map[name]; + //构建键名(group.name) + fullKey = group + "." + name; + + if (map.contains(fullKey)) { + return map[fullKey]; } - map.insert(name, defaultValue); + map.insert(fullKey, defaultValue); } - - emit _signalHub->saveMissionJson(); + + emit _signalHub->saveMissionJson(); return defaultValue; } - // 编辑/设置参数值 - void edit(const QString& name, const QVariant& target) { - - if (map.contains(name)) { - map[name] = target; - } - else { - // 如果参数不存在,创建新的参数项 - map.insert(name, target); + //编辑/设置分组参数值 + void edit(const QString& group, const QString& name, const QVariant& target) { + QString fullKey = group + "." + name; + { + QMutexLocker locker(&globalMutex); + if (map.contains(fullKey)) { + map[fullKey] = target; + } + else { + map.insert(fullKey, target); + } } emit _signalHub->saveMissionJson(); } - // 检查参数是否存在 - bool contains(const QString& name) const { + //检查参数是否存在 + bool contains(const QString& fullKey) const { QMutexLocker locker(&globalMutex); - return map.contains(name); + return map.contains(fullKey); } - // 移除参数 - bool remove(const QString& name) { + //移除参数 + bool remove(const QString& fullKey) { QMutexLocker locker(&globalMutex); - return map.remove(name) > 0; + return map.remove(fullKey) > 0; } // 获取所有参数名 @@ -69,35 +76,71 @@ public: QMutexLocker locker(&globalMutex); std::vector> result; updateJsonFromMap(); - for (auto it = json.begin(); it != json.end(); ++it) { - QString key = QString::fromStdString(it.key()); - QVariant value = jsonToQVariant(it.value()); - result.emplace_back(key, value); - } + for (auto it = map.begin(); it != map.end(); ++it) { + result.emplace_back(it.key(), it.value()); + } return result; } + + // 获取指定分组的所有参数 + std::vector> getGroupParams(const QString& group) { + QMutexLocker locker(&globalMutex); + std::vector> result; + QString prefix = group + "."; + + for (auto it = map.begin(); it != map.end(); ++it) { + if (it.key().startsWith(prefix)) { + QString paramName = it.key().mid(prefix.length()); + result.emplace_back(paramName, it.value()); + } + } + + return result; + } + + // 获取分组列表 + std::vector getGroups() const { + QMutexLocker locker(&globalMutex); + return missionKey; + } + + // 获取指定索引的分组名 + QString getGroup(int index) const { + QMutexLocker locker(&globalMutex); + if (index >= 0 && index < missionKey.size()) { + return missionKey[index]; + } + return QString(); + } // 从JSON加载数据 void loadFromJson(const nlohmann::ordered_json& jsonInput){ QMutexLocker locker(&globalMutex); json = jsonInput; map.clear(); + missionKey.clear(); if (!jsonInput.is_object()) { qDebug() << "Invalid JSON format for paramSyncManager"; return; } - - for (auto it = jsonInput.begin(); it != jsonInput.end(); ++it) { - QString key = QString::fromStdString(it.key()); - QVariant value = jsonToQVariant(it.value()); - - map.insert(key, value); + + for (auto missionIt = jsonInput.begin(); missionIt != jsonInput.end(); ++missionIt) { + QString groupName = QString::fromStdString(missionIt.key()); + missionKey.push_back(groupName); + + const auto& innerObject = *missionIt; + for (auto innerIt = innerObject.begin(); innerIt != innerObject.end(); ++innerIt) { + QString key = groupName + "." + QString::fromStdString(innerIt.key()); + QVariant value = jsonToQVariant(innerIt.value()); + map.insert(key, value); + } } } // 将当前 map 值合并回初始 json 并导出 // 规则:map 中的键覆盖 json 中的同名键;json 中原有但未出现在 map 中的键保留 + // 将当前 map 值合并回 json 并导出 nlohmann::ordered_json toJson() { QMutexLocker locker(&globalMutex); updateJsonFromMap(); @@ -105,17 +148,39 @@ public: } void updateJsonFromMap() { + //遍历 map,重新构建嵌套的 JSON 结构 for (auto it = map.begin(); it != map.end(); ++it) { - if (json.find(it.key().toStdString()) != json.end()) - json[it.key().toStdString()] = qVariantToJson(it.value()); - else - json.emplace(it.key().toStdString(), qVariantToJson(it.value())); + QString key = it.key(); + + //解析键名,判断是否包含分组 + QStringList parts = key.split('.'); + if (parts.size() == 2) { + QString group = parts[0]; + QString paramName = parts.mid(1).join('.'); + + //确保组存在 + if (json.find(group.toStdString()) == json.end()) { + json[group.toStdString()] = nlohmann::ordered_json::object(); + } + //添加参数到组 + json[group.toStdString()][paramName.toStdString()] = qVariantToJson(it.value()); + } + else { + json[key.toStdString()] = qVariantToJson(it.value()); + } + } + missionKey.clear(); + for (auto it = json.begin(); it != json.end(); ++it) { + missionKey.push_back(QString::fromStdString(it.key())); } } + // 清空所有参数 void clear() { QMutexLocker locker(&globalMutex); map.clear(); + json = nlohmann::ordered_json::object(); + missionKey.clear(); } private: diff --git a/src/launcher/GUI/paramEditorDialog.h b/src/launcher/GUI/paramEditorDialog.h index 9e45640..00df9c9 100644 --- a/src/launcher/GUI/paramEditorDialog.h +++ b/src/launcher/GUI/paramEditorDialog.h @@ -23,23 +23,241 @@ #include #include #include +#include +#include +#include class paramTableEditor : public QDialog { Q_OBJECT - public: explicit paramTableEditor(QWidget* parent = nullptr) : QDialog(parent) { - this->setWindowTitle(TR("JSON Table Editor")); - this->resize(700, 450); - setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);// 去掉边框 - //setAttribute(Qt::WA_TranslucentBackground); // 背景透明 + this->setWindowTitle("参数编辑器"); + this->resize(900, 500); + setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); this->setObjectName("paramTableEditor"); this->setStyleSheet(QString("QDialog#paramTableEditor {background-color: rgb(%1);border: 2px solid #000000;border-radius: 6px;}").arg(sColor_Blue)); - - m_tableView = new QTableView(this); - m_tableModel = new QStandardItemModel(0, 2, this);// 2列:选项、值 + + //创建主水平布局 + QHBoxLayout* mainLayout = new QHBoxLayout(this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + + //创建侧边栏 + createSidebar(); + + //创建分隔线 + m_dividerLine = new QFrame(this); + m_dividerLine->setFrameShape(QFrame::VLine); + m_dividerLine->setFrameShadow(QFrame::Sunken); + m_dividerLine->setStyleSheet("background-color: #555555;"); + m_dividerLine->setFixedWidth(1); + + //创建内容区域 + createContentArea(); + + //组装布局 + mainLayout->addWidget(m_sidebarWidget); + mainLayout->addWidget(m_dividerLine); + mainLayout->addWidget(m_contentWidget, 1); //内容区域占据剩余空间 + } + + void setParams(std::vector> params) { + //保存所有参数 + m_allParams = params; + + //清空现有数据 + m_tableModel->setRowCount(0); + m_editorWidgets.clear(); + m_sidebarList->clear(); + + if (params.size() == 0) return; + + //提取分组信息 + QSet groups; + QMap>> groupedParams; + + for (auto& data : params) { + const QString& fullKey = data.first; + QString groupName = "默认分组"; + + //解析分组名 + int firstDotIndex = fullKey.indexOf('.'); + if (firstDotIndex != -1) { + groupName = fullKey.left(firstDotIndex); + } + + groups.insert(groupName); + groupedParams[groupName].push_back(data); + } + + //添加分组到侧边栏 + QStringList groupList = groups.values(); + groupList.sort(); + + //添加"所有参数"选项 + m_sidebarList->addItem("所有参数"); + for (const QString& group : groupList) { + m_sidebarList->addItem(group); + } + + //保存分组参数 + m_groupedParams = groupedParams; + m_groupedParams["所有参数"] = params;// 添加所有参数选项 + + //默认显示所有参数 + displayGroupParams("所有参数"); + + if (m_sidebarList->count() > 0) { + m_sidebarList->setCurrentRow(0); + } + } + +private slots: + void onAccept() { + std::vector> result; + + for (int row = 0; row < m_tableModel->rowCount(); ++row) { + QStandardItem* keyItem = m_tableModel->item(row, 0); + if (!keyItem) { + QMessageBox::warning(this, "错误", QString("第 %1 行数据不完整").arg(row + 1)); + return; + } + + QString fullKey = keyItem->data(Qt::UserRole).toString();//获取完整键名 + if (fullKey.isEmpty()) { + QMessageBox::warning(this, "错误", QString("第 %1 行 key 为空").arg(row + 1)); + return; + } + + //解析分组组名和参数名 + QString group, name; + int dotIndex = fullKey.indexOf('.'); + if (dotIndex != -1) { + group = fullKey.left(dotIndex); + name = fullKey.mid(dotIndex + 1); + } + else { + group = "默认分组"; + name = fullKey; + } + + // 获取原始类型 + if (m_originalTypes.find(fullKey) == m_originalTypes.end()) { + QMessageBox::warning(this, "错误", QString("第 %1 行找不到原始类型信息").arg(row + 1)); + return; + } + + auto expectedType = m_originalTypes[fullKey]; + + // 从编辑器获取值 + QVariant convertedValue; + QString errorMsg; + if (!getValueFromEditor(fullKey, expectedType, convertedValue, errorMsg)) { + QMessageBox::critical(this, "类型验证失败", QString("第 %1 行值验证失败:\n%2").arg(row + 1).arg(errorMsg)); + return; + } + + // 发送参数编辑信号 + emit fSignalHub::getInstance()->editParam(group, name, convertedValue); + } + this->close(); + delete this; + } + + void onSidebarItemClicked(QListWidgetItem* item) { + if (!item) return; + + QString groupName = item->text(); + displayGroupParams(groupName); + } + +private: + QTableView* m_tableView; + QStandardItemModel* m_tableModel; + nlohmann::json m_originalJson; + std::map m_originalTypes; + std::map m_editorWidgets; + + //左侧边栏相关成员 + QWidget* m_sidebarWidget; + QWidget* m_contentWidget; + QListWidget* m_sidebarList; + QFrame* m_dividerLine; + + // 参数数据 + std::vector> m_allParams; + QMap>> m_groupedParams; + + void createSidebar() { + m_sidebarWidget = new QWidget(this); + m_sidebarWidget->setObjectName("sidebar"); + m_sidebarWidget->setFixedWidth(180); + m_sidebarWidget->setStyleSheet(QString(R"( + QWidget#sidebar { + background-color: rgb(%1); + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; + } + )").arg(sColor_BlueWithBlack)); + + QVBoxLayout* sidebarLayout = new QVBoxLayout(m_sidebarWidget); + sidebarLayout->setContentsMargins(8, 8, 8, 8); + sidebarLayout->setSpacing(10); + + //左侧边栏标题 + QLabel* sidebarTitle = new QLabel("参数分组"); + sidebarTitle->setStyleSheet("color: white; font-weight: bold; font-size: 14px; padding: 5px;"); + sidebarTitle->setAlignment(Qt::AlignCenter); + + //侧边栏列表样式 + m_sidebarList = new QListWidget(); + m_sidebarList->setStyleSheet(R"( + QListWidget { + background-color: #3a3a3a; + border: 1px solid #555555; + border-radius: 3px; + color: white; + outline: none; + font-size: 12px; + } + QListWidget::item { + padding: 8px; + border-bottom: 1px solid #555555; + border-radius: 2px; + margin: 2px; + } + QListWidget::item:selected { + background-color: #0078d4; + color: white; + border: 1px solid #005a9e; + } + QListWidget::item:hover { + background-color: #555555; + } + )"); + connect(m_sidebarList, &QListWidget::itemClicked, this, ¶mTableEditor::onSidebarItemClicked); + + sidebarLayout->addWidget(sidebarTitle); + sidebarLayout->addWidget(m_sidebarList); + } + + void createContentArea() { + m_contentWidget = new QWidget(this); + m_contentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + QVBoxLayout* contentLayout = new QVBoxLayout(m_contentWidget); + contentLayout->setContentsMargins(10, 10, 10, 10); + contentLayout->setSpacing(10); + + // 当前分组标签 + m_currentGroupLabel = new QLabel("所有参数"); + m_currentGroupLabel->setStyleSheet("color: white; font-weight: bold; font-size: 16px; padding: 5px;"); + contentLayout->addWidget(m_currentGroupLabel); + + m_tableView = new QTableView(); + m_tableModel = new QStandardItemModel(0, 2, this); m_tableView->setModel(m_tableModel); m_tableView->setCornerButtonEnabled(false); @@ -63,21 +281,20 @@ public: m_tableView->setColumnWidth(0, 280); // 禁止第一列选中 - m_tableView->setColumnHidden(0, false); // 显示第一列 + m_tableView->setColumnHidden(0, false); m_tableView->setFocusPolicy(Qt::NoFocus); - //设置表头 - m_tableModel->setHorizontalHeaderLabels({ TR("Option"), TR("Value") }); + // 设置表头 + m_tableModel->setHorizontalHeaderLabels({ "参数名", "值" }); - //设置表格属性 + // 设置表格属性 m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); m_tableView->setAlternatingRowColors(true); m_tableView->horizontalHeader()->setStretchLastSection(true); - m_tableView->setColumnWidth(1, 200);// 选项列宽度 + m_tableView->setColumnWidth(1, 250); - - fancyButtonText* okBtn = new fancyButtonText(TR("Save"), 70, 22, ""); - fancyButtonText* cancelBtn = new fancyButtonText(TR("Cancel"), 70, 22, ""); + fancyButtonText* okBtn = new fancyButtonText("保存", 70, 22, ""); + fancyButtonText* cancelBtn = new fancyButtonText("取消", 70, 22, ""); connect(okBtn, &QPushButton::clicked, this, ¶mTableEditor::onAccept); connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject); @@ -87,10 +304,9 @@ public: btnLayout->addWidget(okBtn); btnLayout->addWidget(cancelBtn); - QVBoxLayout* mainLayout = new QVBoxLayout(this); - mainLayout->addWidget(m_tableView); - mainLayout->addLayout(btnLayout); - + contentLayout->addWidget(m_tableView, 1); // 表格占据大部分空间 + contentLayout->addLayout(btnLayout); + m_tableView->setStyleSheet(QString(R"( QTableView { background-color: rgb(%1); @@ -111,7 +327,7 @@ public: } QTableCornerButton::section { background: transparent; -border: none; + border: none; } )").arg(sColor_Blue)); @@ -135,7 +351,7 @@ border: none; "QHeaderView {" "background-color: rgb(%1);" "}" - ).arg(sColor_Blue));; + ).arg(sColor_Blue)); m_tableView->setCornerButtonEnabled(false); // 强制隐藏交叉方块区域 @@ -143,42 +359,59 @@ border: none; m_tableView->horizontalHeader()->height() - 1); m_tableView->verticalHeader()->setFixedWidth( m_tableView->verticalHeader()->width() - 1); - } - void setParams(std::vector> params) { + void displayGroupParams(const QString& groupName) { + //更新当前分组标签 + m_currentGroupLabel->setText(groupName); + + // 清空表格 m_tableModel->setRowCount(0); m_editorWidgets.clear(); - - if (params.size() == 0) return; + if (!m_groupedParams.contains(groupName)) { + return; + } + + const auto& params = m_groupedParams[groupName]; int row = 0; + for (auto data : params) { m_tableModel->insertRow(row); - const QString& key = data.first; + const QString& fullKey = data.first; const QVariant& value = data.second; + QString displayName = fullKey; + //分组显示,去掉分组前缀 + if (groupName != "所有参数") { + int dotIndex = fullKey.indexOf('.'); + if (dotIndex != -1) { + displayName = fullKey.mid(dotIndex + 1); + } + } // 设置键名(不可编辑) - QStandardItem* keyItem = new QStandardItem(key); + QStandardItem* keyItem = new QStandardItem(displayName); keyItem->setEditable(false); keyItem->setBackground(QColor(60, 60, 60)); keyItem->setForeground(QColor(255, 255, 255)); + keyItem->setData(fullKey, Qt::UserRole);//存储完整键名 + keyItem->setToolTip(fullKey);//提示显示完整键名 m_tableModel->setItem(row, 0, keyItem); - // 确定类型(内部使用,不显示) - m_originalTypes[key] = value.type(); + //确定类型(内部使用,不显示) + m_originalTypes[fullKey] = value.type(); //为特定类型创建专用编辑器控件 QWidget* editorWidget = createEditorWidget(value, value.type()); if (editorWidget) { m_tableView->setIndexWidget(m_tableModel->index(row, 1), editorWidget); - m_editorWidgets[key] = editorWidget; + m_editorWidgets[fullKey] = editorWidget; } else { // 默认为文本显示 - QString valueText= value.toString(); + QString valueText = value.toString(); QStandardItem* valueItem = new QStandardItem(valueText); valueItem->setToolTip(generateTypeHint(value.type())); m_tableModel->setItem(row, 1, valueItem); @@ -187,59 +420,10 @@ border: none; } } -signals: - -private slots: - void onAccept() { - std::vector> result; - - for (int row = 0; row < m_tableModel->rowCount(); ++row) { - QStandardItem* keyItem = m_tableModel->item(row, 0); - if (!keyItem) { - QMessageBox::warning(this, TR("Error"), QString(TR("Row %1 data is incomplete")).arg(row + 1)); - return; - } - - QString key = keyItem->text().trimmed(); - if (key.isEmpty()) { - QMessageBox::warning(this, TR("Error"), QString(TR("Row %1 key is empty")).arg(row + 1)); - return; - } - - //获取原始类型 - if (m_originalTypes.find(key) == m_originalTypes.end()) { - QMessageBox::warning(this, TR("Error"), QString(TR("Original type information not found for row %1")).arg(row + 1)); - return; - } - - auto expectedType = m_originalTypes[key]; - - //从编辑器获取值 - QVariant convertedValue; - QString errorMsg; - if (!getValueFromEditor(key, expectedType, convertedValue, errorMsg)) { - QMessageBox::critical(this, TR("Type Validation Failed"),QString(TR("Row %1 value validation failed:\n%2")).arg(row + 1).arg(errorMsg)); - return; - } - //esult[keyStd] = convertedValue; - //result.push_back({ key, convertedValue }); - emit fSignalHub::getInstance()->editParam(key, convertedValue); - } - this->close(); - delete this; - } - -private: - QTableView* m_tableView; - QStandardItemModel* m_tableModel; - nlohmann::json m_originalJson; // 保存原始JSON以便类型检查 - std::map m_originalTypes;// 保存每个键的原始类型 - std::map m_editorWidgets;// 保存每个键对应的编辑器控件 - // 根据类型创建不同的编辑器控件 QWidget* createEditorWidget(const QVariant& value, QVariant::Type type) { switch (type) { - case QVariant::Type::Bool:{ + case QVariant::Type::Bool: { CircularSwitch* switchBtn = new CircularSwitch(); switchBtn->setChecked(value.toBool()); switchBtn->setToolTip(generateTypeHint(type)); @@ -248,7 +432,7 @@ private: case QVariant::Type::Int: { QSpinBox* spinBox = new QSpinBox(); spinBox->setMaximumWidth(160); - spinBox->setRange(INT_MIN, INT_MAX); + spinBox->setRange(-1e6, 1e6); spinBox->setValue(value.toInt()); spinBox->setToolTip(generateTypeHint(type)); return spinBox; @@ -257,7 +441,6 @@ private: QDoubleSpinBox* spinBox = new QDoubleSpinBox(); spinBox->setMaximumWidth(160); spinBox->setDecimals(3);//显示小位数 - spinBox->setRange(-1e6, 1e6); spinBox->setValue(value.toDouble()); spinBox->setToolTip(generateTypeHint(type)); return spinBox; @@ -268,7 +451,7 @@ private: lineEdit->setToolTip(generateTypeHint(type)); return lineEdit; } - // 其他类型仍使用文本显示 + // 其他类型仍使用文本显示 default: return nullptr; } @@ -291,7 +474,7 @@ private: updateModelData(key, value ? "true" : "false"); return true; } - errorMsg = TR("Boolean control type mismatch"); + errorMsg = "布尔值控件类型错误"; return false; } case QVariant::Type::Int: { @@ -302,7 +485,7 @@ private: updateModelData(key, QString::number(value)); return true; } - errorMsg = TR("Integer number control type mismatch"); + errorMsg = "数字控件INT类型错误"; return false; } case QVariant::Type::Double: { @@ -313,7 +496,7 @@ private: updateModelData(key, QString::number(value)); return true; } - errorMsg = TR("Number control type mismatch"); + errorMsg = "数字控件DOUBLE类型错误"; return false; } case QVariant::Type::String: { @@ -324,21 +507,20 @@ private: updateModelData(key, value); return true; } - errorMsg = TR("String control type mismatch"); + errorMsg = "字符串控件类型错误"; return false; } - //default: - // // 其他类型使用默认文本处理 - // return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg); } } - //else { - // // 没有专用编辑器控件,使用默认文本处理 - // return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg); - //} + else { + //没有专用编辑器控件,从单元格获取文本值 + QString valueText = getTextFromCell(key); + result = valueText; + return true; + } } catch (const std::exception& e) { - errorMsg = QString(TR("Get value error: %1")).arg(e.what()); + errorMsg = QString("获取值错误: %1").arg(e.what()); return false; } return false; @@ -348,7 +530,7 @@ private: void updateModelData(const QString& key, const QString& value) { for (int row = 0; row < m_tableModel->rowCount(); ++row) { QStandardItem* keyItem = m_tableModel->item(row, 0); - if (keyItem && keyItem->text() == key) { + if (keyItem && keyItem->data(Qt::UserRole).toString() == key) { QStandardItem* valueItem = m_tableModel->item(row, 1); if (valueItem) { valueItem->setText(value); @@ -359,11 +541,11 @@ private: } // 从单元格获取文本值(用于没有专用编辑器的类型) - QString getTextFromCell(const std::string& key) { + QString getTextFromCell(const QString& key) { //查找键对应的行 for (int row = 0; row < m_tableModel->rowCount(); ++row) { QStandardItem* keyItem = m_tableModel->item(row, 0); - if (keyItem && keyItem->text().toStdString() == key) { + if (keyItem && keyItem->data(Qt::UserRole).toString() == key) { QStandardItem* valueItem = m_tableModel->item(row, 1); if (valueItem) { return valueItem->text(); @@ -373,23 +555,23 @@ private: } return ""; } - - + // 生成类型提示 QString generateTypeHint(QVariant::Type type) { switch (type) { - case QVariant::Type::String: - return TR("Enter a string value (no quotes required)"); - case QVariant::Type::Int: - return TR("Enter an integer value"); - case QVariant::Type::Double: - return TR("Enter a decimal value"); - case QVariant::Type::Bool: - return TR("Enter a boolean value (true or false)"); - default: - return TR("Please enter a valid JSON value"); + case QVariant::Type::String: + return "输入字符串值(不需要引号)"; + case QVariant::Type::Int: + return "输入数字值(整数)"; + case QVariant::Type::Double: + return "输入数字值(小数)"; + case QVariant::Type::Bool: + return "输入布尔值(true 或 false)"; + default: + return "请输入有效的JSON值"; } } - - -}; + +private: + QLabel* m_currentGroupLabel; //当前分组标签 +}; \ No newline at end of file diff --git a/src/launcher/frontendSignalHub.h b/src/launcher/frontendSignalHub.h index fc2855f..7affa1d 100644 --- a/src/launcher/frontendSignalHub.h +++ b/src/launcher/frontendSignalHub.h @@ -57,7 +57,7 @@ signals: void triggerAndCaptureImage(std::string cameraName, std::vector* mats); void getCameraNames(std::vector* cameraNames); void getAllParams(std::vector>* params); - void editParam(QString name, QVariant value); + void editParam(QString group, QString name, QVariant value); void saveMissionJson(); }; \ No newline at end of file diff --git a/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp index 43980a2..2977872 100644 --- a/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp +++ b/src/mission/581-BaoMo-Cam91011/581-BaoMo-Cam91011.cpp @@ -80,8 +80,8 @@ bool halconAlgo1_BaoMoHouCeMian_HouDu(std::shared_ptr data, yh_581_add int outFlag = out_Flag.D(); TextRendererZH textPainter(Paint.cols, Paint.rows, 300); - double limitHigh = data->service->_paramSyncManager->get("最大宽度阈值(MAX)", 200).toFloat(); - double limitLow = data->service->_paramSyncManager->get("最小宽度阈值(MIN)", 0).toFloat(); + double limitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "最大宽度阈值(MAX)", 200).toFloat(); + double limitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "最小宽度阈值(MIN)", 0).toFloat(); if (outFlag == 1) { QMutexLocker locker(mutex); @@ -120,10 +120,10 @@ bool halconAlgo1_BaoMoHouCeMian_PoSun(std::shared_ptr data, yh_581_add cv::Mat img = HObject2Mat(test); cv::resize(img, img, cv::Size(), 0.5, 0.5); HTuple in_Parameters; - in_Parameters[0] = data->service->_paramSyncManager->get("灰度管控阈值", 230).toInt(); - in_Parameters[1] = data->service->_paramSyncManager->get("缺陷像素数量管控阈值(pix)", 300000).toInt(); - in_Parameters[2] = data->service->_paramSyncManager->get("缺陷的宽度管控阈值(pix)", 600).toInt(); - in_Parameters[3] = data->service->_paramSyncManager->get("缺陷的高度管控阈值(pix)", 60).toInt(); + in_Parameters[0] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "灰度管控阈值", 230).toInt(); + in_Parameters[1] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "缺陷像素数量管控阈值(pix)", 300000).toInt(); + in_Parameters[2] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "缺陷的宽度管控阈值(pix)", 600).toInt(); + in_Parameters[3] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "缺陷的高度管控阈值(pix)", 60).toInt(); HDevEngineCpp::HDevProcedure proc("_4_TR_TL_BlueCover_Inspection"); HDevProcedureCall procedureCall(proc); @@ -173,7 +173,7 @@ bool ALGO_BaoMoHouCeMian(std::shared_ptr data, baoMoHouDaMianDetParams clock_t start, finish; start = clock(); - data->oriImgs[0] = cv::imread("D:/04QCB82602000JFB5000019N_Camera2_0.bmp", -1); + //data->oriImgs[0] = cv::imread("D:/04QCB82602000JFB5000019N_Camera2_0.bmp", -1); // cv::Mat src = data->oriImgs[0]; diff --git a/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h b/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h index 8a56530..79d22d2 100644 --- a/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h +++ b/src/mission/581-Mfd_yh_mh_hh/581-Mfd.h @@ -1,4 +1,4 @@ -#include +#include #include class mfd_detParams { public: @@ -167,7 +167,7 @@ static bool ManHan(std::shared_ptr data, mfd_detParams* _detParams, yh static bool YuHan(std::shared_ptr data, mfd_detParams* _detParams, yh_581_address address){ try { data->service->_missionResultHandle->toBarChart("", true, {"测试"}); - data->service->_paramSyncManager->get("123", 123); + //data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "123", 123); std::map sqlMapData; sqlMapData["项目"] = "预焊"; sqlMapData["相机"] = "相机" + address.triggerAddr; diff --git a/src/mission/952/952_15_Q_2D3D/952_15_Q_2D3D.h b/src/mission/952/952_15_Q_2D3D/952_15_Q_2D3D.h index 0d5ce2c..df223f1 100644 --- a/src/mission/952/952_15_Q_2D3D/952_15_Q_2D3D.h +++ b/src/mission/952/952_15_Q_2D3D/952_15_Q_2D3D.h @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -297,7 +297,7 @@ public: bool initCustom() { #pragma region 注册触发器回调 - if (_serviceManager->_paramSyncManager->get("way", "IN").toString() == "IN") { + /*if (_serviceManager->_paramSyncManager->get(_serviceManager->_paramSyncManager->getGroup(1), "way", "IN").toString() == "IN") { _2dP_address = { 8010 ,1,{8200} ,"8011" ,"-1", - 1}; _2dN_address = { 8020 ,1,{8300} ,"8021" ,"-1", -1 }; _3d_address = { 8030 ,1,{8400} ,"8031" ,"-1", -1 }; @@ -308,7 +308,7 @@ public: _2dN_address = { 8070 ,1,{8800} ,"8071" ,"-1", -1 }; _3d_address = { 8080 ,1,{8900} ,"8081" ,"-1", -1 }; summary_triggerPos = 8090; - } + }*/ _serviceManager->_triggerManager->registerCallback(_2dP_address.triggerAddr, 1, [this](int triggerPos, int triggerValue, QByteArray& byteArray) {Qian_2D_P(byteArray); }, "2D_1拍照触发"); _serviceManager->_triggerManager->registerCallback(_2dN_address.triggerAddr, 1, [this](int triggerPos, int triggerValue, QByteArray& byteArray) {Qian_2D_N(byteArray); }, "2D_2拍照触发"); _serviceManager->_triggerManager->registerCallback(_3d_address.triggerAddr, 1, [this](int triggerPos, int triggerValue, QByteArray& byteArray) {Qian_3D_1(byteArray); }, "3D拍照触发"); diff --git a/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.cpp b/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.cpp index 7c9a9df..574994d 100644 --- a/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.cpp +++ b/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.cpp @@ -177,17 +177,17 @@ bool hanHouCeLiang(std::shared_ptr data, yuHanHanHouParams* _detParams plcResult = "1"; silieResultText = "1"; fanzheResultText = "1"; #pragma region 判断结果以及储存结果 - double hanyinChangLimitHigh = data->service->_paramSyncManager->get("焊印长(上限)", 30.5).toDouble(); - double hanyinChangLimitLow = data->service->_paramSyncManager->get("焊印长(下限)", 29.5).toDouble(); - bool hanyinChangEnable = data->service->_paramSyncManager->get("焊印长判定启用", false).toBool(); + /*double hanyinChangLimitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印长(上限)", 30.5).toDouble(); + double hanyinChangLimitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印长(下限)", 29.5).toDouble(); + bool hanyinChangEnable = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印长判定启用", false).toBool(); - double hanyinKuanLimitHigh = data->service->_paramSyncManager->get("焊印宽(上限)", 10.5).toDouble(); - double hanyinKuanLimitLow = data->service->_paramSyncManager->get("焊印宽(下限)", 9.5).toDouble(); - bool hanyinKuanEnable = data->service->_paramSyncManager->get("焊印宽判定启用", false).toBool(); + double hanyinKuanLimitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印宽(上限)", 10.5).toDouble(); + double hanyinKuanLimitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印宽(下限)", 9.5).toDouble(); + bool hanyinKuanEnable = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印宽判定启用", false).toBool(); - double jierChangLimitHigh = data->service->_paramSyncManager->get("极耳长度(上限)", 10.5).toDouble(); - double jierChangLimitLow = data->service->_paramSyncManager->get("极耳长度(下限)", 9.5).toDouble(); - bool jierChangEnable = data->service->_paramSyncManager->get("极耳长度判定启用", false).toBool(); + double jierChangLimitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "极耳长度(上限)", 10.5).toDouble(); + double jierChangLimitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "极耳长度(下限)", 9.5).toDouble(); + bool jierChangEnable = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "极耳长度判定启用", false).toBool();*/ #pragma endregion data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈 diff --git a/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.h b/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.h index 82d0b42..b6ad81d 100644 --- a/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.h +++ b/src/mission/YuHan/581_YuHan_hanhou/581_YuHan_hanhou.h @@ -1,4 +1,4 @@ -#include +#include #include #pragma region 算法 #include @@ -122,7 +122,7 @@ public: } bool initCustom() { #pragma region 注册触发器回调 - if (_serviceManager->_paramSyncManager->get("hanhou","OUT") == "OUT") { + /*if (_serviceManager->_paramSyncManager->get(_serviceManager->_paramSyncManager->getGroup(1), "hanhou","OUT") == "OUT") { lv_top90_1.init("Camera1", "极耳尺寸-外-铝-相机1(顶部90°)", { { 522, 1,{540},"523","530",820} }, 1, &lv_90_DetParams[0], _serviceManager, bridge, hanHouCeLiang); lv_down90_2.init("Camera2", "极耳尺寸-外-铝-相机2(底部90°)", { { 524, 1,{540},"525","532",-1} }, 1, &lv_90_DetParams[1], _serviceManager, bridge, hanHouDown); tong_top90_3.init("Camera3", "极耳尺寸-外-铜-相机3(顶部90°)", { { 526,1,{540},"527","534",800} }, 1, &tong_90_DetParams[0], _serviceManager, bridge, hanHouCeLiang); @@ -143,7 +143,7 @@ public: lv_down45_6.init("Camera6", "底部撕裂-内-铝-相机6(底部45°)", { { 644, 1,{580},"645","652",-1} }, 1, &dibu_45_lv_DetParams[0], _serviceManager, bridge, hanHouDown); tong_top45_7.init("Camera7", "底部撕裂-内-铜-相机7(顶部45°)", { { 646, 1,{580},"647","654",-1} }, 1, &dingbu_45_tong_DetParams[0], _serviceManager, bridge, hanHouDown); tong_down45_8.init("Camera8", "底部撕裂-内-铜-相机8(底部45°)", { { 648, 1,{580},"649","656",-1} }, 1, &dibu_45_tong_DetParams[0], _serviceManager, bridge, hanHouDown); - } + }*/ #pragma endregion return true; }