feat(app): TopBar 升级为数据驱动类(工作空间/项目切换信号)
This commit is contained in:
parent
f4ca9bcd38
commit
6e78e50b0b
|
|
@ -127,12 +127,10 @@ QWidget* buildMenuBar(QWidget* parent)
|
||||||
return mb;
|
return mb;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget* buildTopToolBar(QWidget* parent)
|
TopBar::TopBar(QWidget* parent) : QWidget(parent) {
|
||||||
{
|
setObjectName(QStringLiteral("appToolBar"));
|
||||||
auto* bar = new QWidget(parent);
|
setFixedHeight(56);
|
||||||
bar->setObjectName(QStringLiteral("appToolBar"));
|
setStyleSheet(QStringLiteral(
|
||||||
bar->setFixedHeight(56);
|
|
||||||
bar->setStyleSheet(QStringLiteral(
|
|
||||||
"#appToolBar { background:#FFFFFF; border-bottom:1px solid #E1E6EE; }"
|
"#appToolBar { background:#FFFFFF; border-bottom:1px solid #E1E6EE; }"
|
||||||
"#topDivider { color:#E1E6EE; }"
|
"#topDivider { color:#E1E6EE; }"
|
||||||
"#wsSwitcher { color:#1F2A3D; border:none; border-radius:8px; padding:8px 12px;"
|
"#wsSwitcher { color:#1F2A3D; border:none; border-radius:8px; padding:8px 12px;"
|
||||||
|
|
@ -146,81 +144,56 @@ QWidget* buildTopToolBar(QWidget* parent)
|
||||||
"#userName { color:#1F2A3D; font-size:13px; font-weight:600; }"
|
"#userName { color:#1F2A3D; font-size:13px; font-weight:600; }"
|
||||||
"#userRole { color:#8A93A3; font-size:11px; }"));
|
"#userRole { color:#8A93A3; font-size:11px; }"));
|
||||||
|
|
||||||
auto* lay = new QHBoxLayout(bar);
|
auto* lay = new QHBoxLayout(this);
|
||||||
lay->setContentsMargins(14, 0, 14, 0);
|
lay->setContentsMargins(14, 0, 14, 0);
|
||||||
lay->setSpacing(0);
|
lay->setSpacing(0);
|
||||||
|
|
||||||
// ── 工作空间切换(最左):显示当前空间,点击下拉切换 ──
|
// 工作空间切换器(数据驱动;初始占位文本,待 setWorkspaces 填充)。
|
||||||
auto* wsBtn = new QToolButton(bar);
|
wsBtn_ = new QToolButton(this);
|
||||||
wsBtn->setObjectName(QStringLiteral("wsSwitcher"));
|
wsBtn_->setObjectName(QStringLiteral("wsSwitcher"));
|
||||||
wsBtn->setIcon(makeGlyph(Glyph::Workspace, QColor("#2D6CB5"), kWorkspaceIcon));
|
wsBtn_->setIcon(makeGlyph(Glyph::Workspace, QColor("#2D6CB5"), kWorkspaceIcon));
|
||||||
wsBtn->setIconSize(QSize(kWorkspaceIcon, kWorkspaceIcon));
|
wsBtn_->setIconSize(QSize(kWorkspaceIcon, kWorkspaceIcon));
|
||||||
wsBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
wsBtn_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||||
wsBtn->setPopupMode(QToolButton::InstantPopup);
|
wsBtn_->setPopupMode(QToolButton::InstantPopup);
|
||||||
wsBtn->setCursor(Qt::PointingHandCursor);
|
wsBtn_->setCursor(Qt::PointingHandCursor);
|
||||||
|
wsBtn_->setText(QStringLiteral("(加载中…)"));
|
||||||
auto* wsMenu = new QMenu(bar);
|
wsBtn_->setMenu(new QMenu(wsBtn_));
|
||||||
auto* wsHeader = wsMenu->addAction(QStringLiteral("切换空间"));
|
lay->addWidget(wsBtn_);
|
||||||
wsHeader->setEnabled(false);
|
|
||||||
wsMenu->addSeparator();
|
|
||||||
auto* wsGroup = new QActionGroup(bar);
|
|
||||||
wsGroup->setExclusive(true);
|
|
||||||
const QStringList spaces = {QStringLiteral("个人工作空间"), QStringLiteral("勘探一队"),
|
|
||||||
QStringLiteral("研究院共享")};
|
|
||||||
for (const auto& s : spaces) {
|
|
||||||
auto* a = wsMenu->addAction(s);
|
|
||||||
a->setCheckable(true);
|
|
||||||
wsGroup->addAction(a);
|
|
||||||
if (s == spaces.front()) a->setChecked(true);
|
|
||||||
QObject::connect(a, &QAction::triggered, wsBtn,
|
|
||||||
[wsBtn, s]() { wsBtn->setText(s + QStringLiteral(" ▾")); });
|
|
||||||
}
|
|
||||||
wsBtn->setMenu(wsMenu);
|
|
||||||
wsBtn->setText(spaces.front() + QStringLiteral(" ▾"));
|
|
||||||
lay->addWidget(wsBtn);
|
|
||||||
|
|
||||||
lay->addSpacing(10);
|
lay->addSpacing(10);
|
||||||
lay->addWidget(makeDivider(bar));
|
lay->addWidget(makeDivider(this));
|
||||||
lay->addSpacing(10);
|
lay->addSpacing(10);
|
||||||
|
|
||||||
// ── 项目选择器(与工作空间切换同款样式:无边框 + 图标 + 文本 + 下拉)──
|
// 项目切换器(数据驱动)。
|
||||||
auto* projBtn = new QToolButton(bar);
|
projBtn_ = new QToolButton(this);
|
||||||
projBtn->setObjectName(QStringLiteral("wsSwitcher"));
|
projBtn_->setObjectName(QStringLiteral("wsSwitcher"));
|
||||||
projBtn->setIcon(makeGlyph(Glyph::Folder, QColor("#2D6CB5"), kWorkspaceIcon));
|
projBtn_->setIcon(makeGlyph(Glyph::Folder, QColor("#2D6CB5"), kWorkspaceIcon));
|
||||||
projBtn->setIconSize(QSize(kWorkspaceIcon, kWorkspaceIcon));
|
projBtn_->setIconSize(QSize(kWorkspaceIcon, kWorkspaceIcon));
|
||||||
projBtn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
projBtn_->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||||
projBtn->setPopupMode(QToolButton::InstantPopup);
|
projBtn_->setPopupMode(QToolButton::InstantPopup);
|
||||||
projBtn->setCursor(Qt::PointingHandCursor);
|
projBtn_->setCursor(Qt::PointingHandCursor);
|
||||||
auto* projMenu = new QMenu(bar);
|
projBtn_->setText(QStringLiteral("(加载中…)"));
|
||||||
auto* projHeader = projMenu->addAction(QStringLiteral("切换项目"));
|
projBtn_->setMenu(new QMenu(projBtn_));
|
||||||
projHeader->setEnabled(false);
|
lay->addWidget(projBtn_);
|
||||||
projMenu->addSeparator();
|
|
||||||
auto* projCur = projMenu->addAction(QStringLiteral("青海湖北岸勘探项目"));
|
|
||||||
projCur->setCheckable(true);
|
|
||||||
projCur->setChecked(true);
|
|
||||||
projBtn->setMenu(projMenu);
|
|
||||||
projBtn->setText(QStringLiteral("青海湖北岸勘探项目 青海·海北州 ▾"));
|
|
||||||
lay->addWidget(projBtn);
|
|
||||||
|
|
||||||
lay->addStretch();
|
lay->addStretch();
|
||||||
|
|
||||||
// ── 右侧:帮助 / 通知 / 设置(仅图标,悬停显示文本)──
|
lay->addWidget(makeIconButton(this, Glyph::Help, QStringLiteral("帮助")));
|
||||||
lay->addWidget(makeIconButton(bar, Glyph::Help, QStringLiteral("帮助")));
|
lay->addWidget(makeIconButton(this, Glyph::Bell, QStringLiteral("通知")));
|
||||||
lay->addWidget(makeIconButton(bar, Glyph::Bell, QStringLiteral("通知")));
|
lay->addWidget(makeIconButton(this, Glyph::Gear, QStringLiteral("设置")));
|
||||||
lay->addWidget(makeIconButton(bar, Glyph::Gear, QStringLiteral("设置")));
|
|
||||||
lay->addSpacing(10);
|
lay->addSpacing(10);
|
||||||
lay->addWidget(makeDivider(bar));
|
lay->addWidget(makeDivider(this));
|
||||||
lay->addSpacing(12);
|
lay->addSpacing(12);
|
||||||
|
|
||||||
// ── 用户:圆形头像 + 姓名/职务 ──
|
// 用户区(本轮静态)。
|
||||||
auto* avatar = new QLabel(QStringLiteral("ZL"), bar);
|
auto* avatar = new QLabel(QStringLiteral("ZL"), this);
|
||||||
avatar->setObjectName(QStringLiteral("avatar"));
|
avatar->setObjectName(QStringLiteral("avatar"));
|
||||||
avatar->setFixedSize(34, 34);
|
avatar->setFixedSize(34, 34);
|
||||||
avatar->setAlignment(Qt::AlignCenter);
|
avatar->setAlignment(Qt::AlignCenter);
|
||||||
lay->addWidget(avatar);
|
lay->addWidget(avatar);
|
||||||
lay->addSpacing(8);
|
lay->addSpacing(8);
|
||||||
|
|
||||||
auto* userBox = new QWidget(bar);
|
auto* userBox = new QWidget(this);
|
||||||
auto* userLay = new QVBoxLayout(userBox);
|
auto* userLay = new QVBoxLayout(userBox);
|
||||||
userLay->setContentsMargins(0, 0, 0, 0);
|
userLay->setContentsMargins(0, 0, 0, 0);
|
||||||
userLay->setSpacing(0);
|
userLay->setSpacing(0);
|
||||||
|
|
@ -231,8 +204,56 @@ QWidget* buildTopToolBar(QWidget* parent)
|
||||||
userLay->addWidget(userName);
|
userLay->addWidget(userName);
|
||||||
userLay->addWidget(userRole);
|
userLay->addWidget(userRole);
|
||||||
lay->addWidget(userBox);
|
lay->addWidget(userBox);
|
||||||
|
}
|
||||||
|
|
||||||
return bar;
|
void TopBar::setWorkspaces(const std::vector<data::Workspace>& list, const QString& currentId) {
|
||||||
|
auto* menu = new QMenu(wsBtn_);
|
||||||
|
auto* header = menu->addAction(QStringLiteral("切换空间"));
|
||||||
|
header->setEnabled(false);
|
||||||
|
menu->addSeparator();
|
||||||
|
QString currentName;
|
||||||
|
for (const auto& w : list) {
|
||||||
|
const QString id = QString::fromStdString(w.id);
|
||||||
|
const QString name = QString::fromStdString(w.name);
|
||||||
|
auto* a = menu->addAction(name);
|
||||||
|
a->setCheckable(true);
|
||||||
|
a->setChecked(id == currentId);
|
||||||
|
if (id == currentId) currentName = name;
|
||||||
|
QObject::connect(a, &QAction::triggered, this,
|
||||||
|
[this, id]() { emit workspaceSwitchRequested(id); });
|
||||||
|
}
|
||||||
|
if (list.empty()) {
|
||||||
|
auto* none = menu->addAction(QStringLiteral("(暂无空间)"));
|
||||||
|
none->setEnabled(false);
|
||||||
|
}
|
||||||
|
wsBtn_->setMenu(menu);
|
||||||
|
wsBtn_->setText((currentName.isEmpty() ? QStringLiteral("选择空间") : currentName) +
|
||||||
|
QStringLiteral(" ▾"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopBar::setProjects(const std::vector<data::ProjectSummary>& list, const QString& currentId) {
|
||||||
|
auto* menu = new QMenu(projBtn_);
|
||||||
|
auto* header = menu->addAction(QStringLiteral("切换项目"));
|
||||||
|
header->setEnabled(false);
|
||||||
|
menu->addSeparator();
|
||||||
|
QString currentName;
|
||||||
|
for (const auto& p : list) {
|
||||||
|
const QString id = QString::fromStdString(p.id);
|
||||||
|
const QString name = QString::fromStdString(p.name);
|
||||||
|
auto* a = menu->addAction(name);
|
||||||
|
a->setCheckable(true);
|
||||||
|
a->setChecked(id == currentId);
|
||||||
|
if (id == currentId) currentName = name;
|
||||||
|
QObject::connect(a, &QAction::triggered, this,
|
||||||
|
[this, id]() { emit projectSwitchRequested(id); });
|
||||||
|
}
|
||||||
|
if (list.empty()) {
|
||||||
|
auto* none = menu->addAction(QStringLiteral("(暂无项目)"));
|
||||||
|
none->setEnabled(false);
|
||||||
|
}
|
||||||
|
projBtn_->setMenu(menu);
|
||||||
|
projBtn_->setText((currentName.isEmpty() ? QStringLiteral("选择项目") : currentName) +
|
||||||
|
QStringLiteral(" ▾"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <QWidget>
|
||||||
|
#include <vector>
|
||||||
|
#include "repo/RepoTypes.hpp"
|
||||||
|
|
||||||
// 顶部应用区(对齐原型,静态视觉壳):
|
class QToolButton;
|
||||||
// - buildMenuBar:最上方的菜单栏(视图 / 项目管理 / 业务工具 / 设备,含多级子菜单)。
|
|
||||||
// - buildTopToolBar:菜单栏下方的工具条(工作空间切换 + 项目选择 + 帮助/通知/设置 + 用户)。
|
|
||||||
// 调用方将两者纵向堆叠后经 QMainWindow::setMenuWidget 挂到主窗口顶部。
|
|
||||||
// 菜单/按钮当前为静态占位,后续接真实页面与数据。
|
|
||||||
|
|
||||||
class QWidget;
|
|
||||||
|
|
||||||
namespace geopro::app {
|
namespace geopro::app {
|
||||||
|
|
||||||
// 顶部菜单栏(返回 QWidget*,内部是 QMenuBar;调用方放在最上一行)。
|
// 顶部菜单栏(静态,本轮不接真实页面)。
|
||||||
QWidget* buildMenuBar(QWidget* parent = nullptr);
|
QWidget* buildMenuBar(QWidget* parent);
|
||||||
|
|
||||||
// 菜单栏下方的工具条(工作空间/项目/帮助/通知/设置/用户)。
|
// 顶部工具条:数据驱动的工作空间/项目切换器 + 右侧图标 + 用户区。
|
||||||
QWidget* buildTopToolBar(QWidget* parent = nullptr);
|
class TopBar : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TopBar(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void setWorkspaces(const std::vector<data::Workspace>& list, const QString& currentId);
|
||||||
|
void setProjects(const std::vector<data::ProjectSummary>& list, const QString& currentId);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void workspaceSwitchRequested(const QString& tenantId);
|
||||||
|
void projectSwitchRequested(const QString& projectId);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QToolButton* wsBtn_ = nullptr;
|
||||||
|
QToolButton* projBtn_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -790,7 +790,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
topLayout->setContentsMargins(0, 0, 0, 0);
|
topLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
topLayout->setSpacing(0);
|
topLayout->setSpacing(0);
|
||||||
topLayout->addWidget(geopro::app::buildMenuBar(topChrome));
|
topLayout->addWidget(geopro::app::buildMenuBar(topChrome));
|
||||||
topLayout->addWidget(geopro::app::buildTopToolBar(topChrome));
|
topLayout->addWidget(new geopro::app::TopBar(topChrome));
|
||||||
window.setMenuWidget(topChrome);
|
window.setMenuWidget(topChrome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue