geopro/src/app/PanelHeader.cpp

162 lines
5.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "PanelHeader.hpp"
#include "Theme.hpp"
#include <ElaIconButton.h>
#include <ElaToolButton.h>
#include <QButtonGroup>
#include <QColor>
#include <QHBoxLayout>
#include <QLabel>
#include <QSize>
#include <QStackedWidget>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidget>
namespace geopro::app {
namespace {
// ── 专业图标/字号尺寸(统一放大)──
constexpr int kHeaderHeight = 42;
constexpr int kTitleIcon = 20; // 表头标题图标
constexpr int kActionIcon = 19; // 表头操作按钮图标
constexpr int kTabIcon = 19; // Tab 图标
// 表头统一样式(标准表头 + Tab 表头共用)。字号/字重引用 Theme 排版令牌:
// 面板标题=title(15)、徽标=caption(12)、Tab 文本=body(13),加粗统一 semibold。
// #panelBadge 为中性计数徽标;#panelBadgeWarn 为“需注意”变体(语义 warning 色),
// 供异常计数等承载“待复查”含义的徽标使用(调用方改 objectName 即切换)。
// 表头底/标题/徽标样式。Tab(ElaToolButton)与操作按钮(ElaIconButton)自绘 Fluent
// 不再写它们的 QSS选中态由 Ela 的 checked 高亮表达,而非自定义下划线)。
QString headerQss()
{
return QStringLiteral(
"#panelHeader { background:#FFFFFF; border-bottom:1px solid #E6EAF1; }"
"#panelTitle { color:#1F2A3D; font-size:%1px; font-weight:%3; }"
"#panelBadge { background:#EAEEF5; color:#5A6B85; border-radius:9px;"
" padding:1px 7px; font-size:%2px; font-weight:%3; }"
"#panelBadgeWarn { background:%4; color:%5; border-radius:9px;"
" padding:1px 7px; font-size:%2px; font-weight:%3; }")
.arg(type::kTitle)
.arg(type::kCaption)
.arg(type::kWeightSemibold)
.arg(QString::fromUtf8(semantic::kWarningFill))
.arg(QString::fromUtf8(semantic::kWarning));
}
// 数量徽标(默认隐藏,调用方 setText+setVisible 显示)。
QLabel* makeBadge(QWidget* parent)
{
auto* badge = new QLabel(parent);
badge->setObjectName(QStringLiteral("panelBadge"));
badge->setAlignment(Qt::AlignCenter);
badge->setMinimumWidth(16);
badge->setVisible(false);
return badge;
}
// 表头操作按钮Fluent ElaIconButton图标沿用项目 glyph 像素图)。
QWidget* makeActionButton(QWidget* parent, const HeaderAction& a)
{
auto* btn = new ElaIconButton(
makeGlyph(a.first, QColor("#5A6B85"), kActionIcon).pixmap(kActionIcon, kActionIcon), parent);
btn->setFixedSize(30, 30); // QPixmap 构造不设尺寸,显式固定防变形
btn->setCursor(Qt::PointingHandCursor);
btn->setToolTip(a.second + QStringLiteral("(占位)"));
return btn;
}
} // namespace
QWidget* buildPanelHeader(Glyph icon, const QString& title, const QVector<HeaderAction>& actions)
{
auto* header = new QWidget();
header->setObjectName(QStringLiteral("panelHeader"));
header->setFixedHeight(kHeaderHeight);
geopro::app::applyThemedStyleSheet(header, headerQss());
auto* lay = new QHBoxLayout(header);
lay->setContentsMargins(12, 0, 8, 0);
lay->setSpacing(8);
auto* iconLbl = new QLabel(header);
iconLbl->setPixmap(makeGlyph(icon, QColor("#44546B"), kTitleIcon).pixmap(kTitleIcon, kTitleIcon));
lay->addWidget(iconLbl);
auto* titleLbl = new QLabel(title, header);
titleLbl->setObjectName(QStringLiteral("panelTitle"));
lay->addWidget(titleLbl);
lay->addWidget(makeBadge(header)); // 默认隐藏,调用方可经 findChild 更新
lay->addStretch();
for (const auto& a : actions) lay->addWidget(makeActionButton(header, a));
return header;
}
TabbedPanel buildTabbedPanel(const QVector<PanelTab>& tabs, const QVector<HeaderAction>& actions)
{
auto* box = new QWidget();
auto* v = new QVBoxLayout(box);
v->setContentsMargins(0, 0, 0, 0);
v->setSpacing(0);
auto* header = new QWidget(box);
header->setObjectName(QStringLiteral("panelHeader"));
header->setFixedHeight(kHeaderHeight);
geopro::app::applyThemedStyleSheet(header, headerQss());
auto* hlay = new QHBoxLayout(header);
hlay->setContentsMargins(10, 0, 8, 0);
hlay->setSpacing(2);
auto* stack = new QStackedWidget(box);
auto* group = new QButtonGroup(box);
group->setExclusive(true);
TabbedPanel result;
result.container = box;
for (int i = 0; i < tabs.size(); ++i) {
const PanelTab& t = tabs[i];
auto* btn = new ElaToolButton(header); // Fluent tab(选中态由 Ela checked 高亮)
btn->setObjectName(QStringLiteral("tabBtn"));
btn->setText(t.title);
btn->setIcon(makeGlyph(t.icon, QColor("#5A6B85"), kTabIcon));
btn->setIconSize(QSize(kTabIcon, kTabIcon));
btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
btn->setCheckable(true);
btn->setCursor(Qt::PointingHandCursor);
group->addButton(btn, i);
hlay->addWidget(btn);
QLabel* badge = nullptr;
if (t.hasBadge) {
badge = makeBadge(header);
hlay->addWidget(badge);
}
result.badges.append(badge);
stack->addWidget(t.content);
hlay->addSpacing(10);
}
hlay->addStretch();
for (const auto& a : actions) hlay->addWidget(makeActionButton(header, a));
QObject::connect(group, &QButtonGroup::idClicked, stack, &QStackedWidget::setCurrentIndex);
if (auto* first = group->button(0)) first->setChecked(true);
stack->setCurrentIndex(0);
v->addWidget(header);
v->addWidget(stack, 1);
return result;
}
} // namespace geopro::app