v0.25.0: New Tracks, a soft emboss, date added pinned

Groundwork for Cassette (friend library sharing) that stands on its own:

- A brand-new library (fresh data dir, or a fresh iTunes import) starts
  with a "New Tracks" smart playlist: added in the last 3 months, newest
  first. Fixed persistent id, so two machines seeding one unsynced share
  merge into a single playlist.
- Every non-flat button, the sidebar Library button and the transport
  boxes get a very slight top-lit gradient computed from the live palette,
  with the chosen color kept exactly at its midpoint.
- Tests pin that individual imports stamp date added = now even for an
  old file, and that the iTunes migration keeps the XML's dates.
This commit is contained in:
2026-09-28 20:56:28 -07:00
parent 6fc6c335c5
commit 549c5bf94f
9 changed files with 275 additions and 11 deletions
+43
View File
@@ -156,13 +156,56 @@ def apply_theme(app, prefs):
app.setFont(font)
bar = metrics["scrollbar"]
button = palette.color(QPalette.ColorRole.Button)
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; }}
{button_emboss_qss(button)}
""")
def emboss_gradient(color: QColor, pressed: bool = False) -> str:
"""A barely-there top-lit vertical gradient around ``color``.
Computed from the live color rather than hard-coded, so it follows the
palette (light or dark) and the user's grayscale overrides. ``pressed``
flips it, which reads as the button sinking in."""
top, bottom = color.lighter(EMBOSS_LIGHTER), color.darker(EMBOSS_DARKER)
if pressed:
top, bottom = bottom, top
# The color itself sits at the midpoint, so what the user picked is still
# exactly what the middle of the button shows.
return (f"qlineargradient(x1:0, y1:0, x2:0, y2:1, "
f"stop:0 {top.name()}, stop:0.5 {color.name()}, "
f"stop:1 {bottom.name()})")
# How far the emboss strays from the base color (Qt's lighter/darker factor,
# 100 = unchanged). Kept small on purpose: "very slight, soft".
EMBOSS_LIGHTER = 106
EMBOSS_DARKER = 104
def button_emboss_qss(button: QColor) -> str:
"""Global rule for every non-flat QPushButton. Flat buttons (the version
button, the cancel-transfer ✕, the bpm label) opt out by being flat."""
hover = button.lighter(103)
return f"""
QPushButton:!flat {{
border: 1px solid palette(mid); border-radius: 4px;
padding: 3px 12px; min-height: 1.3em;
background: {emboss_gradient(button)};
}}
QPushButton:!flat:hover {{ background: {emboss_gradient(hover)}; }}
QPushButton:!flat:pressed, QPushButton:!flat:checked {{
background: {emboss_gradient(button, pressed=True)};
}}
QPushButton:!flat:default {{ border-color: palette(highlight); }}
QPushButton:!flat:disabled {{ color: palette(mid); }}
"""
def installed_families() -> set[str]:
"""Families Qt can actually resolve on this machine."""
return set(QFontDatabase.families())