From b242240df6f0c7254ba9a40e85f9376dede4050a Mon Sep 17 00:00:00 2001 From: gaozheng Date: Wed, 10 Jun 2026 15:29:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(theme):=20=E5=85=A8=E5=B1=80=20QSS=20?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=8C=96=20+=20palette=20=E4=BB=8E=E4=BB=A4?= =?UTF-8?q?=E7=89=8C=EF=BC=8C=E6=A0=87=E5=87=86=E6=8E=A7=E4=BB=B6=E5=AF=B9?= =?UTF-8?q?=E9=BD=90=E8=A7=84=E8=8C=83=E8=89=B2=E5=80=BC=EF=BC=88=C2=A71/?= =?UTF-8?q?=C2=A73/=C2=A76/=C2=A77=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/Theme.cpp | 219 +++++++++++++++++++++++----------------------- 1 file changed, 110 insertions(+), 109 deletions(-) diff --git a/src/app/Theme.cpp b/src/app/Theme.cpp index e052f7f..0a15e91 100644 --- a/src/app/Theme.cpp +++ b/src/app/Theme.cpp @@ -88,57 +88,57 @@ QString tokenHex(const char* name, bool dark) // 全局样式表(浅色专业)。只描述外观,不含任何交互逻辑。 // 注意:刻意不重写 QCheckBox::indicator —— Fusion 一旦检测到 indicator 子控件被改写, // 就需要自带勾选 image,否则勾选态会变成空白方块。这里交给 Fusion 原生绘制, -// 它会自动采用调色板的 Highlight(#2D6CB5) 作勾选色,省去打包图片资源。 +// 它会自动采用调色板的 Highlight(accent/primary) 作勾选色,省去打包图片资源。 const char* kStyleSheet = R"QSS( /* ── 基础 ───────────────────────────────────────────────── */ QWidget { - color: #1F2A3D; + color: {{text/primary}}; } QMainWindow, QDialog { - background: #F4F6FA; + background: {{bg/app}}; } /* QToolTip 不写 QSS:用系统原生工具提示(自定义 QSS 会让弹窗圆角露直角、且不像原生)。 */ /* ── 视图内工具条(2D/3D、数据详情):白底分段控件,柔和不刺眼 ── */ QToolBar { - background: #FFFFFF; + background: {{bg/panel}}; border: none; - border-bottom: 1px solid #EAEEF4; + border-bottom: 1px solid {{divider}}; padding: 6px 8px; spacing: 4px; } QToolBar QToolButton { background: transparent; - color: #5A6B85; + color: {{text/secondary}}; border: none; border-radius: 8px; padding: 6px 14px; font-weight: 500; } QToolBar QToolButton:hover { - background: #EEF3FB; - color: #1F2A3D; + background: {{bg/hover}}; + color: {{text/primary}}; } QToolBar QToolButton:pressed { - background: #DCE9F8; + background: {{bg/selected}}; } QToolBar QToolButton:checked { - background: #EAF1FB; - color: #2D6CB5; + background: {{bg/hover}}; + color: {{accent/primary}}; font-weight: 600; } QToolBar QToolButton:checked:hover { - background: #DCE9F8; + background: {{bg/selected}}; } QToolBar::separator { - background: #EAEEF4; + background: {{divider}}; width: 1px; margin: 6px 8px; } /* ── 树 / 列表:无边框(靠面板与留白分隔,去掉线框感)+ 充足行距 ── */ QTreeWidget, QListWidget, QTreeView, QListView { - background: #FFFFFF; + background: {{bg/panel}}; border: none; padding: 6px; outline: none; @@ -148,22 +148,22 @@ QTreeWidget::item, QListWidget::item, QTreeView::item, QListView::item { } QTreeWidget::item:hover, QListWidget::item:hover, QTreeView::item:hover, QListView::item:hover { - background: #EEF3FB; + background: {{bg/hover}}; } QTreeWidget::item:selected, QListWidget::item:selected, QTreeView::item:selected, QListView::item:selected { - background: #DCE9F8; - color: #1B3D67; + background: {{bg/selected}}; + color: {{text/primary}}; } /* 注意:不要给 QTreeView::branch 设 background——一旦改写 branch,Qt 会停止绘制 默认的展开/折叠箭头(与 indicator 同类陷阱),父节点折叠图标会消失。 */ /* 表头(对象显示栏) */ QHeaderView::section { - background: #EDF1F7; - color: #3A475C; + background: {{bg/hover}}; + color: {{text/secondary}}; border: none; - border-bottom: 1px solid #D5DBE5; + border-bottom: 1px solid {{border/default}}; padding: 6px 8px; font-weight: 600; } @@ -171,82 +171,82 @@ QHeaderView::section { /* ── 标签页(数据 / 文件):现代下划线 tab,无边框盒子 ──────── */ QTabWidget::pane { border: none; - border-top: 1px solid #EAEEF4; + border-top: 1px solid {{divider}}; top: 0; - background: #FFFFFF; + background: {{bg/panel}}; } QTabBar { background: transparent; } QTabBar::tab { background: transparent; - color: #5A6B85; + color: {{text/secondary}}; border: none; border-bottom: 2px solid transparent; padding: 8px 16px; margin-right: 4px; } QTabBar::tab:selected { - color: #2D6CB5; - border-bottom: 2px solid #2D6CB5; + color: {{accent/primary}}; + border-bottom: 2px solid {{accent/primary}}; font-weight: 600; } QTabBar::tab:hover:!selected { - color: #1F2A3D; + color: {{text/primary}}; } /* ── 复选框(仅调间距/字色,indicator 交给 Fusion 原生)──── */ QCheckBox { spacing: 7px; - color: #1F2A3D; + color: {{text/primary}}; } QCheckBox:disabled { - color: #9AA6B6; + color: {{text/disabled}}; } /* ── 通用按钮 / 输入(登录窗内部各自再覆盖)────────────────── */ QPushButton { - background: #FFFFFF; - color: #1F2A3D; - border: 1px solid #C2CCDA; + background: {{bg/panel}}; + color: {{text/primary}}; + border: 1px solid {{border/strong}}; border-radius: 6px; padding: 6px 14px; } QPushButton:hover { - background: #EEF3FB; - border-color: #2D6CB5; + background: {{bg/hover}}; + border-color: {{accent/primary}}; } QPushButton:pressed { - background: #DCE9F8; + background: {{bg/selected}}; } QPushButton:default { - background: #2D6CB5; - color: #FFFFFF; - border-color: #2D6CB5; + background: {{accent/primary}}; + color: {{text/on-primary}}; + border-color: {{accent/primary}}; } QPushButton:default:hover { - background: #2862A6; + background: {{accent/primary-hover}}; } QPushButton:disabled { - background: #F0F2F6; - color: #9AA6B6; - border-color: #DCE0E7; + background: {{bg/app}}; + color: {{text/disabled}}; + border-color: {{border/default}}; } QLineEdit { - background: #FFFFFF; - color: #1F2A3D; - border: 1px solid #C7D2E0; + background: {{bg/panel}}; + color: {{text/primary}}; + border: 1px solid {{border/strong}}; border-radius: 6px; padding: 6px 8px; - selection-background-color: #2D6CB5; - selection-color: #FFFFFF; + selection-background-color: {{accent/primary}}; + selection-color: {{text/on-primary}}; } QLineEdit:focus { - border: 1px solid #2D6CB5; + border: 1px solid {{accent/primary}}; } QLineEdit:disabled { - background: #F0F2F6; - color: #8A93A3; + background: {{bg/app}}; + color: {{text/disabled}}; } /* ── 滚动条:纤细现代(无需图片资源)───────────────────────── */ @@ -256,12 +256,12 @@ QScrollBar:vertical { margin: 2px; } QScrollBar::handle:vertical { - background: #C2CCDA; + background: {{scrollbar/thumb}}; border-radius: 6px; min-height: 28px; } QScrollBar::handle:vertical:hover { - background: #A7B4C7; + background: {{scrollbar/thumb-hover}}; } QScrollBar:horizontal { background: transparent; @@ -269,12 +269,12 @@ QScrollBar:horizontal { margin: 2px; } QScrollBar::handle:horizontal { - background: #C2CCDA; + background: {{scrollbar/thumb}}; border-radius: 6px; min-width: 28px; } QScrollBar::handle:horizontal:hover { - background: #A7B4C7; + background: {{scrollbar/thumb-hover}}; } QScrollBar::add-line, QScrollBar::sub-line { width: 0; @@ -286,38 +286,38 @@ QScrollBar::add-page, QScrollBar::sub-page { /* ── 分隔条:默认近乎隐形,悬停时才显淡色(去掉灰硬条)──────── */ QSplitter::handle { - background: #EAEEF4; + background: {{divider}}; } QSplitter::handle:hover { - background: #C7D2E0; + background: {{accent/primary}}; } ads--CDockSplitter::handle { - background: #EAEEF4; + background: {{divider}}; } ads--CDockSplitter::handle:hover { - background: #C7D2E0; + background: {{accent/primary}}; } /* ── 状态栏:底部信息条(坐标系 / 状态指示,常驻可见)──────── */ QStatusBar { - background: #FFFFFF; - color: #5A6B85; - border-top: 1px solid #EAEEF4; + background: {{bg/panel}}; + color: {{text/secondary}}; + border-top: 1px solid {{divider}}; } QStatusBar::item { border: none; } QStatusBar QLabel { - color: #5A6B85; + color: {{text/secondary}}; padding: 0 4px; } /* ── 菜单栏 / 菜单(标准 QMenuBar/QMenu):刻意不设 border-radius——弹窗圆角靠系统(Win11 原生圆角),QSS 设圆角会露出后面的直角。仅设底/字/选中,干净不刺眼。 */ QMenuBar { - background: #FFFFFF; - color: #1F2A3D; - border-bottom: 1px solid #EEF1F5; + background: {{bg/panel}}; + color: {{text/primary}}; + border-bottom: 1px solid {{divider}}; padding: 2px 6px; } QMenuBar::item { @@ -326,16 +326,16 @@ QMenuBar::item { border-radius: 6px; } QMenuBar::item:selected { - background: #EAF1FB; - color: #2D6CB5; + background: {{bg/hover}}; + color: {{accent/primary}}; } QMenuBar::item:pressed { - background: #DCE6F4; + background: {{bg/selected}}; } QMenu { - background: #FFFFFF; - color: #1F2A3D; - border: 1px solid #D5DBE5; + background: {{bg/panel}}; + color: {{text/primary}}; + border: 1px solid {{border/default}}; padding: 4px; } QMenu::item { @@ -343,37 +343,37 @@ QMenu::item { border-radius: 6px; } QMenu::item:selected { - background: #EAF1FB; - color: #2D6CB5; + background: {{bg/hover}}; + color: {{accent/primary}}; } QMenu::separator { height: 1px; - background: #E1E6EE; + background: {{divider}}; margin: 4px 8px; } /* ── 下拉框(按需出现时也与主题一致)──────────────────────── */ QComboBox { - background: #FFFFFF; - color: #1F2A3D; - border: 1px solid #C2CCDA; + background: {{bg/panel}}; + color: {{text/primary}}; + border: 1px solid {{border/strong}}; border-radius: 6px; padding: 6px 10px; min-height: 18px; } QComboBox:hover { - border-color: #2D6CB5; + border-color: {{accent/primary}}; } QComboBox:focus { - border-color: #2D6CB5; + border-color: {{accent/primary}}; } QComboBox::drop-down { border: none; width: 22px; } QComboBox QAbstractItemView { - background: #FFFFFF; - border: 1px solid #D5DBE5; + background: {{bg/panel}}; + border: 1px solid {{border/default}}; outline: none; padding: 2px; } @@ -381,16 +381,16 @@ QComboBox QAbstractItemView::item { border: none; padding: 6px 10px; min-height: 20px; - color: #1F2A3D; + color: {{text/primary}}; } QComboBox QAbstractItemView::item:selected { - background: #EAF1FB; - color: #2D6CB5; + background: {{bg/hover}}; + color: {{accent/primary}}; } /* ── 分组框(按需出现时也与主题一致)──────────────────────── */ QGroupBox { - border: 1px solid #D5DBE5; + border: 1px solid {{border/default}}; border-radius: 8px; margin-top: 10px; padding-top: 6px; @@ -400,20 +400,20 @@ QGroupBox::title { subcontrol-origin: margin; left: 12px; padding: 0 4px; - color: #3A475C; + color: {{text/secondary}}; } /* ── 进度条(长任务反馈,遵循 Doherty 阈值)──────────────────── */ QProgressBar { - background: #E6EBF3; + background: {{divider}}; border: none; border-radius: 6px; height: 8px; text-align: center; - color: #5A6B85; + color: {{text/secondary}}; } QProgressBar::chunk { - background: #2D6CB5; + background: {{accent/primary}}; border-radius: 6px; } @@ -421,30 +421,30 @@ QProgressBar::chunk { 面板已锁定(无关闭/浮动/拖动),每个区只一个标签即表头:统一浅色头 + 蓝色下划线强调 + 深色加粗标题。各区一致,读起来像固定子窗口表头。 */ ads--CDockAreaWidget { - background: #F4F6FA; + background: {{bg/app}}; } ads--CDockAreaTitleBar { - background: #EDF1F7; - border-bottom: 1px solid #D5DBE5; + background: {{bg/hover}}; + border-bottom: 1px solid {{border/default}}; padding: 0; } ads--CDockWidgetTab { - background: #EDF1F7; + background: {{bg/hover}}; border: none; border-bottom: 2px solid transparent; padding: 7px 12px; min-height: 22px; } ads--CDockWidgetTab[activeTab="true"] { - background: #EDF1F7; - border-bottom: 2px solid #2D6CB5; + background: {{bg/hover}}; + border-bottom: 2px solid {{accent/primary}}; } ads--CDockWidgetTab QLabel { - color: #5A6B85; + color: {{text/secondary}}; font-weight: 600; } ads--CDockWidgetTab[activeTab="true"] QLabel { - color: #1F2A3D; + color: {{text/primary}}; font-weight: 600; } )QSS"; @@ -504,34 +504,35 @@ QString themedQss(const QString& designQss, bool dark) } // 当前模式的全局 QSS。 -QString styleSheetForMode(bool dark) +QString styleSheetForMode(bool /*dark*/) { - return themedQss(QString::fromUtf8(kStyleSheet), dark); + return fillTokens(QString::fromUtf8(kStyleSheet)); } // 调色板同样取自 ElaTheme,让无 QSS 覆盖处的标准控件也与外壳一致。 QPalette buildPalette(bool dark) { QPalette p; - const QColor shell = roleColor(dark, "#F4F6FA"); - const QColor panel = roleColor(dark, "#FFFFFF"); - const QColor text = roleColor(dark, "#1F2A3D"); - const QColor muted = roleColor(dark, "#5A6B85"); - const QColor accent = roleColor(dark, "#2D6CB5"); - const QColor border = roleColor(dark, "#D5DBE5"); - const QColor disabled = roleColor(dark, "#9AA6B6"); + const QColor shell = QColor(tokenHex("bg/app", dark)); + const QColor panel = QColor(tokenHex("bg/panel", dark)); + const QColor text = QColor(tokenHex("text/primary", dark)); + const QColor muted = QColor(tokenHex("text/secondary", dark)); + const QColor accent = QColor(tokenHex("accent/primary", dark)); + const QColor border = QColor(tokenHex("border/default", dark)); + const QColor disabled = QColor(tokenHex("text/disabled", dark)); + const QColor hoverBg = QColor(tokenHex("bg/hover", dark)); p.setColor(QPalette::Window, shell); p.setColor(QPalette::WindowText, text); p.setColor(QPalette::Base, panel); - p.setColor(QPalette::AlternateBase, roleColor(dark, "#EDF1F7")); + p.setColor(QPalette::AlternateBase, QColor(tokenHex("bg/panel-subtle", dark))); p.setColor(QPalette::Text, text); - p.setColor(QPalette::Button, roleColor(dark, "#EDF1F7")); + p.setColor(QPalette::Button, hoverBg); p.setColor(QPalette::ButtonText, text); p.setColor(QPalette::ToolTipBase, text); - p.setColor(QPalette::ToolTipText, shell); + p.setColor(QPalette::ToolTipText, panel); p.setColor(QPalette::Highlight, accent); - p.setColor(QPalette::HighlightedText, panel); + p.setColor(QPalette::HighlightedText, QColor(tokenHex("text/on-primary", dark))); p.setColor(QPalette::PlaceholderText, muted); p.setColor(QPalette::Link, accent); // Fusion 的明暗 3D 角色统一压成边框色,立体效果塌成平面(去斜角/凹槽)。