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
1 changed files with 44 additions and 31 deletions
Showing only changes of commit c953b35334 - Show all commits

View File

@ -8,10 +8,10 @@
#include <QLabel>
#include <QMenu>
#include <QMenuBar>
#include <QPushButton>
#include <QSize>
#include <QStringList>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidget>
#include "Glyphs.hpp"
@ -132,16 +132,23 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) {
// 角色名=caption(12)。原 11px 角色名上调到 12去掉只差 1px 的糊层级。
// 切换器(ElaToolButton)/图标(ElaIconButton) 自绘 Fluent不再写它们的 QSS。
// 仅保留:工具条底/分隔线、头像(圆形自定义)、用户名/角色。头像白字用 {{text/on-primary}} 令牌。
// 切换器下拉箭头:用生成的高清 chevron PNG 作 menu-indicator替代旧的粗糙文字箭头中性灰双主题可读。
const QString chevron = geopro::app::writeChevronIcon(true, QColor("#7C8493"));
geopro::app::applyTokenizedStyleSheet(
this, QStringLiteral(
"#appToolBar { background:{{bg/header}}; border-bottom:1px solid {{divider}}; }"
"#topDivider { color:{{divider}}; }"
"QToolButton::menu-indicator { image:none; }"
"#wsSwitcher { color:{{text/primary}}; border:none; border-radius:8px; padding:8px 12px;"
"#wsSwitcher { color:{{text/primary}}; border:none; border-radius:8px; padding:8px 26px 8px 12px;"
" font-size:%6px; font-weight:%4; }"
"#wsSwitcher:hover { background:{{bg/hover}}; }"
"#wsSwitcher::menu-indicator { image:url(%7); width:13px; height:13px;"
" subcontrol-position: right center; subcontrol-origin: padding; right:8px; }"
"QToolButton#iconBtn { border:none; border-radius:8px; padding:8px; }"
"QToolButton#iconBtn:hover { background:{{bg/hover}}; }"
"#userBtn { border:none; border-radius:8px; padding:2px 4px; text-align:left; }"
"#userBtn:hover { background:{{bg/hover}}; }"
"#userBtn::menu-indicator { image:none; }"
"#avatar { background:{{accent/primary}}; color:{{text/on-primary}}; border-radius:17px; font-weight:%2;"
" font-size:%1px; }"
"#userName { color:{{text/primary}}; font-size:%3px; font-weight:%4; }"
@ -151,13 +158,14 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) {
.arg(scaledPx(type::kLabel))
.arg(type::kWeightSemibold)
.arg(scaledPx(type::kCaption))
.arg(scaledPx(type::kTitle)));
.arg(scaledPx(type::kTitle))
.arg(chevron));
auto* lay = new QHBoxLayout(this);
lay->setContentsMargins(14, 0, 14, 0);
lay->setSpacing(0);
// 工作空间切换器QToolButton + 主题化 QSS下拉箭头用文字"▾"保证清晰;数据驱动)。
// 工作空间切换器QToolButton + 主题化 QSS下拉箭头用高清 chevron menu-indicator;数据驱动)。
wsBtn_ = new QToolButton(this);
wsBtn_->setObjectName(QStringLiteral("wsSwitcher"));
setThemedGlyph(wsBtn_, Glyph::Workspace, kWorkspaceIcon); // 中性主题色(蓝只留给选中/激活)
@ -197,31 +205,38 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) {
lay->addWidget(makeDivider(this));
lay->addSpacing(12);
// 用户区:头像可点击 → 弹出菜单(退出登录)。
auto* avatar = new QToolButton(this);
// 用户区:头像 + 姓名 + 职务 同一行整块可点击QPushButton + 子布局,子控件鼠标穿透→点击命中按钮)。
auto* userBtn = new QPushButton(this);
userBtn->setObjectName(QStringLiteral("userBtn"));
userBtn->setCursor(Qt::PointingHandCursor);
userBtn->setFlat(true);
auto* userLay = new QHBoxLayout(userBtn);
userLay->setContentsMargins(6, 2, 10, 2);
userLay->setSpacing(8);
auto* avatar = new QLabel(QStringLiteral("ZL"), userBtn);
avatar->setObjectName(QStringLiteral("avatar"));
avatar->setText(QStringLiteral("ZL"));
avatar->setFixedSize(34, 34);
avatar->setCursor(Qt::PointingHandCursor);
avatar->setPopupMode(QToolButton::InstantPopup);
auto* userMenu = new QMenu(avatar);
avatar->setAlignment(Qt::AlignCenter);
avatar->setAttribute(Qt::WA_TransparentForMouseEvents);
userLay->addWidget(avatar);
auto* userName = new QLabel(QStringLiteral("张磊"), userBtn);
userName->setObjectName(QStringLiteral("userName"));
userName->setAttribute(Qt::WA_TransparentForMouseEvents);
userLay->addWidget(userName);
auto* userRole = new QLabel(QStringLiteral("高级工程师"), userBtn);
userRole->setObjectName(QStringLiteral("userRole"));
userRole->setAttribute(Qt::WA_TransparentForMouseEvents);
userLay->addWidget(userRole);
auto* userMenu = new QMenu(userBtn);
QObject::connect(userMenu->addAction(QStringLiteral("退出登录")), &QAction::triggered, this,
[this] { emit logoutRequested(); });
avatar->setMenu(userMenu);
lay->addWidget(avatar);
lay->addSpacing(8);
userBtn->setMenu(userMenu);
auto* userBox = new QWidget(this);
auto* userLay = new QVBoxLayout(userBox);
userLay->setContentsMargins(0, 0, 0, 0);
userLay->setSpacing(0);
auto* userName = new QLabel(QStringLiteral("张磊"), userBox);
userName->setObjectName(QStringLiteral("userName"));
auto* userRole = new QLabel(QStringLiteral("高级工程师"), userBox);
userRole->setObjectName(QStringLiteral("userRole"));
userLay->addWidget(userName);
userLay->addWidget(userRole);
lay->addWidget(userBox);
lay->addWidget(userBtn);
}
void TopBar::setWorkspaces(const std::vector<data::Workspace>& list, const QString& currentId) {
@ -241,7 +256,7 @@ void TopBar::setWorkspaces(const std::vector<data::Workspace>& list, const QStri
group->addAction(a);
if (id == currentId) currentName = name;
QObject::connect(a, &QAction::triggered, this, [this, id, name]() {
wsBtn_->setText(name + QStringLiteral("")); // 立即反馈
wsBtn_->setText(name); // 立即反馈
emit workspaceSwitchRequested(id);
});
}
@ -250,8 +265,7 @@ void TopBar::setWorkspaces(const std::vector<data::Workspace>& list, const QStri
none->setEnabled(false);
}
wsBtn_->setMenu(menu);
wsBtn_->setText((currentName.isEmpty() ? QStringLiteral("选择空间") : currentName) +
QStringLiteral(""));
wsBtn_->setText(currentName.isEmpty() ? QStringLiteral("选择空间") : currentName);
}
void TopBar::setProjects(const std::vector<data::ProjectSummary>& list, const QString& currentId,
@ -272,7 +286,7 @@ void TopBar::setProjects(const std::vector<data::ProjectSummary>& list, const QS
group->addAction(a);
if (id == currentId) currentName = name;
QObject::connect(a, &QAction::triggered, this, [this, id, name]() {
projBtn_->setText(name + QStringLiteral(""));
projBtn_->setText(name);
emit projectSwitchRequested(id);
});
}
@ -286,12 +300,11 @@ void TopBar::setProjects(const std::vector<data::ProjectSummary>& list, const QS
QObject::connect(all, &QAction::triggered, this, [this]() { emit allProjectsRequested(); });
}
projBtn_->setMenu(menu);
projBtn_->setText((currentName.isEmpty() ? QStringLiteral("选择项目") : currentName) +
QStringLiteral(""));
projBtn_->setText(currentName.isEmpty() ? QStringLiteral("选择项目") : currentName);
}
void TopBar::setProjectButtonText(const QString& name) {
projBtn_->setText(name + QStringLiteral(""));
projBtn_->setText(name);
}
} // namespace geopro::app