From cfd39e5be80522ed629986de7c098929f3590f09 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 10 Jun 2026 12:00:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(ela):=20=E5=AF=B9=E8=B1=A1=E6=A0=91?= =?UTF-8?q?=E9=80=80=E5=9B=9E=E6=A0=87=E5=87=86=20QTreeWidget(=E5=A4=8D?= =?UTF-8?q?=E9=80=89=E6=A1=86=E6=B8=85=E6=99=B0)=20+=20=E8=A1=8C=E5=86=85?= =?UTF-8?q?=E8=BE=B9=E8=B7=9D=E6=94=B6=E7=B4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ElaTreeView 是 ElaWidgetTools 自绘控件(非 Qt 原生), light 下复选框对比度不足、选中渲染有局限。 - 对象树 ElaTreeView+QStandardItemModel → 标准 QTreeWidget+QTreeWidgetItem: 复选框/展开箭头由 Fusion 原生绘制, 明暗都清晰; 行为(TM 勾选/点击)不变 - 全局 QTreeView::item padding 8px→4px: 行间距过大修正 --- src/app/Theme.cpp | 2 +- src/app/panels/ObjectTreePanel.cpp | 48 +++++++++++++----------------- src/app/panels/ObjectTreePanel.hpp | 6 ++-- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/app/Theme.cpp b/src/app/Theme.cpp index f059bae..6336338 100644 --- a/src/app/Theme.cpp +++ b/src/app/Theme.cpp @@ -74,7 +74,7 @@ QTreeWidget, QListWidget, QTreeView, QListView { outline: none; } QTreeWidget::item, QListWidget::item, QTreeView::item, QListView::item { - padding: 8px 8px; + padding: 4px 8px; border-radius: 6px; margin: 1px 4px; } diff --git a/src/app/panels/ObjectTreePanel.cpp b/src/app/panels/ObjectTreePanel.cpp index 8afce22..5263fd2 100644 --- a/src/app/panels/ObjectTreePanel.cpp +++ b/src/app/panels/ObjectTreePanel.cpp @@ -1,15 +1,11 @@ #include "panels/ObjectTreePanel.hpp" #include -#include #include -#include -#include -#include +#include +#include #include -#include - #include "Theme.hpp" #include "dto/NavDto.hpp" @@ -19,16 +15,15 @@ namespace { // TM 节点把 tmObjectId 存在该角色;GS/项目根节点为空。 constexpr int kRoleTmId = Qt::UserRole + 2; -void addNodes(QStandardItem* parent, const std::vector& nodes) { +void addNodes(QTreeWidgetItem* parent, const std::vector& nodes) { for (const auto& n : nodes) { - auto* item = new QStandardItem(QString::fromStdString(n.node.name)); - item->setEditable(false); + auto* item = new QTreeWidgetItem(parent); + item->setText(0, QString::fromStdString(n.node.name)); if (n.isTm) { - item->setData(QString::fromStdString(n.node.id), kRoleTmId); - item->setCheckable(true); - item->setCheckState(Qt::Unchecked); // 真实数据渲染下一轮接入,默认不勾 + item->setData(0, kRoleTmId, QString::fromStdString(n.node.id)); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(0, Qt::Unchecked); // 真实数据渲染下一轮接入,默认不勾 } - parent->appendRow(item); addNodes(item, n.children); } } @@ -39,11 +34,10 @@ ObjectTreePanel::ObjectTreePanel(QWidget* parent) : QWidget(parent) { lay->setContentsMargins(0, 0, 0, 0); lay->setSpacing(0); - tree_ = new ElaTreeView(this); // Fluent 树视图(自绘展开/折叠指示,随主题) + // Qt 原生标准树:复选框/展开箭头由 Fusion 绘制(明暗都清晰);配色取自全局主题 QSS。 + tree_ = new QTreeWidget(this); tree_->setHeaderHidden(true); - tree_->setIndentation(14); // 默认缩进偏大,收紧更紧凑协调 - model_ = new QStandardItemModel(tree_); - tree_->setModel(model_); + tree_->setIndentation(14); // 收紧缩进 lay->addWidget(tree_, 1); hint_ = new QLabel(QStringLiteral("正在加载对象…"), this); @@ -52,22 +46,20 @@ ObjectTreePanel::ObjectTreePanel(QWidget* parent) : QWidget(parent) { hint_->setVisible(false); lay->addWidget(hint_); - // 单击 TM → tmClicked(按 index 取 tmId)。 - QObject::connect(tree_, &QTreeView::clicked, this, [this](const QModelIndex& idx) { - const QString tmId = idx.data(kRoleTmId).toString(); + QObject::connect(tree_, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem* item, int) { + const QString tmId = item->data(0, kRoleTmId).toString(); if (!tmId.isEmpty()) emit tmClicked(tmId); }); - // 勾选变化 → tmCheckToggled。 - QObject::connect(model_, &QStandardItemModel::itemChanged, this, [this](QStandardItem* item) { - const QString tmId = item->data(kRoleTmId).toString(); - if (!tmId.isEmpty()) emit tmCheckToggled(tmId, item->checkState() == Qt::Checked); + 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); }); } void ObjectTreePanel::setStructure(const QString& projectName, const std::vector& nodes) { - const QSignalBlocker block(model_); // 重建触发 itemChanged,先屏蔽 - model_->clear(); + const QSignalBlocker block(tree_); // 重建触发 itemChanged,先屏蔽 + tree_->clear(); const auto roots = data::dto::buildStructTree(nodes); if (roots.empty()) { showMessage(projectName.isEmpty() ? QStringLiteral("(暂无项目)") @@ -76,12 +68,12 @@ void ObjectTreePanel::setStructure(const QString& projectName, } hint_->setVisible(false); tree_->setVisible(true); - addNodes(model_->invisibleRootItem(), roots); // 结构已含项目根节点,直接渲染 + addNodes(tree_->invisibleRootItem(), roots); // 结构已含项目根节点,直接渲染 tree_->expandAll(); } void ObjectTreePanel::showMessage(const QString& message) { - model_->clear(); + tree_->clear(); tree_->setVisible(false); hint_->setText(message); hint_->setVisible(true); diff --git a/src/app/panels/ObjectTreePanel.hpp b/src/app/panels/ObjectTreePanel.hpp index 33cfff4..1ba37e8 100644 --- a/src/app/panels/ObjectTreePanel.hpp +++ b/src/app/panels/ObjectTreePanel.hpp @@ -3,8 +3,7 @@ #include #include "repo/RepoTypes.hpp" -class QTreeView; -class QStandardItemModel; +class QTreeWidget; class QLabel; namespace geopro::app { @@ -25,8 +24,7 @@ signals: void tmCheckToggled(const QString& tmObjectId, bool checked); private: - QTreeView* tree_ = nullptr; // ElaTreeView(继承 QTreeView) - QStandardItemModel* model_ = nullptr; // 标准 model(Qt 自带) + QTreeWidget* tree_ = nullptr; // Qt 原生标准树(复选框/箭头由 Fusion 绘制,清晰可控) QLabel* hint_ = nullptr; };