From 82e7c77251505fa3e9efa316697d797ff153db2b Mon Sep 17 00:00:00 2001 From: pax Date: Thu, 9 Apr 2026 20:29:15 -0500 Subject: [PATCH] main_window: read image dimensions for library popout aspect lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Library items' Post objects were constructed without width/height (library_meta doesn't store them), so the popout got 0/0 and _fit_to_content returned early without setting keep_aspect_ratio. Videos were unaffected because mpv reports dimensions later via VideoSizeKnown. Images had no second chance — the aspect lock was never set, and manual window resizing stretched them freely. Fix: new _image_dimensions(path) reads the actual pixel size from the file via QPixmap before constructing the Post. The Post now carries real width/height. _update_fullscreen moved to run AFTER Post construction so cp.width/cp.height are populated when the popout reads them for pre-fit + aspect lock. Not a regression from the templates refactor — pre-existing gap in the library display path. --- booru_viewer/gui/main_window.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/booru_viewer/gui/main_window.py b/booru_viewer/gui/main_window.py index 8e9ec41..a447ca5 100644 --- a/booru_viewer/gui/main_window.py +++ b/booru_viewer/gui/main_window.py @@ -1545,13 +1545,33 @@ class BooruApp(QMainWindow): def _on_library_activated(self, path: str) -> None: self._show_library_post(path) + @staticmethod + def _image_dimensions(path: str) -> tuple[int, int]: + """Read image width/height from a local file. Returns (0, 0) + on failure or for video files (mpv reports those itself).""" + from .media.constants import _is_video + if _is_video(path): + return 0, 0 + try: + pix = QPixmap(path) + if not pix.isNull(): + return pix.width(), pix.height() + except Exception: + pass + return 0, 0 + def _show_library_post(self, path: str) -> None: + # Read actual image dimensions so the popout can pre-fit and + # set keep_aspect_ratio. library_meta doesn't store w/h, so + # without this the popout gets 0/0 and skips the aspect lock. + img_w, img_h = self._image_dimensions(path) self._set_preview_media(path, Path(path).name) - self._update_fullscreen(path, Path(path).name) self._set_library_info(path) # Build a Post from library metadata so toolbar actions work. # Templated filenames go through library_meta.filename; # legacy digit-stem files use int(stem). + # width/height come from the file itself (library_meta doesn't + # store them) so the popout can pre-fit and set keep_aspect_ratio. post_id = self._post_id_from_library_path(Path(path)) if post_id is not None: from ..core.api.base import Post @@ -1562,6 +1582,7 @@ class BooruApp(QMainWindow): score=meta.get("score", 0), rating=meta.get("rating"), source=meta.get("source"), tag_categories=meta.get("tag_categories", {}), + width=img_w, height=img_h, ) self._preview._current_post = post self._preview._current_site_id = self._site_combo.currentData() @@ -1570,6 +1591,9 @@ class BooruApp(QMainWindow): else: self._preview._current_post = None self._preview.update_save_state(True) + # _update_fullscreen reads cp.width/cp.height from _current_post, + # so it runs AFTER the Post is constructed with real dimensions. + self._update_fullscreen(path, Path(path).name) def _on_bookmark_selected(self, fav) -> None: self._status.showMessage(f"Bookmark #{fav.post_id}")