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