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
2 changed files with 67 additions and 15 deletions
Showing only changes of commit 9680fefbe3 - Show all commits

View File

@ -3,6 +3,7 @@
#include <QAbstractButton>
#include <QActionGroup>
#include <QColor>
#include <QEvent>
#include <QFont>
#include <QFrame>
#include <QHBoxLayout>
@ -13,6 +14,7 @@
#include <QPainter>
#include <QPixmap>
#include <QSize>
#include <QVBoxLayout>
#include <QStringList>
#include <QToolButton>
#include <QWidget>
@ -232,22 +234,65 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) {
lay->addWidget(makeDivider(this));
lay->addSpacing(12);
// 用户区:头像(圆形图标) + 姓名·职务 同一行,整块可点击 → 退出登录菜单。
// 用 QToolButton(图标+文字),而非 QPushButton+子布局——后者按空文本算尺寸会把内容挤成一团。
auto* userBtn = new QToolButton(this);
userBtn->setObjectName(QStringLiteral("userBtn"));
userBtn->setIcon(QIcon(renderAvatar(QStringLiteral("ZL"), 30,
geopro::app::tokenColor("accent/primary"), Qt::white)));
userBtn->setIconSize(QSize(30, 30));
userBtn->setText(QStringLiteral("张磊 · 高级工程师"));
userBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
userBtn->setPopupMode(QToolButton::InstantPopup);
userBtn->setCursor(Qt::PointingHandCursor);
auto* userMenu = new QMenu(userBtn);
QObject::connect(userMenu->addAction(QStringLiteral("退出登录")), &QAction::triggered, this,
// 用户区:头像(圆形,竖直居中) + 右侧 姓名(上)/职务(下) 左对齐 + 下拉箭头;整块可点 → 菜单。
// 用普通 QWidget + eventFilterQWidget 按子布局正确撑开QPushButton 装布局会按空文字算尺寸挤成一团)。
userRow_ = new QWidget(this);
userRow_->setObjectName(QStringLiteral("userBtn"));
userRow_->setAttribute(Qt::WA_StyledBackground, true); // 令 QSS 背景(hover)在 QWidget 上生效
userRow_->setCursor(Qt::PointingHandCursor);
userRow_->installEventFilter(this);
auto* uLay = new QHBoxLayout(userRow_);
uLay->setContentsMargins(8, 3, 8, 3);
uLay->setSpacing(10);
auto* avatar = new QLabel(userRow_);
avatar->setPixmap(
renderAvatar(QStringLiteral("ZL"), 34, geopro::app::tokenColor("accent/primary"), Qt::white));
avatar->setFixedSize(34, 34);
avatar->setAttribute(Qt::WA_TransparentForMouseEvents);
uLay->addWidget(avatar, 0, Qt::AlignVCenter);
auto* nameBox = new QWidget(userRow_);
nameBox->setAttribute(Qt::WA_TransparentForMouseEvents);
auto* nameLay = new QVBoxLayout(nameBox);
nameLay->setContentsMargins(0, 0, 0, 0);
nameLay->setSpacing(0);
auto* userName = new QLabel(QStringLiteral("张磊"), nameBox);
userName->setObjectName(QStringLiteral("userName"));
auto* userRole = new QLabel(QStringLiteral("高级工程师"), nameBox);
userRole->setObjectName(QStringLiteral("userRole"));
nameLay->addWidget(userName);
nameLay->addWidget(userRole);
uLay->addWidget(nameBox, 0, Qt::AlignVCenter);
auto* chevronLbl = new QLabel(userRow_);
chevronLbl->setPixmap(QPixmap(geopro::app::writeChevronIcon(true, QColor("#7C8493")))
.scaled(12, 12, Qt::KeepAspectRatio, Qt::SmoothTransformation));
chevronLbl->setAttribute(Qt::WA_TransparentForMouseEvents);
uLay->addWidget(chevronLbl, 0, Qt::AlignVCenter);
// 下拉菜单(加宽):账户 / 个人资料 / 偏好设置 / API 密钥 / 退出登录。
userMenu_ = new QMenu(this);
userMenu_->setMinimumWidth(200);
userMenu_->addAction(QStringLiteral("账户"));
userMenu_->addAction(QStringLiteral("个人资料"));
QObject::connect(userMenu_->addAction(QStringLiteral("偏好设置")), &QAction::triggered, this,
[this] { emit settingsRequested(); });
userMenu_->addAction(QStringLiteral("API 密钥"));
userMenu_->addSeparator();
QObject::connect(userMenu_->addAction(QStringLiteral("退出登录")), &QAction::triggered, this,
[this] { emit logoutRequested(); });
userBtn->setMenu(userMenu);
lay->addWidget(userBtn);
lay->addWidget(userRow_);
}
bool TopBar::eventFilter(QObject* obj, QEvent* event) {
if (obj == userRow_ && event->type() == QEvent::MouseButtonRelease) {
if (userMenu_)
userMenu_->exec(userRow_->mapToGlobal(QPoint(0, userRow_->height() + 2)));
return true;
}
return QWidget::eventFilter(obj, event);
}
void TopBar::setWorkspaces(const std::vector<data::Workspace>& list, const QString& currentId) {

View File

@ -4,6 +4,8 @@
#include "repo/RepoTypes.hpp"
class QToolButton;
class QEvent;
class QMenu;
namespace geopro::app {
@ -21,6 +23,9 @@ public:
bool hasMore);
void setProjectButtonText(const QString& name); // 弹窗切换项目后更新按钮文字
protected:
bool eventFilter(QObject* obj, QEvent* event) override; // 用户区整块可点 → 弹菜单
signals:
void workspaceSwitchRequested(const QString& tenantId);
void projectSwitchRequested(const QString& projectId);
@ -31,6 +36,8 @@ signals:
private:
QToolButton* wsBtn_ = nullptr;
QToolButton* projBtn_ = nullptr;
QWidget* userRow_ = nullptr; // 用户区整块(头像+姓名/职务+箭头)
QMenu* userMenu_ = nullptr; // 用户下拉菜单
};
} // namespace geopro::app