refactor/pure-qt-ui #3

Merged
gaozheng merged 56 commits from refactor/pure-qt-ui into main 2026-06-10 18:41:53 +08:00
3 changed files with 33 additions and 35 deletions
Showing only changes of commit 389a2da744 - Show all commits

View File

@ -19,6 +19,7 @@
#include <ElaComboBox.h> #include <ElaComboBox.h>
#include <ElaLineEdit.h> #include <ElaLineEdit.h>
#include <ElaPushButton.h> #include <ElaPushButton.h>
#include <ElaTableWidget.h>
namespace geopro::app { namespace geopro::app {
namespace { namespace {
@ -66,7 +67,7 @@ ProjectListDialog::ProjectListDialog(data::IProjectRepository& repo, QWidget* pa
filter->addStretch(); filter->addStretch();
root->addLayout(filter); root->addLayout(filter);
table_ = new QTableWidget(this); table_ = new ElaTableWidget(this); // Ela item 版表格(继承 QTableWidget),直替
table_->setColumnCount(8); table_->setColumnCount(8);
table_->setHorizontalHeaderLabels(QStringList{ table_->setHorizontalHeaderLabels(QStringList{
QStringLiteral("序号"), QStringLiteral("项目名称"), QStringLiteral("项目编号"), QStringLiteral("序号"), QStringLiteral("项目名称"), QStringLiteral("项目编号"),

View File

@ -1,13 +1,15 @@
#include "panels/ObjectTreePanel.hpp" #include "panels/ObjectTreePanel.hpp"
#include <QColor>
#include <QLabel> #include <QLabel>
#include <QModelIndex>
#include <QSignalBlocker> #include <QSignalBlocker>
#include <QTreeWidget> #include <QStandardItem>
#include <QTreeWidgetItem> #include <QStandardItemModel>
#include <QTreeView>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "Glyphs.hpp" #include <ElaTreeView.h>
#include "Theme.hpp" #include "Theme.hpp"
#include "dto/NavDto.hpp" #include "dto/NavDto.hpp"
@ -17,15 +19,16 @@ namespace {
// TM 节点把 tmObjectId 存在该角色GS/项目根节点为空。 // TM 节点把 tmObjectId 存在该角色GS/项目根节点为空。
constexpr int kRoleTmId = Qt::UserRole + 2; constexpr int kRoleTmId = Qt::UserRole + 2;
void addNodes(QTreeWidgetItem* parent, const std::vector<data::dto::StructTreeNode>& nodes) { void addNodes(QStandardItem* 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 QStandardItem(QString::fromStdString(n.node.name));
item->setText(0, QString::fromStdString(n.node.name)); item->setEditable(false);
if (n.isTm) { if (n.isTm) {
item->setData(0, kRoleTmId, QString::fromStdString(n.node.id)); item->setData(QString::fromStdString(n.node.id), kRoleTmId);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckable(true);
item->setCheckState(0, Qt::Unchecked); // 真实数据渲染下一轮接入,默认不勾 item->setCheckState(Qt::Unchecked); // 真实数据渲染下一轮接入,默认不勾
} }
parent->appendRow(item);
addNodes(item, n.children); addNodes(item, n.children);
} }
} }
@ -36,19 +39,10 @@ ObjectTreePanel::ObjectTreePanel(QWidget* parent) : QWidget(parent) {
lay->setContentsMargins(0, 0, 0, 0); lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0); lay->setSpacing(0);
tree_ = new QTreeWidget(this); tree_ = new ElaTreeView(this); // Fluent 树视图(自绘展开/折叠指示,随主题)
tree_->setHeaderHidden(true); tree_->setHeaderHidden(true);
{ model_ = new QStandardItemModel(tree_);
const QString openArrow = writeChevronIcon(true, QColor("#8A93A3")); tree_->setModel(model_);
const QString closedArrow = writeChevronIcon(false, QColor("#8A93A3"));
geopro::app::applyThemedStyleSheet(
tree_, QStringLiteral("QTreeView::branch { background: #FFFFFF; }"
"QTreeView::branch:has-children:!has-siblings:closed,"
"QTreeView::branch:closed:has-children:has-siblings { image: url(%1); }"
"QTreeView::branch:open:has-children:!has-siblings,"
"QTreeView::branch:open:has-children:has-siblings { image: url(%2); }")
.arg(closedArrow, openArrow));
}
lay->addWidget(tree_, 1); lay->addWidget(tree_, 1);
hint_ = new QLabel(QStringLiteral("正在加载对象…"), this); hint_ = new QLabel(QStringLiteral("正在加载对象…"), this);
@ -57,21 +51,22 @@ ObjectTreePanel::ObjectTreePanel(QWidget* parent) : QWidget(parent) {
hint_->setVisible(false); hint_->setVisible(false);
lay->addWidget(hint_); lay->addWidget(hint_);
QObject::connect(tree_, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem* item, int) { // 单击 TM → tmClicked按 index 取 tmId
const QString tmId = item->data(0, kRoleTmId).toString(); QObject::connect(tree_, &QTreeView::clicked, this, [this](const QModelIndex& idx) {
const QString tmId = idx.data(kRoleTmId).toString();
if (!tmId.isEmpty()) emit tmClicked(tmId); if (!tmId.isEmpty()) emit tmClicked(tmId);
}); });
QObject::connect(tree_, &QTreeWidget::itemChanged, this, [this](QTreeWidgetItem* item, int) { // 勾选变化 → tmCheckToggled。
const QString tmId = item->data(0, kRoleTmId).toString(); QObject::connect(model_, &QStandardItemModel::itemChanged, this, [this](QStandardItem* item) {
if (!tmId.isEmpty()) const QString tmId = item->data(kRoleTmId).toString();
emit tmCheckToggled(tmId, item->checkState(0) == Qt::Checked); if (!tmId.isEmpty()) emit tmCheckToggled(tmId, item->checkState() == Qt::Checked);
}); });
} }
void ObjectTreePanel::setStructure(const QString& projectName, void ObjectTreePanel::setStructure(const QString& projectName,
const std::vector<data::StructNode>& nodes) { const std::vector<data::StructNode>& nodes) {
const QSignalBlocker block(tree_); // 重建触发 itemChanged先屏蔽 const QSignalBlocker block(model_); // 重建触发 itemChanged先屏蔽
tree_->clear(); model_->clear();
const auto roots = data::dto::buildStructTree(nodes); const auto roots = data::dto::buildStructTree(nodes);
if (roots.empty()) { if (roots.empty()) {
showMessage(projectName.isEmpty() ? QStringLiteral("(暂无项目)") showMessage(projectName.isEmpty() ? QStringLiteral("(暂无项目)")
@ -80,12 +75,12 @@ void ObjectTreePanel::setStructure(const QString& projectName,
} }
hint_->setVisible(false); hint_->setVisible(false);
tree_->setVisible(true); tree_->setVisible(true);
addNodes(tree_->invisibleRootItem(), roots); // 结构已含项目根节点,直接渲染 addNodes(model_->invisibleRootItem(), roots); // 结构已含项目根节点,直接渲染
tree_->expandAll(); tree_->expandAll();
} }
void ObjectTreePanel::showMessage(const QString& message) { void ObjectTreePanel::showMessage(const QString& message) {
tree_->clear(); model_->clear();
tree_->setVisible(false); tree_->setVisible(false);
hint_->setText(message); hint_->setText(message);
hint_->setVisible(true); hint_->setVisible(true);

View File

@ -3,7 +3,8 @@
#include <vector> #include <vector>
#include "repo/RepoTypes.hpp" #include "repo/RepoTypes.hpp"
class QTreeWidget; class QTreeView;
class QStandardItemModel;
class QLabel; class QLabel;
namespace geopro::app { namespace geopro::app {
@ -24,7 +25,8 @@ signals:
void tmCheckToggled(const QString& tmObjectId, bool checked); void tmCheckToggled(const QString& tmObjectId, bool checked);
private: private:
QTreeWidget* tree_ = nullptr; QTreeView* tree_ = nullptr; // ElaTreeView(继承 QTreeView)
QStandardItemModel* model_ = nullptr; // 标准 model(Qt 自带)
QLabel* hint_ = nullptr; QLabel* hint_ = nullptr;
}; };