Import existing LinTunes project
Snapshot of the existing codebase before working through the TASKS.md backlog. Real library data (data/) and the iTunes import fixture (itunes-test-library/) are gitignored.
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
"""App-wide theming: highlight color and UI/text scale, driven by Preferences.
|
||||
|
||||
Everything that shows the highlight color (table/sidebar selection, the seek
|
||||
slider's filled groove, the visualizer bars) reads QPalette.Highlight, so
|
||||
recoloring is a palette swap. UI scale adjusts the app font, scrollbar
|
||||
dimensions, and (via MainWindow.apply_ui_metrics) table row heights.
|
||||
"""
|
||||
from PyQt6.QtGui import QPalette, QColor, QFontDatabase
|
||||
|
||||
|
||||
# The font the now-playing panel wants by default. Not bundled (it's a
|
||||
# proprietary Monotype face); the user is asked to install it and, if missing,
|
||||
# to pick a substitute on first run (see main.ensure_now_playing_font).
|
||||
CENTURY_GOTHIC = "Century Gothic"
|
||||
|
||||
|
||||
HIGHLIGHT_COLORS = {
|
||||
"blue": "#3584E4",
|
||||
"marigold": "#F5A623",
|
||||
"magenta": "#D6409F",
|
||||
"seafoam": "#7FD1AE",
|
||||
"gray": "#8A8A8A",
|
||||
}
|
||||
|
||||
UI_SCALES = {
|
||||
"small": {"font_pt": 9, "scrollbar": 10, "row_height": 20, "header_strip": 28,
|
||||
"status_height": 22},
|
||||
"medium": {"font_pt": 11, "scrollbar": 14, "row_height": 24, "header_strip": 34,
|
||||
"status_height": 26},
|
||||
"large": {"font_pt": 13, "scrollbar": 18, "row_height": 28, "header_strip": 40,
|
||||
"status_height": 32},
|
||||
}
|
||||
|
||||
_base_palette = None
|
||||
|
||||
|
||||
def highlight_color(prefs) -> QColor:
|
||||
return QColor(HIGHLIGHT_COLORS.get(prefs.get("highlight"),
|
||||
HIGHLIGHT_COLORS["blue"]))
|
||||
|
||||
|
||||
def scale_metrics(prefs) -> dict:
|
||||
return UI_SCALES.get(prefs.get("ui_scale"), UI_SCALES["medium"])
|
||||
|
||||
|
||||
def apply_theme(app, prefs):
|
||||
global _base_palette
|
||||
if _base_palette is None:
|
||||
_base_palette = QPalette(app.palette())
|
||||
|
||||
color = highlight_color(prefs)
|
||||
# Black text on light highlights, white on dark
|
||||
luminance = (0.299 * color.red() + 0.587 * color.green()
|
||||
+ 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.setColor(group, QPalette.ColorRole.Highlight, color)
|
||||
palette.setColor(group, QPalette.ColorRole.HighlightedText, text)
|
||||
palette.setColor(group, QPalette.ColorRole.Accent, color)
|
||||
app.setPalette(palette)
|
||||
|
||||
metrics = scale_metrics(prefs)
|
||||
font = app.font()
|
||||
font.setPointSize(metrics["font_pt"])
|
||||
app.setFont(font)
|
||||
|
||||
bar = metrics["scrollbar"]
|
||||
app.setStyleSheet(f"""
|
||||
QScrollBar:vertical {{ width: {bar}px; }}
|
||||
QScrollBar:horizontal {{ height: {bar}px; }}
|
||||
QScrollBar::handle {{ min-height: {bar * 2}px; min-width: {bar * 2}px; }}
|
||||
""")
|
||||
|
||||
|
||||
def century_gothic_available() -> bool:
|
||||
"""True if the Century Gothic family is installed and resolvable by Qt."""
|
||||
return CENTURY_GOTHIC in QFontDatabase.families()
|
||||
|
||||
|
||||
def now_playing_font_family(prefs) -> str | None:
|
||||
"""Family the now-playing panel should use, or None for the app default.
|
||||
|
||||
prefs["now_playing_font"] semantics:
|
||||
- missing/None : never set → prefer Century Gothic, fall back to default
|
||||
- "" : user chose "use default" → always the app default
|
||||
- "Family" : user picked a family → use it (if still installed)
|
||||
"""
|
||||
saved = prefs.get("now_playing_font")
|
||||
if saved == "":
|
||||
return None
|
||||
if saved: # a previously chosen family
|
||||
return saved if saved in QFontDatabase.families() else None
|
||||
# Never set: prefer Century Gothic when present, else default.
|
||||
return CENTURY_GOTHIC if century_gothic_available() else None
|
||||
Reference in New Issue
Block a user