v0.51.1: album art sits under the list frame's closing line, like the empty panel

This commit is contained in:
2026-10-13 10:11:55 -07:00
parent 976d338574
commit f48165080b
4 changed files with 58 additions and 8 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
"""LinTunes — iTunes-style music library manager and player for Linux."""
__version__ = "0.51.0"
__version__ = "0.51.1"
+28 -6
View File
@@ -2,9 +2,9 @@ from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QPushButton, QTreeWidget, QTreeWidgetItem, QMenu,
QInputDialog, QMessageBox, QAbstractItemView, QLineEdit, QApplication,
QHBoxLayout, QListWidget, QListWidgetItem, QStackedWidget, QSizePolicy,
QFrame,
QFrame, QStyle, QStyleOptionFrame,
)
from PyQt6.QtCore import Qt, QTimer, QPoint, QRectF, pyqtSignal
from PyQt6.QtCore import Qt, QTimer, QPoint, QRect, QRectF, pyqtSignal
from PyQt6.QtGui import QBrush, QPainter, QPalette, QPixmap
from lintunes.models import PlaylistType
@@ -267,6 +267,10 @@ class FriendPlaylistList(QListWidget):
# it, with the visualizer's corners.
NO_ART_GAP = 6
NO_ART_RADIUS = 8
# Art sits inside the list's frame, so the frame never closes between them;
# the art draws that closing line itself, this tall, so a cover with a white
# border doesn't run straight on from the list.
ART_RULE = 1
class SidebarArt(QWidget):
@@ -326,7 +330,7 @@ class SidebarArt(QWidget):
def _fit_height(self):
# Keep it square: height follows the sidebar's width (plus the gap
# above the empty panel)
height = self.width() + (0 if self.has_art() else NO_ART_GAP)
height = self.width() + (ART_RULE if self.has_art() else NO_ART_GAP)
if self.height() != height:
self.setFixedHeight(height)
@@ -358,11 +362,29 @@ class SidebarArt(QWidget):
self.palette().alternateBase().color(),
NO_ART_RADIUS, like=CONTROL_HEIGHT)
return
# The list frame's own bottom edge, drawn by the style: a frame
# whose bottom row is this widget's top row, its sides pushed out of
# view, so the line is exactly the one under the list with no art.
option = QStyleOptionFrame()
option.initFrom(self)
option.frameShape = QFrame.Shape.StyledPanel
option.state |= QStyle.StateFlag.State_Sunken
option.lineWidth = option.midLineWidth = 0
frame = self.style().pixelMetric(QStyle.PixelMetric.PM_DefaultFrameWidth)
option.rect = QRect(-frame - 4, ART_RULE - 4 * frame - 8,
self.width() + 2 * frame + 8, 4 * frame + 8)
painter.save()
painter.setClipRect(0, 0, self.width(), ART_RULE)
self.style().drawPrimitive(QStyle.PrimitiveElement.PE_Frame,
option, painter, self)
painter.restore()
area = self.rect().adjusted(0, ART_RULE, 0, 0)
scaled = self._pixmap.scaled(
self.size(), Qt.AspectRatioMode.KeepAspectRatioByExpanding,
area.size(), Qt.AspectRatioMode.KeepAspectRatioByExpanding,
Qt.TransformationMode.SmoothTransformation)
x = (self.width() - scaled.width()) // 2
y = (self.height() - scaled.height()) // 2
x = (area.width() - scaled.width()) // 2
y = area.top() + (area.height() - scaled.height()) // 2
painter.setClipRect(area)
painter.drawPixmap(x, y, scaled)
+2 -1
View File
@@ -138,6 +138,7 @@ def test_no_art_panel_sits_below_the_frame(qapp, tmp_path):
def test_real_art_goes_inside_the_frame(qapp, tmp_path):
from PyQt6.QtGui import QPixmap
from lintunes.gui.sidebar import ART_RULE
window, sidebar = _sidebar(qapp, tmp_path)
art = sidebar.art
pixmap = QPixmap(10, 10)
@@ -146,7 +147,7 @@ def test_real_art_goes_inside_the_frame(qapp, tmp_path):
art.has_art_changed.emit(True)
art._fit_height()
assert art.parentWidget() is sidebar.list_area
assert art.height() == art.width()
assert art.height() == art.width() + ART_RULE
art._pixmap = None
art.set_track(None)
assert art.parentWidget() is sidebar
+27
View File
@@ -0,0 +1,27 @@
"""Round 82: the list frame closes above album art too."""
from PyQt6.QtGui import QColor, QPixmap
from tests.test_round80 import _sidebar
def test_art_draws_the_frames_closing_line(qapp, tmp_path):
"""A white cover inside the list's frame starts under a line in the
frame's own color, not straight on from the list."""
from lintunes.gui.sidebar import ART_RULE
window, sidebar = _sidebar(qapp, tmp_path)
art = sidebar.art
pixmap = QPixmap(10, 10)
pixmap.fill(QColor("white"))
art._pixmap = pixmap
art.has_art_changed.emit(True)
art._fit_height()
qapp.processEvents()
group = sidebar.list_area.grab().toImage()
# the frame's own left edge, halfway down the list
frame = group.pixelColor(0, group.height() // 4)
image = art.grab().toImage()
middle = image.width() // 2
for y in range(ART_RULE):
assert image.pixelColor(middle, y) == frame
assert image.pixelColor(middle, ART_RULE) == QColor("white")
window.close()