initial commit, functinal software

This commit is contained in:
ykcheungab
2026-09-06 21:57:50 +08:00
commit e2d5e69229
78 changed files with 5407 additions and 0 deletions
@@ -0,0 +1,5 @@
"""Theme helpers."""
from orisys_app_shared.theme.qss import build_qss, clear_theme_cache, color, load_colors
__all__ = ["build_qss", "clear_theme_cache", "color", "load_colors"]
@@ -0,0 +1,23 @@
{
"window_bg": "#121316",
"panel_bg": "#1a1c20",
"panel_border": "#2a2d33",
"text_primary": "#e8eaed",
"text_secondary": "#9aa0a6",
"accent": "#536dce",
"accent_hover": "#6b82d9",
"button_bg": "#2a2d33",
"button_hover": "#3a3f47",
"input_bg": "#0f1012",
"input_border": "#3a3f47",
"menu_bg": "#1a1c20",
"menu_hover": "#2a2d33",
"plot_fn": "#8ab4f8",
"plot_fx": "#34a853",
"plot_fy": "#fbbc04",
"plot_bg": "#121316",
"plot_grid": "#2a2d33",
"arrow_canvas": "#121316",
"danger": "#ea4335",
"success": "#34a853"
}
@@ -0,0 +1,23 @@
{
"window_bg": "#f5f6f8",
"panel_bg": "#ffffff",
"panel_border": "#d0d4dc",
"text_primary": "#1a1c20",
"text_secondary": "#5f6368",
"accent": "#536dce",
"accent_hover": "#3f56b5",
"button_bg": "#e8eaed",
"button_hover": "#d0d4dc",
"input_bg": "#ffffff",
"input_border": "#c0c4cc",
"menu_bg": "#ffffff",
"menu_hover": "#e8eaed",
"plot_fn": "#1a73e8",
"plot_fx": "#188038",
"plot_fy": "#f9ab00",
"plot_bg": "#ffffff",
"plot_grid": "#e0e3e8",
"arrow_canvas": "#eef0f3",
"danger": "#d93025",
"success": "#188038"
}
+105
View File
@@ -0,0 +1,105 @@
"""Build Qt stylesheets from theme color token JSON (no hex in widgets)."""
from __future__ import annotations
import json
from functools import lru_cache
from pathlib import Path
def _theme_dir() -> Path:
return Path(__file__).resolve().parent
@lru_cache(maxsize=4)
def load_colors(theme: str = "dark") -> dict[str, str]:
name = "colors_dark.json" if theme != "light" else "colors_light.json"
path = _theme_dir() / name
data = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(data, dict):
raise ValueError(f"Invalid theme file: {path}")
return {str(k): str(v) for k, v in data.items()}
def build_qss(theme: str = "dark") -> str:
c = load_colors(theme)
return f"""
QWidget {{
background-color: {c['window_bg']};
color: {c['text_primary']};
font-family: "Microsoft YaHei", "Segoe UI", sans-serif;
font-size: 13px;
}}
QMainWindow, QDialog {{
background-color: {c['window_bg']};
}}
QMenuBar {{
background-color: {c['menu_bg']};
color: {c['text_primary']};
border-bottom: 1px solid {c['panel_border']};
}}
QMenuBar::item:selected {{
background-color: {c['menu_hover']};
}}
QMenu {{
background-color: {c['menu_bg']};
color: {c['text_primary']};
border: 1px solid {c['panel_border']};
}}
QMenu::item:selected {{
background-color: {c['menu_hover']};
}}
QToolBar {{
background-color: {c['panel_bg']};
border-bottom: 1px solid {c['panel_border']};
spacing: 8px;
padding: 4px;
}}
QPushButton {{
background-color: {c['button_bg']};
color: {c['text_primary']};
border: 1px solid {c['panel_border']};
border-radius: 4px;
padding: 6px 12px;
}}
QPushButton:hover {{
background-color: {c['button_hover']};
}}
QPushButton:disabled {{
color: {c['text_secondary']};
}}
QComboBox, QLineEdit, QSpinBox {{
background-color: {c['input_bg']};
color: {c['text_primary']};
border: 1px solid {c['input_border']};
border-radius: 4px;
padding: 4px 8px;
min-height: 24px;
}}
QLabel#panelTitle {{
color: {c['text_secondary']};
font-weight: 600;
}}
QLabel#panelMeta {{
color: {c['text_secondary']};
font-weight: 500;
padding-right: 8px;
}}
QFrame#contentPanel {{
background-color: {c['panel_bg']};
border: 1px solid {c['panel_border']};
border-radius: 6px;
}}
QStatusBar {{
background-color: {c['panel_bg']};
color: {c['text_secondary']};
}}
"""
def color(theme: str, key: str, default: str = "#888888") -> str:
return load_colors(theme).get(key, default)
def clear_theme_cache() -> None:
load_colors.cache_clear()