152 lines
4.9 KiB
C++
152 lines
4.9 KiB
C++
#include "PanelHeader.hpp"
|
|
|
|
#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 表头共用)。
|
|
const char* kHeaderQss =
|
|
"#panelHeader { background:#FFFFFF; border-bottom:1px solid #E6EAF1; }"
|
|
"#panelTitle { color:#1F2A3D; font-size:14px; font-weight:600; }"
|
|
"#panelBadge { background:#EAEEF5; color:#5A6B85; border-radius:9px;"
|
|
" padding:1px 7px; font-size:12px; font-weight:600; }"
|
|
"QToolButton#panelAction { border:none; border-radius:7px; padding:5px; }"
|
|
"QToolButton#panelAction:hover { background:#EEF3FB; }"
|
|
"QToolButton#tabBtn { border:none; border-bottom:2px solid transparent; color:#5A6B85;"
|
|
" padding:8px 4px; font-size:14px; }"
|
|
"QToolButton#tabBtn:hover { color:#1F2A3D; }"
|
|
"QToolButton#tabBtn:checked { color:#1F2A3D; font-weight:600;"
|
|
" border-bottom:2px solid #2D6CB5; }";
|
|
|
|
// 数量徽标(默认隐藏,调用方 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;
|
|
}
|
|
|
|
// 表头操作按钮(静态占位)。
|
|
QToolButton* makeActionButton(QWidget* parent, const HeaderAction& a)
|
|
{
|
|
auto* btn = new QToolButton(parent);
|
|
btn->setObjectName(QStringLiteral("panelAction"));
|
|
btn->setIcon(makeGlyph(a.first, QColor("#5A6B85"), kActionIcon));
|
|
btn->setIconSize(QSize(kActionIcon, kActionIcon));
|
|
btn->setCursor(Qt::PointingHandCursor);
|
|
btn->setToolTip(a.second + QStringLiteral("(占位)"));
|
|
btn->setAutoRaise(true);
|
|
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);
|
|
header->setStyleSheet(QString::fromUtf8(kHeaderQss));
|
|
|
|
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);
|
|
header->setStyleSheet(QString::fromUtf8(kHeaderQss));
|
|
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 QToolButton(header);
|
|
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);
|
|
btn->setAutoRaise(true);
|
|
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
|