refactor: remove placeholder video, fix type hints in preview_thumb.py (#906)

* type fixes

* remove `stop_file_use()` method and release the file properly.

* remove "placeholder_mp4" from resources.json
This commit is contained in:
VasigaranAndAngel
2025-05-05 03:43:34 +05:30
committed by GitHub
parent 6598630984
commit efb062034d
5 changed files with 23 additions and 33 deletions

View File

@@ -122,9 +122,5 @@
"thumb_loading": {
"path": "qt/images/thumb_loading.png",
"mode": "pil"
},
"placeholder_mp4": {
"path": "qt/videos/placeholder.mp4",
"mode": "rb"
}
}

View File

@@ -1045,7 +1045,7 @@ class QtDriver(DriverMixin, QObject):
for i, tup in enumerate(pending):
e_id, f = tup
if (origin_path == f) or (not origin_path):
self.preview_panel.thumb.stop_file_use()
self.preview_panel.thumb.media_player.stop()
if delete_file(self.lib.library_dir / f):
self.main_window.statusbar.showMessage(
Translations.format(

View File

@@ -416,9 +416,9 @@ class MediaPlayer(QGraphicsView):
self.scene().removeItem(self.video_preview)
def stop(self) -> None:
"""Clear the filepath and stop the player."""
"""Clear the filepath, stop the player and release the source."""
self.filepath = None
self.player.stop()
self.player.setSource(QUrl())
def play(self, filepath: Path) -> None:
"""Set the source of the QMediaPlayer and play."""

View File

@@ -4,8 +4,8 @@
import io
import time
import typing
from pathlib import Path
from typing import TYPE_CHECKING, override
from warnings import catch_warnings
import cv2
@@ -24,12 +24,11 @@ from tagstudio.qt.helpers.file_tester import is_readable_video
from tagstudio.qt.helpers.qbutton_wrapper import QPushButtonWrapper
from tagstudio.qt.helpers.rounded_pixmap_style import RoundedPixmapStyle
from tagstudio.qt.platform_strings import open_file_str, trash_term
from tagstudio.qt.resource_manager import ResourceManager
from tagstudio.qt.translations import Translations
from tagstudio.qt.widgets.media_player import MediaPlayer
from tagstudio.qt.widgets.thumb_renderer import ThumbRenderer
if typing.TYPE_CHECKING:
if TYPE_CHECKING:
from tagstudio.qt.ts_qt import QtDriver
logger = structlog.get_logger(__name__)
@@ -39,7 +38,7 @@ Image.MAX_IMAGE_PIXELS = None
class PreviewThumb(QWidget):
"""The Preview Panel Widget."""
def __init__(self, library: Library, driver: "QtDriver"):
def __init__(self, library: Library, driver: "QtDriver") -> None:
super().__init__()
self.is_connected = False
@@ -54,6 +53,7 @@ class PreviewThumb(QWidget):
self.image_layout.setStackingMode(QStackedLayout.StackingMode.StackAll)
self.image_layout.setContentsMargins(0, 0, 0, 0)
self.opener: FileOpenerHelper | None = None
self.open_file_action = QAction(Translations["file.open_file"], self)
self.open_explorer_action = QAction(open_file_str(), self)
self.delete_action = QAction(
@@ -133,17 +133,17 @@ class PreviewThumb(QWidget):
def _has_video_changed(self, video: bool) -> None:
self.update_image_size((self.size().width(), self.size().height()))
def _stacked_page_setup(self, page: QWidget, widget: QWidget):
def _stacked_page_setup(self, page: QWidget, widget: QWidget) -> None:
layout = QHBoxLayout(page)
layout.addWidget(widget)
layout.setAlignment(widget, Qt.AlignmentFlag.AlignCenter)
layout.setContentsMargins(0, 0, 0, 0)
page.setLayout(layout)
def set_image_ratio(self, ratio: float):
def set_image_ratio(self, ratio: float) -> None:
self.image_ratio = ratio
def update_image_size(self, size: tuple[int, int], ratio: float | None = None):
def update_image_size(self, size: tuple[int, int], ratio: float | None = None) -> None:
if ratio:
self.set_image_ratio(ratio)
@@ -204,7 +204,7 @@ class PreviewThumb(QWidget):
self.size().height(),
)
def switch_preview(self, preview: str):
def switch_preview(self, preview: str) -> None:
if preview in ["audio", "video"]:
self.media_player.show()
self.image_layout.setCurrentWidget(self.media_player_page)
@@ -229,7 +229,7 @@ class PreviewThumb(QWidget):
self.gif_buffer.close()
self.preview_gif.hide()
def _display_fallback_image(self, filepath: Path, ext: str) -> dict:
def _display_fallback_image(self, filepath: Path, ext: str) -> dict[str, int]:
"""Renders the given file as an image, no matter its media type.
Useful for fallback scenarios.
@@ -244,9 +244,9 @@ class PreviewThumb(QWidget):
)
return self._update_image(filepath, ext)
def _update_image(self, filepath: Path, ext: str) -> dict:
def _update_image(self, filepath: Path, ext: str) -> dict[str, int]:
"""Update the static image preview from a filepath."""
stats: dict = {}
stats: dict[str, int] = {}
self.switch_preview("image")
image: Image.Image | None = None
@@ -287,9 +287,9 @@ class PreviewThumb(QWidget):
return stats
def _update_animation(self, filepath: Path, ext: str) -> dict:
def _update_animation(self, filepath: Path, ext: str) -> dict[str, int]:
"""Update the animated image preview from a filepath."""
stats: dict = {}
stats: dict[str, int] = {}
# Ensure that any movie and buffer from previous animations are cleared.
if self.preview_gif.movie():
@@ -351,8 +351,8 @@ class PreviewThumb(QWidget):
image = Image.fromarray(frame)
return (success, QSize(image.width, image.height))
def _update_media(self, filepath: Path, type: MediaType) -> dict:
stats: dict = {}
def _update_media(self, filepath: Path, type: MediaType) -> dict[str, int]:
stats: dict[str, int] = {}
self.media_player.play(filepath)
@@ -380,9 +380,9 @@ class PreviewThumb(QWidget):
stats["duration"] = self.media_player.player.duration() * 1000
return stats
def update_preview(self, filepath: Path, ext: str) -> dict:
def update_preview(self, filepath: Path, ext: str) -> dict[str, int]:
"""Render a single file preview."""
stats: dict = {}
stats: dict[str, int] = {}
# Video
if MediaCategories.is_ext_in_category(
@@ -448,17 +448,11 @@ class PreviewThumb(QWidget):
return stats
def hide_preview(self):
def hide_preview(self) -> None:
"""Completely hide the file preview."""
self.switch_preview("")
def stop_file_use(self):
"""Stops the use of the currently previewed file. Used to release file permissions."""
logger.info("[PreviewThumb] Stopping file use in video playback...")
# This swaps the video out for a placeholder so the previous video's file
# is no longer in use by this object.
self.media_player.play(ResourceManager.get_path("placeholder_mp4"))
def resizeEvent(self, event: QResizeEvent) -> None: # noqa: N802
@override
def resizeEvent(self, event: QResizeEvent) -> None:
self.update_image_size((self.size().width(), self.size().height()))
return super().resizeEvent(event)