From 75db7a3faa7aac41233b7559e183bf006b3fee7b Mon Sep 17 00:00:00 2001 From: Mathieu Moran Date: Wed, 9 Sep 2026 12:27:46 -0400 Subject: [PATCH] Fill cover grid width in library and store (no dead gap) --- app/gui.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/app/gui.py b/app/gui.py index 3aa8072..800a837 100644 --- a/app/gui.py +++ b/app/gui.py @@ -11,7 +11,7 @@ import sys import threading from pathlib import Path -from PySide6.QtCore import QBuffer, QByteArray, QObject, QRect, QSettings, QSize, Qt, QThread, QTimer, QUrl, Signal +from PySide6.QtCore import QBuffer, QByteArray, QEvent, QObject, QRect, QSettings, QSize, Qt, QThread, QTimer, QUrl, Signal from PySide6.QtGui import QColor, QDesktopServices, QFont, QIcon, QImage, QPainter, QPixmap from PySide6.QtWidgets import ( QAbstractItemView, QApplication, QCheckBox, QComboBox, QDialog, QDialogButtonBox, @@ -342,6 +342,9 @@ class CoverShowcase(QWidget): self.list.customContextMenuRequested.connect(self._on_context_menu) self.list.currentItemChanged.connect(self._on_current_changed) self.list.itemDoubleClicked.connect(self._on_item_double_clicked) + # The vertical scrollbar appearing/disappearing changes the viewport + # width, so re-fit the grid whenever the viewport resizes. + self.list.viewport().installEventFilter(self) layout.addWidget(self.list) self.status = QLabel("") @@ -376,8 +379,37 @@ class CoverShowcase(QWidget): item.setData(Qt.UserRole, it) self.list.addItem(item) + self._fit_grid() self._start_loader(gen) + def _fit_grid(self): + """Stretch cover cells to fill the viewport width (no dead right gap).""" + lst = self.list + vp = lst.viewport().width() + if vp <= 0: + return + spacing = lst.spacing() or 6 + cols = max(1, round((vp + spacing) / (self.GRID_W + spacing))) + cell_w = (vp - (cols - 1) * spacing) // cols + cell_w = max(cell_w, self.ICON_W + 16) + cell_w = min(cell_w, self.GRID_W + 48) + cur = lst.gridSize() + if cur.width() != cell_w or cur.height() != self.GRID_H: + lst.setGridSize(QSize(cell_w, self.GRID_H)) + + def eventFilter(self, obj, event): + if obj is self.list.viewport() and event.type() == QEvent.Resize: + self._fit_grid() + return super().eventFilter(obj, event) + + def showEvent(self, event): + super().showEvent(event) + self._fit_grid() + + def resizeEvent(self, event): + super().resizeEvent(event) + self._fit_grid() + def _start_loader(self, gen): if self._closing or not self.items: return @@ -1731,6 +1763,7 @@ class StorePage(QWidget): self.grid.setContextMenuPolicy(Qt.CustomContextMenu) self.grid.customContextMenuRequested.connect(self._on_grid_menu) self.grid.verticalScrollBar().valueChanged.connect(self._on_scroll) + self.grid.viewport().installEventFilter(self) self.stack.addWidget(self.grid) self.table = QTableWidget(0, 5) @@ -2069,6 +2102,33 @@ class StorePage(QWidget): self._date_queue.append((row, str(rid), system, covers.plain_title(store.display_name(it["name"])) or it["name"])) + def _fit_grid(self): + """Stretch store cover cells to fill the viewport (no dead right gap).""" + vp = self.grid.viewport().width() + if vp <= 0: + return + spacing = self.grid.spacing() or 6 + cols = max(1, round((vp + spacing) / (self.GRID_W + spacing))) + cell_w = (vp - (cols - 1) * spacing) // cols + cell_w = max(cell_w, self.ICON_W + 16) + cell_w = min(cell_w, self.GRID_W + 48) + cur = self.grid.gridSize() + if cur.width() != cell_w or cur.height() != self.GRID_H: + self.grid.setGridSize(QSize(cell_w, self.GRID_H)) + + def eventFilter(self, obj, event): + if obj is self.grid.viewport() and event.type() == QEvent.Resize: + self._fit_grid() + return super().eventFilter(obj, event) + + def showEvent(self, event): + super().showEvent(event) + self._fit_grid() + + def resizeEvent(self, event): + super().resizeEvent(event) + self._fit_grid() + def _finish_fill(self): if self._fill_timer is not None: self._fill_timer.stop()