v0.51.1: album art sits under the list frame's closing line, like the empty panel
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
"""LinTunes — iTunes-style music library manager and player for Linux."""
|
"""LinTunes — iTunes-style music library manager and player for Linux."""
|
||||||
|
|
||||||
__version__ = "0.51.0"
|
__version__ = "0.51.1"
|
||||||
|
|||||||
+28
-6
@@ -2,9 +2,9 @@ from PyQt6.QtWidgets import (
|
|||||||
QWidget, QVBoxLayout, QPushButton, QTreeWidget, QTreeWidgetItem, QMenu,
|
QWidget, QVBoxLayout, QPushButton, QTreeWidget, QTreeWidgetItem, QMenu,
|
||||||
QInputDialog, QMessageBox, QAbstractItemView, QLineEdit, QApplication,
|
QInputDialog, QMessageBox, QAbstractItemView, QLineEdit, QApplication,
|
||||||
QHBoxLayout, QListWidget, QListWidgetItem, QStackedWidget, QSizePolicy,
|
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 PyQt6.QtGui import QBrush, QPainter, QPalette, QPixmap
|
||||||
|
|
||||||
from lintunes.models import PlaylistType
|
from lintunes.models import PlaylistType
|
||||||
@@ -267,6 +267,10 @@ class FriendPlaylistList(QListWidget):
|
|||||||
# it, with the visualizer's corners.
|
# it, with the visualizer's corners.
|
||||||
NO_ART_GAP = 6
|
NO_ART_GAP = 6
|
||||||
NO_ART_RADIUS = 8
|
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):
|
class SidebarArt(QWidget):
|
||||||
@@ -326,7 +330,7 @@ class SidebarArt(QWidget):
|
|||||||
def _fit_height(self):
|
def _fit_height(self):
|
||||||
# Keep it square: height follows the sidebar's width (plus the gap
|
# Keep it square: height follows the sidebar's width (plus the gap
|
||||||
# above the empty panel)
|
# 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:
|
if self.height() != height:
|
||||||
self.setFixedHeight(height)
|
self.setFixedHeight(height)
|
||||||
|
|
||||||
@@ -358,11 +362,29 @@ class SidebarArt(QWidget):
|
|||||||
self.palette().alternateBase().color(),
|
self.palette().alternateBase().color(),
|
||||||
NO_ART_RADIUS, like=CONTROL_HEIGHT)
|
NO_ART_RADIUS, like=CONTROL_HEIGHT)
|
||||||
return
|
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(
|
scaled = self._pixmap.scaled(
|
||||||
self.size(), Qt.AspectRatioMode.KeepAspectRatioByExpanding,
|
area.size(), Qt.AspectRatioMode.KeepAspectRatioByExpanding,
|
||||||
Qt.TransformationMode.SmoothTransformation)
|
Qt.TransformationMode.SmoothTransformation)
|
||||||
x = (self.width() - scaled.width()) // 2
|
x = (area.width() - scaled.width()) // 2
|
||||||
y = (self.height() - scaled.height()) // 2
|
y = area.top() + (area.height() - scaled.height()) // 2
|
||||||
|
painter.setClipRect(area)
|
||||||
painter.drawPixmap(x, y, scaled)
|
painter.drawPixmap(x, y, scaled)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
def test_real_art_goes_inside_the_frame(qapp, tmp_path):
|
||||||
from PyQt6.QtGui import QPixmap
|
from PyQt6.QtGui import QPixmap
|
||||||
|
from lintunes.gui.sidebar import ART_RULE
|
||||||
window, sidebar = _sidebar(qapp, tmp_path)
|
window, sidebar = _sidebar(qapp, tmp_path)
|
||||||
art = sidebar.art
|
art = sidebar.art
|
||||||
pixmap = QPixmap(10, 10)
|
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.has_art_changed.emit(True)
|
||||||
art._fit_height()
|
art._fit_height()
|
||||||
assert art.parentWidget() is sidebar.list_area
|
assert art.parentWidget() is sidebar.list_area
|
||||||
assert art.height() == art.width()
|
assert art.height() == art.width() + ART_RULE
|
||||||
art._pixmap = None
|
art._pixmap = None
|
||||||
art.set_track(None)
|
art.set_track(None)
|
||||||
assert art.parentWidget() is sidebar
|
assert art.parentWidget() is sidebar
|
||||||
|
|||||||
@@ -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()
|
||||||
Reference in New Issue
Block a user