style: centralize the GUI color palette in styles.py
Every color literal in the GUI moves into one palette module: ~200 grouped constants, a qcolor() helper (hue from the theme, alpha at the call site), and both QSS stylesheets become string.Templates fed by _palette() so a renamed constant fails loudly. Also retints: light background #d8e4fd -> #e2e7ee, banner indigo -> #a2b7e4, and the portrait dark theme adopts Catppuccin Macchiato. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+419
-93
@@ -1,8 +1,312 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from string import Template
|
||||
|
||||
THEME_ORIGINAL = "original"
|
||||
THEME_PORTRAIT = "portrait"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Color palette. Change values HERE to try a different look — the QSS below
|
||||
# and the widgets that import these use them everywhere. Every UPPERCASE
|
||||
# constant is exposed to the QSS templates as $lowercase_name (see _palette),
|
||||
# so no color literals live inside the stylesheets themselves.
|
||||
# Any value can be "transparent" (e.g. to hide a border or a fill).
|
||||
# string.Template ($name) instead of f-strings so the QSS braces stay literal.
|
||||
|
||||
# -- Light theme ------------------------------------------------------------
|
||||
BACKGROUND = "#e2e7ee"
|
||||
BANNER = "#a2b7e4"
|
||||
BANNER_TEXT = "#263043" # must contrast with BANNER
|
||||
TEXT = "#263043"
|
||||
SURFACE = "#f2f2f2" # input fields, cards, group boxes
|
||||
|
||||
# Borders (all can be "transparent" to hide the line):
|
||||
BORDER = "transparent" # main dividers, e.g. the beamline state bar top line
|
||||
CARD_BORDER = "transparent" # cards / group boxes (Local Contact, automation)
|
||||
COMPACT_BORDER = "transparent" # compact-automation cards and buttons
|
||||
|
||||
# Compact-automation page:
|
||||
COMPACT_CARD_BG = "#e6eefc"
|
||||
COMPACT_TITLE = "#17324d" # section titles + menu/secondary button text
|
||||
COMPACT_HINT = "#51657d" # secondary text: hints, queue titles
|
||||
COMPACT_VALUE = "#10263a"
|
||||
COMPACT_MENU_BG = "#cbdcf8"
|
||||
COMPACT_MENU_BG_HOVER = "#bfd4f6"
|
||||
PRIMARY = "#2563eb" # main action button
|
||||
PRIMARY_HOVER = "#1d4ed8"
|
||||
PRIMARY_TEXT = "white"
|
||||
SECONDARY_BG = "#dfe9fb"
|
||||
SECONDARY_BG_HOVER = "#d3e1f8"
|
||||
|
||||
# Alert banners (alertKind: error / success / waiting=warning):
|
||||
ERROR_BG = "#fbe4e6"
|
||||
ERROR_BORDER = "#d97a84"
|
||||
ERROR_TEXT = "#8f1d2c"
|
||||
SUCCESS_BG = "#e7f6ea"
|
||||
SUCCESS_BORDER = "#7bbf8e"
|
||||
SUCCESS_TEXT = "#1f6a3a"
|
||||
WARNING_BG = "#fff8e1"
|
||||
WARNING_BORDER = "#ffb300"
|
||||
WARNING_TEXT = "#e65100"
|
||||
|
||||
# Axis video status + beamline state bar:
|
||||
STATUS_IDLE_BG = "#d9e2f2"
|
||||
STATUS_LABEL_TEXT = "#2f3b52"
|
||||
STATE_TOGGLE_TEXT = "white" # collapse glyph sitting on the BANNER strip
|
||||
STATE_CURRENT_TEXT = "#1e293b" # same slate as HEADING_TEXT, separate knob
|
||||
STATE_TELL_TEXT = "#374357" # also the status-bar TELL line
|
||||
|
||||
# -- Portrait (dark) theme: Catppuccin Macchiato ----------------------------
|
||||
# https://catppuccin.com/palette — token names in comments. DARK_BG was set to
|
||||
# Macchiato mantle by hand, so the rest follows that flavor.
|
||||
DARK_BG = "#1e2030" # mantle
|
||||
DARK_TEXT = "#cad3f5" # text
|
||||
DARK_SURFACE = "#24273a" # base — cards, state panel, scrollbar track
|
||||
DARK_ELEVATED = "#363a4f" # surface0 — buttons, title strip, idle status pill
|
||||
DARK_BORDER = "#494d64" # surface1 — card borders, scrollbar handle, button hover fill
|
||||
DARK_ACCENT = "#8bd5ca" # teal
|
||||
DARK_ACCENT_HOVER = "#a2ddd5" # teal +20% white — palette has no lighter teal step
|
||||
DARK_MUTED = "#a5adcb" # subtext0 — secondary text
|
||||
# Alert banners: full-strength color for border/text, 25%-over-DARK_BG tint
|
||||
# for bg (Catppuccin defines no alert backgrounds, so these are blends).
|
||||
DARK_ERROR_BG = "#523a4a" # red 25% over mantle
|
||||
DARK_ERROR_BORDER = "#ed8796" # red
|
||||
DARK_ERROR_TEXT = "#ed8796" # red
|
||||
DARK_SUCCESS_BG = "#404e49" # green 25% over mantle
|
||||
DARK_SUCCESS_BORDER = "#a6da95" # green
|
||||
DARK_SUCCESS_TEXT = "#a6da95" # green
|
||||
DARK_WARNING_BG = "#524d4c" # yellow 25% over mantle
|
||||
DARK_WARNING_BORDER = "#eed49f" # yellow
|
||||
DARK_WARNING_TEXT = "#eed49f" # yellow
|
||||
|
||||
# -- Shared chrome (light-theme widgets) ------------------------------------
|
||||
# Extracted from per-widget literals so the whole app is themeable from this
|
||||
# file. The same hex may appear under two names when the roles differ —
|
||||
# separate knobs on purpose.
|
||||
WHITE = "#ffffff"
|
||||
DEFAULT_TEXT = "#000000" # labels that reset to plain black
|
||||
NOTE_TEXT = "#555555" # tutorial hints, TELL sample details
|
||||
DIM_TEXT = "#666666" # baton dialog timers
|
||||
HINT_TEXT = "#999999" # baton dialog fine print
|
||||
HEADING_TEXT = "#1e293b" # card headings (slate-800)
|
||||
SUBTLE_TEXT = "#334155" # card body text (slate-700)
|
||||
MUTED_TEXT = "#475569" # neutral chip / idle step text (slate-600)
|
||||
FAINT_TEXT = "#64748b" # pending/skipped step text (slate-500)
|
||||
SHADOW = "#000000" # drop shadows & tutorial scrim; alpha stays at call site
|
||||
|
||||
# -- Semantic action colors -------------------------------------------------
|
||||
GO_TEXT = "#4e9a06" # green start/run/measure button text
|
||||
ABORT_TEXT = "#a40000" # abort button text
|
||||
ALERT_TEXT = "#ff0000" # out-of-range motor labels
|
||||
PATH_WARN_TEXT = "#c80000" # file-exists warning in path panel
|
||||
DANGER_ACCENT = "#d9534f" # invalid p-group border + message text
|
||||
|
||||
# -- Status chips (local contact status) — "good" reuses SUCCESS_BG/TEXT ----
|
||||
CHIP_WARN_BG = "#fff3cd"
|
||||
CHIP_WARN_TEXT = "#7a4b00"
|
||||
CHIP_BAD_BG = "#fdeaea"
|
||||
CHIP_BAD_TEXT = "#8b1e1e"
|
||||
CHIP_NEUTRAL_BG = "#e9eef5" # text uses MUTED_TEXT
|
||||
CHIP_INFO_BG = "#e8f1ff"
|
||||
CHIP_INFO_TEXT = "#12406a"
|
||||
|
||||
# -- Status cards (beamline recovery, local contact error frame) ------------
|
||||
WARN_CARD_BORDER = "#f0c36d"
|
||||
BAD_CARD_BORDER = "#e6a8a8"
|
||||
INFO_CARD_BG = "#eef6ff"
|
||||
INFO_CARD_BORDER = "#a8c7e6"
|
||||
PENDING_CARD_BG = "#fff7db"
|
||||
PENDING_CARD_BORDER = "#e7cb73"
|
||||
|
||||
# -- Log panel --------------------------------------------------------------
|
||||
LOG_BORDER = "#8a8a8a"
|
||||
LOG_PANEL_BG = "#fff4f4"
|
||||
LOG_ERROR_BG = "#fff1f1"
|
||||
LOG_ERROR_BORDER = "#dd6666"
|
||||
LOG_WARN_BG = "#fff8e8"
|
||||
LOG_WARN_BORDER = "#d7aa42"
|
||||
LOG_SUCCESS_BG = "#eefaf0"
|
||||
LOG_SUCCESS_BORDER = "#6cb37a"
|
||||
LOG_INFO_BG = "#eef5ff"
|
||||
LOG_INFO_BORDER = "#6b9bd6"
|
||||
|
||||
# -- Automation panel + progress steps --------------------------------------
|
||||
AUTOMATION_TITLE_TEXT = "#1f2937"
|
||||
AUTOMATION_HINT_TEXT = "#374151"
|
||||
STEP_RUNNING_TEXT = "#2563eb" # same blue as PRIMARY, separate knob
|
||||
STEP_SUCCESS_TEXT = "#15803d"
|
||||
STEP_FAILED_TEXT = "#b91c1c"
|
||||
STEP_PAUSED_TEXT = "#c2410c"
|
||||
STEP_DONE_BG = "#ecfdf3"
|
||||
STEP_DONE_TEXT = "#166534"
|
||||
STEP_DONE_BORDER = "#a7f3d0"
|
||||
STEP_ACTIVE_BG = "#eff6ff"
|
||||
STEP_ACTIVE_TEXT = "#1d4ed8"
|
||||
STEP_ACTIVE_BORDER = "#bfdbfe"
|
||||
STEP_FAILED_BG = "#fef2f2"
|
||||
STEP_FAILED_BORDER = "#fecaca"
|
||||
STEP_PAUSED_BG = "#fff7ed"
|
||||
STEP_PAUSED_BORDER = "#fed7aa"
|
||||
STEP_IDLE_BG = "#f8fafc"
|
||||
STEP_IDLE_BORDER = "#e2e8f0"
|
||||
|
||||
# -- Baton request dialog ---------------------------------------------------
|
||||
BATON_OK_BG = "#4caf50"
|
||||
BATON_OK_HOVER = "#45a049"
|
||||
BATON_OK_PRESSED = "#3d8b40"
|
||||
BATON_DANGER_BG = "#f44336"
|
||||
BATON_DANGER_HOVER = "#da190b"
|
||||
BATON_DANGER_PRESSED = "#c41000"
|
||||
BATON_WARN = "#ff9800"
|
||||
BATON_INFO = "#2196f3"
|
||||
LIGHT_BORDER = "#cccccc"
|
||||
PROGRESS_TRACK_BG = "#f0f0f0"
|
||||
|
||||
# -- Splash screen ----------------------------------------------------------
|
||||
SPLASH_BG = "#222222"
|
||||
SPLASH_BORDER = "#444444"
|
||||
SPLASH_ACCENT = "#0078d7"
|
||||
|
||||
# -- Numeric inputs ---------------------------------------------------------
|
||||
INPUT_BG = "#ffffff"
|
||||
INPUT_INVALID_BG = "#ffd5d5"
|
||||
INPUT_DISABLED_BG = "#f0f0f0"
|
||||
INPUT_DISABLED_INVALID_BG = "#f0e1e1"
|
||||
|
||||
# -- Status bar flags (hex equivalents of the old CSS named colors) ---------
|
||||
STATUS_OK = "#008000" # closed / idle / owned / tell ok (was "green")
|
||||
STATUS_ALERT = "#ff0000" # open / busy / other-owner / hot cryo (was "red")
|
||||
STATUS_WARN = "#ffa500" # baton waiting / warming cryo / tell busy (was "orange")
|
||||
STATUS_INFO = "#0000ff" # cold cryo (was "blue")
|
||||
STATUS_VACANT = "#ffff00" # baton vacant (was "yellow")
|
||||
STATUS_REQUEST = "#00ffff" # baton request (was "cyan")
|
||||
|
||||
# -- Beamline state panel ---------------------------------------------------
|
||||
STATE_AVAILABLE = "#ed8936"
|
||||
STATE_UNAVAILABLE = "#8c96a5"
|
||||
STATE_MSG_ERROR = "#c81e1e"
|
||||
STATE_MSG_INFO = "#005caa"
|
||||
|
||||
# -- Sample tables + raster grid --------------------------------------------
|
||||
SAMPLE_ROW_ACTIVE_BG = "#ff6600"
|
||||
SAMPLE_ROW_QUEUED_BG = "#729fcf"
|
||||
SAMPLE_ROW_HIGHLIGHT_BG = "#d8e4fd"
|
||||
RASTER_GRID_LINE = "#729fcf"
|
||||
TABLE_SHADE_BG = "#e0e0e0"
|
||||
|
||||
# -- Camera / video overlay (painter colors, alpha at call site) ------------
|
||||
BEAM_OPEN = "#00ff00" # beam marker: shutter open
|
||||
BEAM_IDLE = "#f57900" # beam marker: idle
|
||||
BEAM_BUSY = "#ff0000" # beam marker: busy
|
||||
BEAM_MARKING = "#663399" # beam marker: marking mode
|
||||
MARKER_GREEN = "#32cd32" # loop-centering click marker
|
||||
PATH_START = "#008000" # raster path gradient start + start circle
|
||||
PATH_END = "#ff0000" # raster path gradient end + end circle
|
||||
LEGEND_BG = "#141414"
|
||||
LEGEND_TEXT = "#f0f0f0"
|
||||
TOOLTIP_TEXT = "#e6e6e6"
|
||||
MARK_TOOLTIP_GOLD = "#ffd700"
|
||||
MARK_TOOLTIP_ORANGE = "#ffa500"
|
||||
MARK_TOOLTIP_RED = "#ff0000"
|
||||
MARK_BADGE_BG = "#b43c00"
|
||||
|
||||
# Prediction class overlay colors. The chart variant historically used pure
|
||||
# green (#00ff00) while the overlay used CSS green (#008000) — both kept.
|
||||
CLASS_COLORS = {
|
||||
"pin": "#ff0000",
|
||||
"loop_all": "#008000",
|
||||
"loop_face": "#ffff00",
|
||||
"crystal": "#0000ff",
|
||||
"needle": "#ff00ff",
|
||||
"ice": "#00ffff",
|
||||
}
|
||||
CHART_CLASS_COLORS = {
|
||||
"Pin": "#ff0000",
|
||||
"Loop_all": "#00ff00",
|
||||
"Loop_face": "#ffff00",
|
||||
"Crystal": "#0000ff",
|
||||
"Needle": "#ff00ff",
|
||||
"Ice": "#00ffff",
|
||||
}
|
||||
TARGET_COLORS = {"Cyan": "#00ffff", "Dark Blue": "#0046a0", "Dark Red": "#8c1919"}
|
||||
BOOKMARK_COLORS = {
|
||||
"red": "#ff0000",
|
||||
"green": "#008000",
|
||||
"blue": "#0000ff",
|
||||
"indigo": "#4b0082",
|
||||
"lime": "#00ff00",
|
||||
}
|
||||
|
||||
# -- Busy overlay (per-source color coding) ---------------------------------
|
||||
BUSY_YELLOW = "#f1c40f"
|
||||
BUSY_YELLOW_BORDER = "#fff8d2"
|
||||
BUSY_YELLOW_DOT = "#fff6bf"
|
||||
BUSY_YELLOW_TEXT_DARK = "#3b2f00"
|
||||
BUSY_PURPLE = "#8e44ad"
|
||||
BUSY_PURPLE_BORDER = "#ebdcf5"
|
||||
BUSY_PURPLE_DOT = "#f0dfff"
|
||||
BUSY_RED_BADGE = "#d64545"
|
||||
BUSY_RED_FILL = "#be2828"
|
||||
BUSY_RED_BORDER = "#ffdcdc"
|
||||
BUSY_RED_DOT = "#ffdddd"
|
||||
BUSY_ORANGE = "#e67e22"
|
||||
BUSY_ORANGE_BORDER = "#ffead6"
|
||||
BUSY_ORANGE_DOT = "#fff0db"
|
||||
BUSY_BLUE = "#3498db"
|
||||
BUSY_BLUE_BORDER = "#dcf0ff"
|
||||
BUSY_BLUE_DOT = "#dff2ff"
|
||||
BUSY_PSI_RED = "#e04f39"
|
||||
BUSY_PSI_RED_BORDER = "#ffe1dc"
|
||||
BUSY_PSI_RED_DOT = "#ffd8d1"
|
||||
|
||||
# -- Charts (prediction metrics, target stability, fluorescence) ------------
|
||||
CHART_BLUE = "#1f77b4"
|
||||
CHART_BLUE_LIGHT = "#6baed6"
|
||||
CHART_BLUE_PALE = "#9ecae1"
|
||||
CHART_RED = "#d62728"
|
||||
CHART_RED_LIGHT = "#ff9896"
|
||||
CHART_RED_DARK = "#c43c39"
|
||||
CHART_ORANGE = "#ff7f0e"
|
||||
CHART_ORANGE_PALE = "#ffbb78"
|
||||
CHART_GREEN = "#2ca02c"
|
||||
CHART_GREEN_PALE = "#98df8a"
|
||||
CHART_CYAN = "#17becf"
|
||||
CHART_PURPLE = "#9467bd"
|
||||
CHART_MUTED = "#888888"
|
||||
CONFIDENCE_BIN_COLORS = [CHART_RED, CHART_ORANGE, CHART_ORANGE_PALE, CHART_GREEN_PALE, CHART_GREEN]
|
||||
SPECTRUM_LINE = "#cc0000"
|
||||
|
||||
# -- Generic panels (developer help, raster table) --------------------------
|
||||
PANEL_BG_SOFT = "#f6f6f6"
|
||||
PANEL_BG_FAINT = "#fafafa"
|
||||
PANEL_BORDER = "#d0d0d0"
|
||||
PANEL_BORDER_DARK = "#bdbdbd"
|
||||
PANEL_BORDER_LIGHT = "#e0e0e0"
|
||||
TUTORIAL_BORDER = "#555555"
|
||||
TUTORIAL_HIGHLIGHT = "#ffff00" # widget spotlight pen (was Qt.yellow)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _palette() -> dict[str, str]:
|
||||
# Why: one substitution mapping instead of ~40 kwargs per stylesheet, and
|
||||
# a renamed/missing constant fails loudly (KeyError) instead of silently.
|
||||
return {k.lower(): v for k, v in globals().items() if k.isupper() and isinstance(v, str)}
|
||||
|
||||
|
||||
def qcolor(color: str, alpha: int | None = None):
|
||||
"""QColor from a palette hex string, optional 0-255 alpha.
|
||||
|
||||
Hue lives here (theme), alpha stays at the call site (behavior). Lazy Qt
|
||||
import so this module — and its self-check — stay importable without
|
||||
PySide6.
|
||||
"""
|
||||
from PySide6.QtGui import QColor
|
||||
|
||||
c = QColor(color)
|
||||
if alpha is not None:
|
||||
c.setAlpha(alpha)
|
||||
return c
|
||||
|
||||
|
||||
def build_app_stylesheet(theme: str) -> str:
|
||||
if theme == THEME_PORTRAIT:
|
||||
@@ -11,24 +315,24 @@ def build_app_stylesheet(theme: str) -> str:
|
||||
|
||||
|
||||
def _original_stylesheet() -> str:
|
||||
return """
|
||||
return Template("""
|
||||
QMainWindow, QWidget {
|
||||
background-color: rgb(216, 228, 253);
|
||||
color: rgb(30, 41, 59);
|
||||
background-color: $background;
|
||||
color: $text;
|
||||
}
|
||||
|
||||
QWidget#mainContentRoot,
|
||||
QWidget#standardMainPage,
|
||||
QWidget#compactAutomationPage {
|
||||
background-color: rgb(216, 228, 253);
|
||||
background-color: $background;
|
||||
}
|
||||
|
||||
QWidget#portraitModePage {
|
||||
background-color: #071018;
|
||||
background-color: $dark_bg;
|
||||
}
|
||||
|
||||
QFrame#compactAutomationPanel {
|
||||
background: #d8e4fd;
|
||||
background: $background;
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
}
|
||||
@@ -38,42 +342,42 @@ def _original_stylesheet() -> str:
|
||||
QFrame#compactProgressCard,
|
||||
QFrame#compactQueueCard,
|
||||
QFrame#compactQueueItem {
|
||||
background: #e6eefc;
|
||||
border: 1px solid #b9ccee;
|
||||
background: $compact_card_bg;
|
||||
border: 1px solid $compact_border;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
QLabel#compactSectionTitle {
|
||||
background: transparent;
|
||||
color: #17324d;
|
||||
color: $compact_title;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QLabel#compactSectionHint {
|
||||
background: transparent;
|
||||
color: #51657d;
|
||||
color: $compact_hint;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
QLabel#compactQueueTitle {
|
||||
background: transparent;
|
||||
color: #51657d;
|
||||
color: $compact_hint;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QLabel#compactQueueValue {
|
||||
background: transparent;
|
||||
color: #10263a;
|
||||
color: $compact_value;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QToolButton#compactMenuButton {
|
||||
background: #cbdcf8;
|
||||
color: #17324d;
|
||||
border: 1px solid #9fb9e5;
|
||||
background: $compact_menu_bg;
|
||||
color: $compact_title;
|
||||
border: 1px solid $compact_border;
|
||||
border-radius: 14px;
|
||||
padding: 10px 14px;
|
||||
font-size: 18px;
|
||||
@@ -81,12 +385,12 @@ def _original_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QToolButton#compactMenuButton:hover {
|
||||
background: #bfd4f6;
|
||||
background: $compact_menu_bg_hover;
|
||||
}
|
||||
|
||||
QPushButton#compactPrimaryButton {
|
||||
background: #2563eb;
|
||||
color: white;
|
||||
background: $primary;
|
||||
color: $primary_text;
|
||||
border: none;
|
||||
border-radius: 14px;
|
||||
padding: 14px 18px;
|
||||
@@ -95,14 +399,14 @@ def _original_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QPushButton#compactPrimaryButton:hover {
|
||||
background: #1d4ed8;
|
||||
background: $primary_hover;
|
||||
}
|
||||
|
||||
QPushButton#compactSecondaryButton,
|
||||
QToolButton#compactSecondaryButton {
|
||||
background: #dfe9fb;
|
||||
color: #17324d;
|
||||
border: 1px solid #b2c7eb;
|
||||
background: $secondary_bg;
|
||||
color: $compact_title;
|
||||
border: 1px solid $compact_border;
|
||||
border-radius: 14px;
|
||||
padding: 14px 18px;
|
||||
font-size: 14px;
|
||||
@@ -111,26 +415,26 @@ def _original_stylesheet() -> str:
|
||||
|
||||
QPushButton#compactSecondaryButton:hover,
|
||||
QToolButton#compactSecondaryButton:hover {
|
||||
background: #d3e1f8;
|
||||
background: $secondary_bg_hover;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="error"] {
|
||||
background-color: #fbe4e6;
|
||||
border: 2px solid #d97a84;
|
||||
background-color: $error_bg;
|
||||
border: 2px solid $error_border;
|
||||
border-radius: 12px;
|
||||
margin: 8px 12px 8px 12px;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="success"] {
|
||||
background-color: #e7f6ea;
|
||||
border: 2px solid #7bbf8e;
|
||||
background-color: $success_bg;
|
||||
border: 2px solid $success_border;
|
||||
border-radius: 12px;
|
||||
margin: 8px 12px 8px 12px;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="waiting"] {
|
||||
background-color: #fff8e1;
|
||||
border: 2px solid #ffb300;
|
||||
background-color: $warning_bg;
|
||||
border: 2px solid $warning_border;
|
||||
border-radius: 12px;
|
||||
margin: 8px 12px 8px 12px;
|
||||
}
|
||||
@@ -142,20 +446,20 @@ def _original_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="error"] QLabel {
|
||||
color: #8f1d2c;
|
||||
color: $error_text;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="success"] QLabel {
|
||||
color: #1f6a3a;
|
||||
color: $success_text;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="waiting"] QLabel {
|
||||
color: #e65100;
|
||||
color: $warning_text;
|
||||
}
|
||||
|
||||
QWidget#axisVideoStatusContainer[busyState="idle"] {
|
||||
border-radius: 12px;
|
||||
background-color: #d9e2f2;
|
||||
background-color: $status_idle_bg;
|
||||
}
|
||||
|
||||
QWidget#axisVideoStatusContainer[busyState="active"] {
|
||||
@@ -173,18 +477,33 @@ def _original_stylesheet() -> str:
|
||||
|
||||
QLabel#axisVideoStatusLabel {
|
||||
background-color: transparent;
|
||||
color: #2f3b52;
|
||||
color: $status_label_text;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QTabWidget::pane {
|
||||
border: 1px solid $border;
|
||||
}
|
||||
|
||||
QMainWindow::separator {
|
||||
background: $border;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
QFrame#beamlineControls,
|
||||
QFrame#dataCollectionSettings {
|
||||
border: 1px solid $border;
|
||||
}
|
||||
|
||||
QFrame#beamlineStatePanel {
|
||||
background: rgb(216, 228, 253);
|
||||
border-top: 1px solid rgb(185, 204, 238);
|
||||
background: $background;
|
||||
border-top: 1px solid $border;
|
||||
}
|
||||
|
||||
QLabel#beamlineStateTitle {
|
||||
background-color: #4B0082;
|
||||
color: #ffffff;
|
||||
background-color: $banner;
|
||||
color: $banner_text;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
@@ -193,13 +512,13 @@ def _original_stylesheet() -> str:
|
||||
QPushButton#beamlineStateToggleButton {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: white;
|
||||
color: $state_toggle_text;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QLabel#beamlineStateCurrentLabel {
|
||||
color: rgb(30, 41, 59);
|
||||
color: $state_current_text;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
padding-left: 4px;
|
||||
@@ -207,7 +526,7 @@ def _original_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QLabel#beamlineStateTellLabel {
|
||||
color: rgb(55, 67, 87);
|
||||
color: $state_tell_text;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
padding-left: 4px;
|
||||
@@ -216,8 +535,8 @@ def _original_stylesheet() -> str:
|
||||
|
||||
QWidget#portraitRoot,
|
||||
QWidget#portraitRoot QWidget {
|
||||
background: #071018;
|
||||
color: #F5F7FA;
|
||||
background: $dark_bg;
|
||||
color: $dark_text;
|
||||
font-family: 'Inter', 'SF Pro Display', Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -228,13 +547,13 @@ def _original_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QWidget#portraitRoot QScrollBar:vertical {
|
||||
background: #0E1A26;
|
||||
background: $dark_surface;
|
||||
width: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QWidget#portraitRoot QScrollBar::handle:vertical {
|
||||
background: #1A3A36;
|
||||
background: $dark_border;
|
||||
border-radius: 2px;
|
||||
min-height: 20px;
|
||||
}
|
||||
@@ -243,33 +562,33 @@ def _original_stylesheet() -> str:
|
||||
QWidget#portraitRoot QScrollBar::sub-line:vertical {
|
||||
height: 0px;
|
||||
}
|
||||
"""
|
||||
""").substitute(_palette())
|
||||
|
||||
|
||||
def _portrait_stylesheet() -> str:
|
||||
return """
|
||||
return Template("""
|
||||
QMainWindow, QWidget {
|
||||
background: #071018;
|
||||
color: #F5F7FA;
|
||||
background: $dark_bg;
|
||||
color: $dark_text;
|
||||
}
|
||||
|
||||
QWidget#mainContentRoot,
|
||||
QWidget#standardMainPage,
|
||||
QWidget#compactAutomationPage,
|
||||
QWidget#portraitModePage {
|
||||
background: #071018;
|
||||
background: $dark_bg;
|
||||
}
|
||||
|
||||
QTabWidget::pane,
|
||||
QScrollArea,
|
||||
QDockWidget,
|
||||
QDockWidget > QWidget {
|
||||
background: #071018;
|
||||
color: #F5F7FA;
|
||||
background: $dark_bg;
|
||||
color: $dark_text;
|
||||
}
|
||||
|
||||
QFrame#compactAutomationPanel {
|
||||
background: #071018;
|
||||
background: $dark_bg;
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
}
|
||||
@@ -279,42 +598,42 @@ def _portrait_stylesheet() -> str:
|
||||
QFrame#compactProgressCard,
|
||||
QFrame#compactQueueCard,
|
||||
QFrame#compactQueueItem {
|
||||
background: #0E1A26;
|
||||
border: 1px solid #1A3A36;
|
||||
background: $dark_surface;
|
||||
border: 1px solid $dark_border;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
QLabel#compactSectionTitle {
|
||||
background: transparent;
|
||||
color: #62D8C8;
|
||||
color: $dark_accent;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QLabel#compactSectionHint {
|
||||
background: transparent;
|
||||
color: #8A9BB0;
|
||||
color: $dark_muted;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
QLabel#compactQueueTitle {
|
||||
background: transparent;
|
||||
color: #8A9BB0;
|
||||
color: $dark_muted;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QLabel#compactQueueValue {
|
||||
background: transparent;
|
||||
color: #F5F7FA;
|
||||
color: $dark_text;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QToolButton#compactMenuButton {
|
||||
background: #132131;
|
||||
color: #62D8C8;
|
||||
border: 1px solid #1A3A36;
|
||||
background: $dark_elevated;
|
||||
color: $dark_accent;
|
||||
border: 1px solid $dark_border;
|
||||
border-radius: 14px;
|
||||
padding: 10px 14px;
|
||||
font-size: 18px;
|
||||
@@ -322,12 +641,12 @@ def _portrait_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QToolButton#compactMenuButton:hover {
|
||||
background: #1A3A36;
|
||||
background: $dark_border;
|
||||
}
|
||||
|
||||
QPushButton#compactPrimaryButton {
|
||||
background: #62D8C8;
|
||||
color: #071018;
|
||||
background: $dark_accent;
|
||||
color: $dark_bg;
|
||||
border: none;
|
||||
border-radius: 14px;
|
||||
padding: 14px 18px;
|
||||
@@ -336,14 +655,14 @@ def _portrait_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QPushButton#compactPrimaryButton:hover {
|
||||
background: #7ce6d8;
|
||||
background: $dark_accent_hover;
|
||||
}
|
||||
|
||||
QPushButton#compactSecondaryButton,
|
||||
QToolButton#compactSecondaryButton {
|
||||
background: #132131;
|
||||
color: #F5F7FA;
|
||||
border: 1px solid #1A3A36;
|
||||
background: $dark_elevated;
|
||||
color: $dark_text;
|
||||
border: 1px solid $dark_border;
|
||||
border-radius: 14px;
|
||||
padding: 14px 18px;
|
||||
font-size: 14px;
|
||||
@@ -352,26 +671,26 @@ def _portrait_stylesheet() -> str:
|
||||
|
||||
QPushButton#compactSecondaryButton:hover,
|
||||
QToolButton#compactSecondaryButton:hover {
|
||||
background: #1A3A36;
|
||||
background: $dark_border;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="error"] {
|
||||
background: #1A0E0E;
|
||||
border: 2px solid #8f1d2c;
|
||||
background: $dark_error_bg;
|
||||
border: 2px solid $dark_error_border;
|
||||
border-radius: 12px;
|
||||
margin: 8px 12px 8px 12px;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="success"] {
|
||||
background: #0E1A12;
|
||||
border: 2px solid #2a7a44;
|
||||
background: $dark_success_bg;
|
||||
border: 2px solid $dark_success_border;
|
||||
border-radius: 12px;
|
||||
margin: 8px 12px 8px 12px;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="waiting"] {
|
||||
background: #2B2208;
|
||||
border: 2px solid #ffb300;
|
||||
background: $dark_warning_bg;
|
||||
border: 2px solid $dark_warning_border;
|
||||
border-radius: 12px;
|
||||
margin: 8px 12px 8px 12px;
|
||||
}
|
||||
@@ -383,20 +702,20 @@ def _portrait_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="error"] QLabel {
|
||||
color: #ffb3bc;
|
||||
color: $dark_error_text;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="success"] QLabel {
|
||||
color: #a8f0c0;
|
||||
color: $dark_success_text;
|
||||
}
|
||||
|
||||
QFrame#alertBanner[alertKind="waiting"] QLabel {
|
||||
color: #ffd166;
|
||||
color: $dark_warning_text;
|
||||
}
|
||||
|
||||
QWidget#axisVideoStatusContainer[busyState="idle"] {
|
||||
border-radius: 12px;
|
||||
background-color: #132131;
|
||||
background-color: $dark_elevated;
|
||||
}
|
||||
|
||||
QWidget#axisVideoStatusContainer[busyState="active"] {
|
||||
@@ -414,18 +733,18 @@ def _portrait_stylesheet() -> str:
|
||||
|
||||
QLabel#axisVideoStatusLabel {
|
||||
background-color: transparent;
|
||||
color: #8A9BB0;
|
||||
color: $dark_muted;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QFrame#beamlineStatePanel {
|
||||
background: #0E1A26;
|
||||
border-top: 1px solid #1A3A36;
|
||||
background: $dark_surface;
|
||||
border-top: 1px solid $dark_border;
|
||||
}
|
||||
|
||||
QLabel#beamlineStateTitle {
|
||||
background-color: #132131;
|
||||
color: #F5F7FA;
|
||||
background-color: $dark_elevated;
|
||||
color: $dark_text;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
@@ -434,13 +753,13 @@ def _portrait_stylesheet() -> str:
|
||||
QPushButton#beamlineStateToggleButton {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #F5F7FA;
|
||||
color: $dark_text;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
QLabel#beamlineStateCurrentLabel {
|
||||
color: #F5F7FA;
|
||||
color: $dark_text;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
padding-left: 4px;
|
||||
@@ -448,7 +767,7 @@ def _portrait_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QLabel#beamlineStateTellLabel {
|
||||
color: #8A9BB0;
|
||||
color: $dark_muted;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
padding-left: 4px;
|
||||
@@ -457,8 +776,8 @@ def _portrait_stylesheet() -> str:
|
||||
|
||||
QWidget#portraitRoot,
|
||||
QWidget#portraitRoot QWidget {
|
||||
background: #071018;
|
||||
color: #F5F7FA;
|
||||
background: $dark_bg;
|
||||
color: $dark_text;
|
||||
font-family: 'Inter', 'SF Pro Display', Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -469,13 +788,13 @@ def _portrait_stylesheet() -> str:
|
||||
}
|
||||
|
||||
QWidget#portraitRoot QScrollBar:vertical {
|
||||
background: #0E1A26;
|
||||
background: $dark_surface;
|
||||
width: 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QWidget#portraitRoot QScrollBar::handle:vertical {
|
||||
background: #1A3A36;
|
||||
background: $dark_border;
|
||||
border-radius: 2px;
|
||||
min-height: 20px;
|
||||
}
|
||||
@@ -484,4 +803,11 @@ def _portrait_stylesheet() -> str:
|
||||
QWidget#portraitRoot QScrollBar::sub-line:vertical {
|
||||
height: 0px;
|
||||
}
|
||||
"""
|
||||
""").substitute(_palette())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# ponytail: smallest check that fails if a $name has no matching constant
|
||||
for _theme in (THEME_ORIGINAL, THEME_PORTRAIT):
|
||||
assert "$" not in build_app_stylesheet(_theme)
|
||||
print("gude")
|
||||
|
||||
Reference in New Issue
Block a user