Add per-area color preference sliders
Five grayscale (black->white) sliders in Preferences that update live:
outer-chrome background (QPalette.Window), the rounded transport button
boxes, the now-playing panel, the now-playing text, and the row stripes
(QPalette.AlternateBase). Defaults are None ("inherit current") so nothing
changes until the user drags. Decouples the button boxes from the stripe
color (they used to share palette alternate-base). Live preview via
Preferences.set_live (no disk write); persisted ~0.4s after the drag.
This commit is contained in:
+62
-5
@@ -34,6 +34,54 @@ UI_SCALES = {
|
||||
_base_palette = None
|
||||
|
||||
|
||||
# The five user-tunable grayscale surfaces. now-playing bg/text have fixed
|
||||
# defaults (white/black); the rest default to whatever the base palette uses,
|
||||
# so an untouched install looks exactly as it did before the feature existed.
|
||||
_PALETTE_GRAY_ROLE = {
|
||||
"color_background": QPalette.ColorRole.Window,
|
||||
"color_stripe": QPalette.ColorRole.AlternateBase,
|
||||
"color_button": QPalette.ColorRole.AlternateBase,
|
||||
}
|
||||
_FIXED_GRAY_DEFAULT = {
|
||||
"color_now_playing_bg": 255,
|
||||
"color_now_playing_text": 0,
|
||||
}
|
||||
|
||||
|
||||
def _base() -> QPalette:
|
||||
"""The app's original palette, captured once, used as the reference for
|
||||
highlight/grayscale overrides and for the sliders' 'current' defaults."""
|
||||
global _base_palette
|
||||
if _base_palette is None:
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
app = QApplication.instance()
|
||||
_base_palette = QPalette(app.palette()) if app is not None else QPalette()
|
||||
return _base_palette
|
||||
|
||||
|
||||
def gray(value) -> QColor:
|
||||
"""A 0..255 lightness as an opaque gray QColor."""
|
||||
v = max(0, min(255, int(value)))
|
||||
return QColor(v, v, v)
|
||||
|
||||
|
||||
def default_gray(key: str) -> int:
|
||||
"""The slider's value when this surface hasn't been overridden — i.e. its
|
||||
current appearance, so showing the slider doesn't imply a change."""
|
||||
if key in _FIXED_GRAY_DEFAULT:
|
||||
return _FIXED_GRAY_DEFAULT[key]
|
||||
color = _base().color(QPalette.ColorGroup.Active, _PALETTE_GRAY_ROLE[key])
|
||||
return round(0.299 * color.red() + 0.587 * color.green()
|
||||
+ 0.114 * color.blue())
|
||||
|
||||
|
||||
def gray_value(prefs, key: str) -> int:
|
||||
"""The 0..255 value to show/apply for a surface: the saved override, or the
|
||||
current default when the user hasn't touched it."""
|
||||
saved = prefs.get(key)
|
||||
return default_gray(key) if saved is None else max(0, min(255, int(saved)))
|
||||
|
||||
|
||||
def highlight_color(prefs) -> QColor:
|
||||
return QColor(HIGHLIGHT_COLORS.get(prefs.get("highlight"),
|
||||
HIGHLIGHT_COLORS["blue"]))
|
||||
@@ -44,9 +92,7 @@ def scale_metrics(prefs) -> dict:
|
||||
|
||||
|
||||
def apply_theme(app, prefs):
|
||||
global _base_palette
|
||||
if _base_palette is None:
|
||||
_base_palette = QPalette(app.palette())
|
||||
base = _base()
|
||||
|
||||
color = highlight_color(prefs)
|
||||
# Black text on light highlights, white on dark
|
||||
@@ -54,11 +100,22 @@ def apply_theme(app, prefs):
|
||||
+ 0.114 * color.blue()) / 255
|
||||
text = QColor("black") if luminance > 0.6 else QColor("white")
|
||||
|
||||
palette = QPalette(_base_palette)
|
||||
for group in (QPalette.ColorGroup.Active, QPalette.ColorGroup.Inactive):
|
||||
palette = QPalette(base)
|
||||
groups = (QPalette.ColorGroup.Active, QPalette.ColorGroup.Inactive)
|
||||
for group in groups:
|
||||
palette.setColor(group, QPalette.ColorRole.Highlight, color)
|
||||
palette.setColor(group, QPalette.ColorRole.HighlightedText, text)
|
||||
palette.setColor(group, QPalette.ColorRole.Accent, color)
|
||||
# User grayscale overrides (None = leave the base color untouched). The
|
||||
# button-box color lives in transport.py, not the palette.
|
||||
background = prefs.get("color_background")
|
||||
if background is not None:
|
||||
for group in groups:
|
||||
palette.setColor(group, QPalette.ColorRole.Window, gray(background))
|
||||
stripe = prefs.get("color_stripe")
|
||||
if stripe is not None:
|
||||
for group in groups:
|
||||
palette.setColor(group, QPalette.ColorRole.AlternateBase, gray(stripe))
|
||||
app.setPalette(palette)
|
||||
|
||||
metrics = scale_metrics(prefs)
|
||||
|
||||
Reference in New Issue
Block a user