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:
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user