From 3ccb8df4ed47c3c49427e011ff3a06c41d1b1802 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 10 Jun 2026 17:41:46 +0800 Subject: [PATCH] =?UTF-8?q?fix(ui):=20=E4=BF=AE=E5=A4=8D=E6=94=B9=E5=90=8D?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E5=81=9C=E9=9D=A0=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E4=B8=A2=E5=A4=B1(bump=20dockState=E9=94=AE=E4=B8=A2=E5=BC=83?= =?UTF-8?q?=E5=A4=B1=E9=85=8D=E6=97=A7=E5=B8=83=E5=B1=80)=20+=20=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8C=BA=E6=94=B9=E5=9B=9EQToolButton(=E5=A4=B4?= =?UTF-8?q?=E5=83=8F=E5=9B=BE=E6=A0=87+=E5=A7=93=E5=90=8D=E8=81=8C?= =?UTF-8?q?=E5=8A=A1=E4=B8=80=E8=A1=8C,=E6=95=B4=E5=9D=97=E5=8F=AF?= =?UTF-8?q?=E7=82=B9)=E4=BF=AE=E5=A4=8D=E6=8C=A4=E6=88=90=E4=B8=80?= =?UTF-8?q?=E5=9B=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/TopBar.cpp | 65 +++++++++++++++++++++++++++------------------- src/app/main.cpp | 6 +++-- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/app/TopBar.cpp b/src/app/TopBar.cpp index 539fda5..471675d 100644 --- a/src/app/TopBar.cpp +++ b/src/app/TopBar.cpp @@ -3,12 +3,15 @@ #include #include #include +#include #include #include +#include #include #include #include -#include +#include +#include #include #include #include @@ -50,6 +53,29 @@ QWidget* makeIconButton(QWidget* parent, Glyph icon, const QString& tip) return btn; } +// 圆形头像图标:强调色填充 + 白色缩写。2x 绘制保证高 DPI 清晰。 +QPixmap renderAvatar(const QString& initials, int px, const QColor& bg, const QColor& fg) +{ + constexpr int kScale = 2; + const int s = px * kScale; + QPixmap pm(s, s); + pm.fill(Qt::transparent); + QPainter p(&pm); + p.setRenderHint(QPainter::Antialiasing, true); + p.setPen(Qt::NoPen); + p.setBrush(bg); + p.drawEllipse(0, 0, s, s); + QFont f = p.font(); + f.setPixelSize(static_cast(s * 0.4)); + f.setBold(true); + p.setFont(f); + p.setPen(fg); + p.drawText(QRect(0, 0, s, s), Qt::AlignCenter, initials); + p.end(); + pm.setDevicePixelRatio(kScale); + return pm; +} + // ── 四个菜单(结构对齐需求;叶子项当前为静态占位,后续接真实页面)── QMenu* buildViewMenu(QWidget* p) { @@ -146,7 +172,8 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) { " 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 { border:none; border-radius:8px; padding:4px 10px 4px 6px;" + " color:{{text/primary}}; font-size:%3px; }" "#userBtn:hover { background:{{bg/hover}}; }" "#userBtn::menu-indicator { image:none; }" "#avatar { background:{{accent/primary}}; color:{{text/on-primary}}; border-radius:17px; font-weight:%2;" @@ -205,37 +232,21 @@ TopBar::TopBar(QWidget* parent) : QWidget(parent) { lay->addWidget(makeDivider(this)); lay->addSpacing(12); - // 用户区:头像 + 姓名 + 职务 同一行,整块可点击(QPushButton + 子布局,子控件鼠标穿透→点击命中按钮)。 - auto* userBtn = new QPushButton(this); + // 用户区:头像(圆形图标) + 姓名·职务 同一行,整块可点击 → 退出登录菜单。 + // 用 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); - 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->setFixedSize(34, 34); - 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(); }); userBtn->setMenu(userMenu); - lay->addWidget(userBtn); } diff --git a/src/app/main.cpp b/src/app/main.cpp index 5bc18bd..d88b1fe 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -999,7 +999,9 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re const QSettings settings; const QByteArray geo = settings.value(QStringLiteral("ui/geometry")).toByteArray(); if (!geo.isEmpty()) window.restoreGeometry(geo); - const QByteArray dockState = settings.value(QStringLiteral("ui/dockState")).toByteArray(); + // 注意:ADS 按 dock 唯一名作键。改过 dock 名后旧布局会失配 → bump 此键丢弃旧布局, + // 回落到下方 addDockWidget 的默认排布(再改 dock 名时同样要 bump 版本号)。 + const QByteArray dockState = settings.value(QStringLiteral("ui/dockState_v2")).toByteArray(); if (!dockState.isEmpty()) { dockManager->restoreState(dockState); // restoreState 重建停靠区会重新显示 ADS 标题栏,再隐藏一次保持“无双标题”。 @@ -1010,7 +1012,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re QObject::connect(qApp, &QCoreApplication::aboutToQuit, dockManager, [dockManager, &window]() { QSettings settings; settings.setValue(QStringLiteral("ui/geometry"), window.saveGeometry()); - settings.setValue(QStringLiteral("ui/dockState"), dockManager->saveState()); + settings.setValue(QStringLiteral("ui/dockState_v2"), dockManager->saveState()); }); }