feat(ui): ObjectTreePanel GS三态勾选 + objectClicked/checkedTmsChanged 合并发射
This commit is contained in:
parent
595d65cd3b
commit
68296a5d36
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QSignalBlocker>
|
#include <QSignalBlocker>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QTimer>
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "Glyphs.hpp"
|
#include "Glyphs.hpp"
|
||||||
#include "Theme.hpp"
|
#include "Theme.hpp"
|
||||||
|
|
@ -13,17 +16,22 @@
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// TM 节点把 tmObjectId 存在该角色;GS/项目根节点为空。
|
constexpr int kRoleObjId = Qt::UserRole + 2; // 节点对象 id(GS/TM 都存)
|
||||||
constexpr int kRoleTmId = Qt::UserRole + 2;
|
constexpr int kRoleConfType = Qt::UserRole + 3; // 1=GS 2=TM
|
||||||
|
|
||||||
void addNodes(QTreeWidgetItem* parent, const std::vector<data::dto::StructTreeNode>& nodes) {
|
void addNodes(QTreeWidgetItem* parent, const std::vector<data::dto::StructTreeNode>& nodes) {
|
||||||
for (const auto& n : nodes) {
|
for (const auto& n : nodes) {
|
||||||
auto* item = new QTreeWidgetItem(parent);
|
auto* item = new QTreeWidgetItem(parent);
|
||||||
item->setText(0, QString::fromStdString(n.node.name));
|
item->setText(0, QString::fromStdString(n.node.name));
|
||||||
|
item->setData(0, kRoleObjId, QString::fromStdString(n.node.id));
|
||||||
if (n.isTm) {
|
if (n.isTm) {
|
||||||
item->setData(0, kRoleTmId, QString::fromStdString(n.node.id));
|
item->setData(0, kRoleConfType, 2);
|
||||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
item->setCheckState(0, Qt::Unchecked); // 真实数据渲染下一轮接入,默认不勾
|
item->setCheckState(0, Qt::Unchecked);
|
||||||
|
} else {
|
||||||
|
item->setData(0, kRoleConfType, 1); // GS
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate);
|
||||||
|
item->setCheckState(0, Qt::Unchecked);
|
||||||
}
|
}
|
||||||
addNodes(item, n.children);
|
addNodes(item, n.children);
|
||||||
}
|
}
|
||||||
|
|
@ -49,12 +57,28 @@ ObjectTreePanel::ObjectTreePanel(QWidget* parent) : QWidget(parent) {
|
||||||
lay->addWidget(hint_);
|
lay->addWidget(hint_);
|
||||||
|
|
||||||
QObject::connect(tree_, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem* item, int) {
|
QObject::connect(tree_, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem* item, int) {
|
||||||
const QString tmId = item->data(0, kRoleTmId).toString();
|
const QString id = item->data(0, kRoleObjId).toString();
|
||||||
if (!tmId.isEmpty()) emit tmClicked(tmId);
|
const int confType = item->data(0, kRoleConfType).toInt();
|
||||||
|
if (!id.isEmpty() && confType != 0) emit objectClicked(id, confType);
|
||||||
|
});
|
||||||
|
// 勾选变化:GS 级联会触发多次 itemChanged,用 0ms 单发合并成一次「收集勾选叶子并发射」。
|
||||||
|
QObject::connect(tree_, &QTreeWidget::itemChanged, this, [this](QTreeWidgetItem*, int) {
|
||||||
|
if (checkPending_) return;
|
||||||
|
checkPending_ = true;
|
||||||
|
QTimer::singleShot(0, this, [this]() {
|
||||||
|
checkPending_ = false;
|
||||||
|
QStringList tmIds;
|
||||||
|
std::function<void(QTreeWidgetItem*)> walk = [&](QTreeWidgetItem* node) {
|
||||||
|
for (int i = 0; i < node->childCount(); ++i) {
|
||||||
|
QTreeWidgetItem* c = node->child(i);
|
||||||
|
if (c->data(0, kRoleConfType).toInt() == 2 && c->checkState(0) == Qt::Checked)
|
||||||
|
tmIds << c->data(0, kRoleObjId).toString();
|
||||||
|
walk(c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
walk(tree_->invisibleRootItem());
|
||||||
|
emit checkedTmsChanged(tmIds);
|
||||||
});
|
});
|
||||||
QObject::connect(tree_, &QTreeWidget::itemChanged, this, [this](QTreeWidgetItem* item, int) {
|
|
||||||
const QString tmId = item->data(0, kRoleTmId).toString();
|
|
||||||
if (!tmId.isEmpty()) emit tmCheckToggled(tmId, item->checkState(0) == Qt::Checked);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <QStringList>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "repo/RepoTypes.hpp"
|
#include "repo/RepoTypes.hpp"
|
||||||
|
|
@ -19,13 +20,15 @@ public:
|
||||||
void showMessage(const QString& message); // 错误/空状态占位
|
void showMessage(const QString& message); // 错误/空状态占位
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void tmClicked(const QString& tmObjectId);
|
// confType: 1=GS 2=TM。单击行(驱动数据列表 + 对象属性)。
|
||||||
// 前瞻钩子:勾选驱动中央渲染留待下一轮接真实 DS(本轮暂无消费者)。
|
void objectClicked(const QString& objectId, int confType);
|
||||||
void tmCheckToggled(const QString& tmObjectId, bool checked);
|
// 当前全部被勾选的 TM 叶子 id(已合并发射)。
|
||||||
|
void checkedTmsChanged(const QStringList& tmObjectIds);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTreeWidget* tree_ = nullptr; // Qt 原生标准树(复选框/箭头由 Fusion 绘制,清晰可控)
|
QTreeWidget* tree_ = nullptr; // Qt 原生标准树(复选框/箭头由 Fusion 绘制,清晰可控)
|
||||||
QLabel* hint_ = nullptr;
|
QLabel* hint_ = nullptr;
|
||||||
|
bool checkPending_ = false; // 勾选合并发射防重入
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue