feat(theme): 语义令牌基础设施(令牌表+token/fillTokens API,规范§1)
This commit is contained in:
parent
0edfa56ec6
commit
18d084047f
|
|
@ -28,6 +28,63 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── 语义令牌表(全 UI 唯一颜色来源)。改色只改这一处。 ──────────────────
|
||||||
|
// 取值来源:规范 §1.5 语义映射 + 附录 A 速查 + §1.3 画布专用色。
|
||||||
|
// 画布(canvas/*)与 bg/canvas 两模式同值——规范 §0.5「视图区永远深色」。
|
||||||
|
struct Token { const char* name; const char* light; const char* dark; };
|
||||||
|
const Token kTokens[] = {
|
||||||
|
// 背景
|
||||||
|
{"bg/app", "#F7F8FA", "#0E1116"},
|
||||||
|
{"bg/panel", "#FFFFFF", "#161A20"},
|
||||||
|
{"bg/panel-subtle", "#FCFCFD", "#161B22"},
|
||||||
|
{"bg/header", "#FFFFFF", "#12161C"},
|
||||||
|
{"bg/hover", "#EFF1F4", "#1B2129"},
|
||||||
|
{"bg/selected", "#EFF5FF", "#16243F"},
|
||||||
|
{"bg/canvas", "#0B1320", "#0B1320"},
|
||||||
|
// 边框
|
||||||
|
{"border/default", "#E3E6EB", "#262C35"},
|
||||||
|
{"border/strong", "#CDD2DA", "#333B45"},
|
||||||
|
{"border/focus", "#3B73EC", "#5E8DF5"},
|
||||||
|
// 文字
|
||||||
|
{"text/primary", "#272C35", "#E6E9EF"},
|
||||||
|
{"text/secondary", "#5A626F", "#A4ADBB"},
|
||||||
|
{"text/tertiary", "#7C8493", "#7A8494"},
|
||||||
|
{"text/disabled", "#A8AFBC", "#5A626F"},
|
||||||
|
{"text/link", "#3B73EC", "#5E8DF5"},
|
||||||
|
{"text/on-primary", "#FFFFFF", "#FFFFFF"},
|
||||||
|
// 强调
|
||||||
|
{"accent/primary", "#3B73EC", "#5E8DF5"},
|
||||||
|
{"accent/primary-hover", "#2B5FD9", "#93B4FA"},
|
||||||
|
{"accent/primary-pressed","#2450B8", "#3B73EC"},
|
||||||
|
// 其他
|
||||||
|
{"divider", "#E3E6EB", "#22272F"},
|
||||||
|
{"scrollbar/thumb", "#CDD2DA", "#3A424D"},
|
||||||
|
{"scrollbar/thumb-hover", "#A8AFBC", "#4A535F"},
|
||||||
|
// 状态色(主色 + 浅底)规范 §1.4
|
||||||
|
{"status/danger", "#E5484D", "#FF6166"},
|
||||||
|
{"status/danger-bg", "#FDECEC", "#3A1D1F"},
|
||||||
|
{"status/warning", "#E08A1E", "#F5A623"},
|
||||||
|
{"status/warning-bg", "#FBF0DD", "#3A2C12"},
|
||||||
|
{"status/success", "#2E9E5B", "#46C07A"},
|
||||||
|
{"status/success-bg", "#E7F6ED", "#16301F"},
|
||||||
|
{"status/info", "#3B73EC", "#5E8DF5"},
|
||||||
|
{"status/info-bg", "#EFF5FF", "#16243F"},
|
||||||
|
{"status/neutral", "#7C8493", "#8A93A3"},
|
||||||
|
// 画布专用(两模式同值)规范 §1.3
|
||||||
|
{"canvas/bg", "#0B1320", "#0B1320"},
|
||||||
|
{"canvas/bg-soft", "#111B2D", "#111B2D"},
|
||||||
|
{"canvas/grid", "#1E2A3D", "#1E2A3D"},
|
||||||
|
{"canvas/text", "#E6ECF5", "#E6ECF5"},
|
||||||
|
{"canvas/text-dim", "#8A97AC", "#8A97AC"},
|
||||||
|
};
|
||||||
|
|
||||||
|
QString tokenHex(const char* name, bool dark)
|
||||||
|
{
|
||||||
|
for (const auto& t : kTokens)
|
||||||
|
if (qstrcmp(t.name, name) == 0) return QString::fromLatin1(dark ? t.dark : t.light);
|
||||||
|
return QStringLiteral("#FF00FF"); // 漏配的令牌显眼品红,便于一眼发现
|
||||||
|
}
|
||||||
|
|
||||||
// 全局样式表(浅色专业)。只描述外观,不含任何交互逻辑。
|
// 全局样式表(浅色专业)。只描述外观,不含任何交互逻辑。
|
||||||
// 注意:刻意不重写 QCheckBox::indicator —— Fusion 一旦检测到 indicator 子控件被改写,
|
// 注意:刻意不重写 QCheckBox::indicator —— Fusion 一旦检测到 indicator 子控件被改写,
|
||||||
// 就需要自带勾选 image,否则勾选态会变成空白方块。这里交给 Fusion 原生绘制,
|
// 就需要自带勾选 image,否则勾选态会变成空白方块。这里交给 Fusion 原生绘制,
|
||||||
|
|
@ -625,4 +682,26 @@ void applyThemedStyleSheet(QWidget* w, const QString& designQss)
|
||||||
[w, designQss]() { w->setStyleSheet(themedQss(designQss, isDarkTheme())); });
|
[w, designQss]() { w->setStyleSheet(themedQss(designQss, isDarkTheme())); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString token(const char* name) { return tokenHex(name, isDarkTheme()); }
|
||||||
|
|
||||||
|
QColor tokenColor(const char* name) { return QColor(token(name)); }
|
||||||
|
|
||||||
|
QString fillTokens(const QString& tmpl)
|
||||||
|
{
|
||||||
|
const bool dark = isDarkTheme();
|
||||||
|
QString s = tmpl;
|
||||||
|
for (const auto& t : kTokens)
|
||||||
|
s.replace(QStringLiteral("{{%1}}").arg(QLatin1String(t.name)),
|
||||||
|
QString::fromLatin1(dark ? t.dark : t.light));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyTokenizedStyleSheet(QWidget* w, const QString& tmpl)
|
||||||
|
{
|
||||||
|
if (!w) return;
|
||||||
|
w->setStyleSheet(fillTokens(tmpl));
|
||||||
|
QObject::connect(&ThemeManager::instance(), &ThemeManager::changed, w,
|
||||||
|
[w, tmpl]() { w->setStyleSheet(fillTokens(tmpl)); });
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
// 文字 #1F2A3D 次要文字 #5A6B85 边框 #D5DBE5 强边框 #C2CCDA
|
// 文字 #1F2A3D 次要文字 #5A6B85 边框 #D5DBE5 强边框 #C2CCDA
|
||||||
// 危险 #C0392B
|
// 危险 #C0392B
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
|
@ -136,4 +137,15 @@ void applyThemedStyleSheet(QWidget* w, const QString& designQss);
|
||||||
// 如 ADS dockManager 在其自带样式后追加规则)。不自动随主题切换,调用方需自行在切换时重取。
|
// 如 ADS dockManager 在其自带样式后追加规则)。不自动随主题切换,调用方需自行在切换时重取。
|
||||||
QString themed(const QString& designQss);
|
QString themed(const QString& designQss);
|
||||||
|
|
||||||
|
// ── 语义令牌(单一事实来源,取值见 Theme.cpp kTokens;规范 §1.5 + 附录 A + §1.3)──
|
||||||
|
// 组件只引语义 token,禁止散落硬编码 hex。token 名形如 "bg/panel"、"accent/primary"。
|
||||||
|
QString token(const char* name); // 当前明暗下的 hex(未知名返回品红 "#FF00FF" 以便一眼发现漏配)
|
||||||
|
QColor tokenColor(const char* name); // 同上,QColor 形式
|
||||||
|
|
||||||
|
// 把 QSS 模板里的 {{token}} 占位替换为当前明暗的 hex 后返回。
|
||||||
|
QString fillTokens(const QString& tmpl);
|
||||||
|
|
||||||
|
// 应用一段 {{token}} 模板 QSS 到 widget,并随主题切换自动重填。
|
||||||
|
void applyTokenizedStyleSheet(QWidget* w, const QString& tmpl);
|
||||||
|
|
||||||
} // namespace geopro::app
|
} // namespace geopro::app
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue