429 lines
11 KiB
C++
429 lines
11 KiB
C++
#include "Theme.hpp"
|
||
|
||
#include <QApplication>
|
||
#include <QColor>
|
||
#include <QFont>
|
||
#include <QPalette>
|
||
#include <QStyleFactory>
|
||
|
||
namespace geopro::app {
|
||
|
||
namespace {
|
||
|
||
// 全局样式表(浅色专业)。只描述外观,不含任何交互逻辑。
|
||
// 注意:刻意不重写 QCheckBox::indicator —— Fusion 一旦检测到 indicator 子控件被改写,
|
||
// 就需要自带勾选 image,否则勾选态会变成空白方块。这里交给 Fusion 原生绘制,
|
||
// 它会自动采用调色板的 Highlight(#2D6CB5) 作勾选色,省去打包图片资源。
|
||
const char* kStyleSheet = R"QSS(
|
||
/* ── 基础 ───────────────────────────────────────────────── */
|
||
QWidget {
|
||
color: #1F2A3D;
|
||
}
|
||
QMainWindow, QDialog {
|
||
background: #F4F6FA;
|
||
}
|
||
QToolTip {
|
||
background: #1F2A3D;
|
||
color: #F4F6FA;
|
||
border: 1px solid #2D6CB5;
|
||
border-radius: 4px;
|
||
padding: 4px 8px;
|
||
}
|
||
|
||
/* ── 视图内工具条(2D/3D、数据详情):白底分段控件,柔和不刺眼 ── */
|
||
QToolBar {
|
||
background: #FFFFFF;
|
||
border: none;
|
||
border-bottom: 1px solid #EAEEF4;
|
||
padding: 6px 8px;
|
||
spacing: 4px;
|
||
}
|
||
QToolBar QToolButton {
|
||
background: transparent;
|
||
color: #5A6B85;
|
||
border: none;
|
||
border-radius: 7px;
|
||
padding: 6px 14px;
|
||
font-weight: 500;
|
||
}
|
||
QToolBar QToolButton:hover {
|
||
background: #EEF3FB;
|
||
color: #1F2A3D;
|
||
}
|
||
QToolBar QToolButton:pressed {
|
||
background: #DCE9F8;
|
||
}
|
||
QToolBar QToolButton:checked {
|
||
background: #EAF1FB;
|
||
color: #2D6CB5;
|
||
font-weight: 600;
|
||
}
|
||
QToolBar QToolButton:checked:hover {
|
||
background: #DCE9F8;
|
||
}
|
||
QToolBar::separator {
|
||
background: #EAEEF4;
|
||
width: 1px;
|
||
margin: 6px 8px;
|
||
}
|
||
|
||
/* ── 树 / 列表:无边框(靠面板与留白分隔,去掉线框感)+ 充足行距 ── */
|
||
QTreeWidget, QListWidget, QTreeView, QListView {
|
||
background: #FFFFFF;
|
||
border: none;
|
||
padding: 6px;
|
||
outline: none;
|
||
}
|
||
QTreeWidget::item, QListWidget::item, QTreeView::item, QListView::item {
|
||
padding: 7px 8px;
|
||
border-radius: 6px;
|
||
margin: 1px 4px;
|
||
}
|
||
QTreeWidget::item:hover, QListWidget::item:hover,
|
||
QTreeView::item:hover, QListView::item:hover {
|
||
background: #EEF3FB;
|
||
}
|
||
QTreeWidget::item:selected, QListWidget::item:selected,
|
||
QTreeView::item:selected, QListView::item:selected {
|
||
background: #DCE9F8;
|
||
color: #1B3D67;
|
||
}
|
||
/* 注意:不要给 QTreeView::branch 设 background——一旦改写 branch,Qt 会停止绘制
|
||
默认的展开/折叠箭头(与 indicator 同类陷阱),父节点折叠图标会消失。 */
|
||
|
||
/* 表头(对象显示栏) */
|
||
QHeaderView::section {
|
||
background: #EDF1F7;
|
||
color: #3A475C;
|
||
border: none;
|
||
border-bottom: 1px solid #D5DBE5;
|
||
padding: 6px 8px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* ── 标签页(数据 / 文件):现代下划线 tab,无边框盒子 ──────── */
|
||
QTabWidget::pane {
|
||
border: none;
|
||
border-top: 1px solid #EAEEF4;
|
||
top: 0;
|
||
background: #FFFFFF;
|
||
}
|
||
QTabBar {
|
||
background: transparent;
|
||
}
|
||
QTabBar::tab {
|
||
background: transparent;
|
||
color: #5A6B85;
|
||
border: none;
|
||
border-bottom: 2px solid transparent;
|
||
padding: 8px 16px;
|
||
margin-right: 4px;
|
||
}
|
||
QTabBar::tab:selected {
|
||
color: #2D6CB5;
|
||
border-bottom: 2px solid #2D6CB5;
|
||
font-weight: 600;
|
||
}
|
||
QTabBar::tab:hover:!selected {
|
||
color: #1F2A3D;
|
||
}
|
||
|
||
/* ── 复选框(仅调间距/字色,indicator 交给 Fusion 原生)──── */
|
||
QCheckBox {
|
||
spacing: 7px;
|
||
color: #1F2A3D;
|
||
}
|
||
QCheckBox:disabled {
|
||
color: #9AA6B6;
|
||
}
|
||
|
||
/* ── 通用按钮 / 输入(登录窗内部各自再覆盖)────────────────── */
|
||
QPushButton {
|
||
background: #FFFFFF;
|
||
color: #1F2A3D;
|
||
border: 1px solid #C2CCDA;
|
||
border-radius: 6px;
|
||
padding: 6px 14px;
|
||
}
|
||
QPushButton:hover {
|
||
background: #EEF3FB;
|
||
border-color: #2D6CB5;
|
||
}
|
||
QPushButton:pressed {
|
||
background: #DCE9F8;
|
||
}
|
||
QPushButton:default {
|
||
background: #2D6CB5;
|
||
color: #FFFFFF;
|
||
border-color: #2D6CB5;
|
||
}
|
||
QPushButton:default:hover {
|
||
background: #2862A6;
|
||
}
|
||
QPushButton:disabled {
|
||
background: #F0F2F6;
|
||
color: #9AA6B6;
|
||
border-color: #DCE0E7;
|
||
}
|
||
QLineEdit {
|
||
background: #FFFFFF;
|
||
color: #1F2A3D;
|
||
border: 1px solid #C7D2E0;
|
||
border-radius: 6px;
|
||
padding: 5px 8px;
|
||
selection-background-color: #2D6CB5;
|
||
selection-color: #FFFFFF;
|
||
}
|
||
QLineEdit:focus {
|
||
border: 1px solid #2D6CB5;
|
||
}
|
||
QLineEdit:disabled {
|
||
background: #F0F2F6;
|
||
color: #8A93A3;
|
||
}
|
||
|
||
/* ── 滚动条:纤细现代(无需图片资源)───────────────────────── */
|
||
QScrollBar:vertical {
|
||
background: transparent;
|
||
width: 12px;
|
||
margin: 2px;
|
||
}
|
||
QScrollBar::handle:vertical {
|
||
background: #C2CCDA;
|
||
border-radius: 5px;
|
||
min-height: 28px;
|
||
}
|
||
QScrollBar::handle:vertical:hover {
|
||
background: #A7B4C7;
|
||
}
|
||
QScrollBar:horizontal {
|
||
background: transparent;
|
||
height: 12px;
|
||
margin: 2px;
|
||
}
|
||
QScrollBar::handle:horizontal {
|
||
background: #C2CCDA;
|
||
border-radius: 5px;
|
||
min-width: 28px;
|
||
}
|
||
QScrollBar::handle:horizontal:hover {
|
||
background: #A7B4C7;
|
||
}
|
||
QScrollBar::add-line, QScrollBar::sub-line {
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
QScrollBar::add-page, QScrollBar::sub-page {
|
||
background: transparent;
|
||
}
|
||
|
||
/* ── 分隔条:默认近乎隐形,悬停时才显淡色(去掉灰硬条)──────── */
|
||
QSplitter::handle {
|
||
background: #EAEEF4;
|
||
}
|
||
QSplitter::handle:hover {
|
||
background: #C7D2E0;
|
||
}
|
||
ads--CDockSplitter::handle {
|
||
background: #EAEEF4;
|
||
}
|
||
ads--CDockSplitter::handle:hover {
|
||
background: #C7D2E0;
|
||
}
|
||
|
||
/* ── 状态栏:底部信息条(坐标系 / 状态指示,常驻可见)──────── */
|
||
QStatusBar {
|
||
background: #FFFFFF;
|
||
color: #5A6B85;
|
||
border-top: 1px solid #EAEEF4;
|
||
}
|
||
QStatusBar::item {
|
||
border: none;
|
||
}
|
||
QStatusBar QLabel {
|
||
color: #5A6B85;
|
||
padding: 0 4px;
|
||
}
|
||
|
||
/* ── 菜单栏 / 菜单(按需出现时也与主题一致)────────────────── */
|
||
QMenuBar {
|
||
background: #EDF1F7;
|
||
color: #1F2A3D;
|
||
border-bottom: 1px solid #D5DBE5;
|
||
}
|
||
QMenuBar::item {
|
||
background: transparent;
|
||
padding: 5px 12px;
|
||
border-radius: 6px;
|
||
}
|
||
QMenuBar::item:selected {
|
||
background: #DCE6F4;
|
||
}
|
||
QMenu {
|
||
background: #FFFFFF;
|
||
color: #1F2A3D;
|
||
border: 1px solid #D5DBE5;
|
||
border-radius: 8px;
|
||
padding: 5px;
|
||
}
|
||
QMenu::item {
|
||
padding: 6px 24px 6px 14px;
|
||
border-radius: 5px;
|
||
}
|
||
QMenu::item:selected {
|
||
background: #DCE9F8;
|
||
color: #1B3D67;
|
||
}
|
||
QMenu::separator {
|
||
height: 1px;
|
||
background: #E1E6EE;
|
||
margin: 5px 8px;
|
||
}
|
||
|
||
/* ── 下拉框(按需出现时也与主题一致)──────────────────────── */
|
||
QComboBox {
|
||
background: #FFFFFF;
|
||
color: #1F2A3D;
|
||
border: 1px solid #C2CCDA;
|
||
border-radius: 6px;
|
||
padding: 5px 10px;
|
||
min-height: 18px;
|
||
}
|
||
QComboBox:hover {
|
||
border-color: #2D6CB5;
|
||
}
|
||
QComboBox:focus {
|
||
border-color: #2D6CB5;
|
||
}
|
||
QComboBox::drop-down {
|
||
border: none;
|
||
width: 22px;
|
||
}
|
||
QComboBox QAbstractItemView {
|
||
background: #FFFFFF;
|
||
border: 1px solid #D5DBE5;
|
||
border-radius: 6px;
|
||
selection-background-color: #DCE9F8;
|
||
selection-color: #1B3D67;
|
||
outline: none;
|
||
}
|
||
|
||
/* ── 分组框(按需出现时也与主题一致)──────────────────────── */
|
||
QGroupBox {
|
||
border: 1px solid #D5DBE5;
|
||
border-radius: 8px;
|
||
margin-top: 10px;
|
||
padding-top: 6px;
|
||
font-weight: 600;
|
||
}
|
||
QGroupBox::title {
|
||
subcontrol-origin: margin;
|
||
left: 12px;
|
||
padding: 0 4px;
|
||
color: #3A475C;
|
||
}
|
||
|
||
/* ── 进度条(长任务反馈,遵循 Doherty 阈值)──────────────────── */
|
||
QProgressBar {
|
||
background: #E6EBF3;
|
||
border: none;
|
||
border-radius: 5px;
|
||
height: 8px;
|
||
text-align: center;
|
||
color: #5A6B85;
|
||
}
|
||
QProgressBar::chunk {
|
||
background: #2D6CB5;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
/* ── ADS 停靠:标题栏做成「固定面板表头」(对齐原型)──────────────
|
||
面板已锁定(无关闭/浮动/拖动),每个区只一个标签即表头:统一浅色头 +
|
||
蓝色下划线强调 + 深色加粗标题。各区一致,读起来像固定子窗口表头。 */
|
||
ads--CDockAreaWidget {
|
||
background: #F4F6FA;
|
||
}
|
||
ads--CDockAreaTitleBar {
|
||
background: #EDF1F7;
|
||
border-bottom: 1px solid #D5DBE5;
|
||
padding: 0;
|
||
}
|
||
ads--CDockWidgetTab {
|
||
background: #EDF1F7;
|
||
border: none;
|
||
border-bottom: 2px solid transparent;
|
||
padding: 7px 12px;
|
||
min-height: 22px;
|
||
}
|
||
ads--CDockWidgetTab[activeTab="true"] {
|
||
background: #EDF1F7;
|
||
border-bottom: 2px solid #2D6CB5;
|
||
}
|
||
ads--CDockWidgetTab QLabel {
|
||
color: #5A6B85;
|
||
font-weight: 600;
|
||
}
|
||
ads--CDockWidgetTab[activeTab="true"] QLabel {
|
||
color: #1F2A3D;
|
||
font-weight: 600;
|
||
}
|
||
)QSS";
|
||
|
||
// 浅色专业调色板:让标准控件在无 QSS 覆盖处也保持一致底色/选中色。
|
||
QPalette buildPalette()
|
||
{
|
||
QPalette p;
|
||
const QColor shell("#F4F6FA");
|
||
const QColor panel("#FFFFFF");
|
||
const QColor text("#1F2A3D");
|
||
const QColor mutedText("#5A6B85");
|
||
const QColor accent("#2D6CB5");
|
||
|
||
p.setColor(QPalette::Window, shell);
|
||
p.setColor(QPalette::WindowText, text);
|
||
p.setColor(QPalette::Base, panel);
|
||
p.setColor(QPalette::AlternateBase, QColor("#F0F3F8"));
|
||
p.setColor(QPalette::Text, text);
|
||
p.setColor(QPalette::Button, QColor("#EDF1F7"));
|
||
p.setColor(QPalette::ButtonText, text);
|
||
p.setColor(QPalette::ToolTipBase, QColor("#1F2A3D"));
|
||
p.setColor(QPalette::ToolTipText, shell);
|
||
p.setColor(QPalette::Highlight, accent);
|
||
p.setColor(QPalette::HighlightedText, panel);
|
||
p.setColor(QPalette::PlaceholderText, mutedText);
|
||
p.setColor(QPalette::Link, accent);
|
||
|
||
// 关键:把 Fusion 用于绘制 3D 凹凸(斜角/凹槽/分隔条阴影)的明暗角色统一压成相近浅灰,
|
||
// 立体效果即塌成平面。ADS 分隔条用 palette(dark),这样也变成一条扁平浅灰细线(无 3D)。
|
||
p.setColor(QPalette::Light, QColor("#FFFFFF"));
|
||
p.setColor(QPalette::Midlight, QColor("#EEF1F5"));
|
||
p.setColor(QPalette::Mid, QColor("#E1E6EE"));
|
||
p.setColor(QPalette::Dark, QColor("#D7DEE8"));
|
||
p.setColor(QPalette::Shadow, QColor("#D7DEE8"));
|
||
|
||
// 禁用态:统一灰化,避免 Fusion 默认禁用色偏暗看不清。
|
||
p.setColor(QPalette::Disabled, QPalette::Text, QColor("#9AA6B6"));
|
||
p.setColor(QPalette::Disabled, QPalette::WindowText, QColor("#9AA6B6"));
|
||
p.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#9AA6B6"));
|
||
return p;
|
||
}
|
||
|
||
} // namespace
|
||
|
||
void applyTheme(QApplication& app)
|
||
{
|
||
// Fusion:跨平台一致且对 QSS 友好(Windows 原生风对部分控件会忽略样式表)。
|
||
app.setStyle(QStyleFactory::create(QStringLiteral("Fusion")));
|
||
|
||
// 基础字体:中文界面用 微软雅黑 UI 渲染最清爽;缺失时 Qt 自动回退。
|
||
// 10pt(≈13px)对齐主流商用客户端基准;9pt 偏小显拥挤。抗锯齿优先,观感更精致。
|
||
QFont base(QStringLiteral("Microsoft YaHei UI"), 10);
|
||
base.setStyleStrategy(QFont::PreferAntialias);
|
||
app.setFont(base);
|
||
|
||
app.setPalette(buildPalette());
|
||
app.setStyleSheet(QString::fromUtf8(kStyleSheet));
|
||
}
|
||
|
||
} // namespace geopro::app
|