diff --git a/docs/changelog.rst b/docs/changelog.rst index 8c6717a97..ff401f729 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -91,6 +91,7 @@ Added: the original image. Thanks `@Yutsuten`_ for reviving this! * Add the ``none`` sorting type for the ``sort.image_order`` and ``sort.directory_order`` options, implemented by `@buzzingwires`_ +* Add the ``thumbnail.save`` option, implemented by `@buzzingwires`_ Changed: ^^^^^^^^ diff --git a/tests/unit/utils/test_thumbnail_manager.py b/tests/unit/utils/test_thumbnail_manager.py index f7a155035..34a6510d1 100644 --- a/tests/unit/utils/test_thumbnail_manager.py +++ b/tests/unit/utils/test_thumbnail_manager.py @@ -11,6 +11,7 @@ import pytest +from vimiv.api import settings from vimiv.utils import thumbnail_manager @@ -24,6 +25,28 @@ def manager(qtbot, tmp_path, mocker): yield thumbnail_manager.ThumbnailManager(None) +def test_thumbnail_save_disabled(monkeypatch, qtbot, tmp_path, manager): + monkeypatch.setattr(settings.thumbnail.save, "value", False) + no_thumbnail_path = str(tmp_path / "no_thumbnail.jpg") + QPixmap(300, 300).save(no_thumbnail_path, "jpg") + manager.create_thumbnails_async([no_thumbnail_path]) + check_thumbails_created(qtbot, manager, 0) + + +def test_thumbnail_save_disabled_no_delete_old(monkeypatch, qtbot, tmp_path, manager): + monkeypatch.setattr(settings.thumbnail.save, "value", True) + has_thumbnail_path = str(tmp_path / "has_thumbnail.jpg") + QPixmap(300, 300).save(has_thumbnail_path, "jpg") + manager.create_thumbnails_async([has_thumbnail_path]) + check_thumbails_created(qtbot, manager, 1) + + monkeypatch.setattr(settings.thumbnail.save, "value", False) + no_thumbnail_path = str(tmp_path / "no_thumbnail.jpg") + QPixmap(300, 300).save(no_thumbnail_path, "jpg") + manager.create_thumbnails_async([has_thumbnail_path, no_thumbnail_path]) + check_thumbails_created(qtbot, manager, 1) + + @pytest.mark.parametrize("n_paths", (1, 5)) def test_create_n_thumbnails(qtbot, tmp_path, manager, n_paths): # Create images to create thumbnails of diff --git a/vimiv/api/settings.py b/vimiv/api/settings.py index 4d1d9c4c1..af1e3ac3c 100644 --- a/vimiv/api/settings.py +++ b/vimiv/api/settings.py @@ -470,6 +470,11 @@ class thumbnail: # pylint: disable=invalid-name """Namespace for thumbnail related settings.""" size = ThumbnailSizeSetting("thumbnail.size", 128, desc="Size of thumbnails") + save = BoolSetting( + "thumbnail.save", + True, + desc="Save new thumbnails to the disk in the shared icon cache for later use" + ) class slideshow: # pylint: disable=invalid-name diff --git a/vimiv/utils/thumbnail_manager.py b/vimiv/utils/thumbnail_manager.py index a547f0f93..aed51f666 100644 --- a/vimiv/utils/thumbnail_manager.py +++ b/vimiv/utils/thumbnail_manager.py @@ -22,6 +22,7 @@ from PyQt5.QtGui import QIcon, QPixmap, QImage import vimiv +from vimiv import api from vimiv.utils import xdg, imagereader, Pool @@ -131,6 +132,24 @@ def _get_thumbnail_filename(self, path: str) -> str: def _get_source_mtime(path: str) -> int: return int(os.path.getmtime(path)) + def _save_thumbnail(self, image: QImage, thumbnail_path: str) -> None: + """Save the thumbnail file to the disk. + + Args: + image: The QImage representing the thumbnail. + thumbnail_path: Path to which the thumbnail is stored. + Returns: + None. + """ + # First create temporary file and then move it. This avoids + # problems with concurrent access of the thumbnail cache, since + # "move" is an atomic operation + handle, tmp_filename = tempfile.mkstemp(dir=self._manager.directory) + os.close(handle) + os.chmod(tmp_filename, 0o600) + image.save(tmp_filename, format="png") + os.replace(tmp_filename, thumbnail_path) + def _create_thumbnail(self, path: str, thumbnail_path: str) -> QPixmap: """Create thumbnail for an image. @@ -153,14 +172,8 @@ def _create_thumbnail(self, path: str, thumbnail_path: str) -> QPixmap: return self._manager.fail_pixmap for key, value in attributes.items(): image.setText(key, value) - # First create temporary file and then move it. This avoids - # problems with concurrent access of the thumbnail cache, since - # "move" is an atomic operation - handle, tmp_filename = tempfile.mkstemp(dir=self._manager.directory) - os.close(handle) - os.chmod(tmp_filename, 0o600) - image.save(tmp_filename, format="png") - os.replace(tmp_filename, thumbnail_path) + if api.settings.thumbnail.save: + self._save_thumbnail(image, thumbnail_path) return QPixmap(image) def _get_thumbnail_attributes(self, path: str, image: QImage) -> Dict[str, str]: