From 95b024ee4245848613f32fc78351e3d76bad5034 Mon Sep 17 00:00:00 2001 From: Rebecca Breu Date: Sun, 26 May 2024 12:03:38 +0200 Subject: [PATCH] Make arrange method for importing images configurable --- CHANGELOG.rst | 3 +++ beeref/config/settings.py | 5 +++++ beeref/scene.py | 14 +++++++++++++- beeref/view.py | 2 +- beeref/widgets/settings.py | 18 ++++++++++++++++-- tests/test_scene.py | 15 +++++++++++++++ 6 files changed, 53 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 643f56e..903ad8b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,9 @@ Added The confirmation dialog can be disalbed in: Settings -> Miscellaneous -> Confirm when closing an unsaved file * Add option to arrange by filename (Arrange -> Square (by filename)) +* Added a setting to choose the default arrange method on importing + images in batch. + (Settings -> Settings -> Images & Items -> Default Arrange Method). Fixed ----- diff --git a/beeref/config/settings.py b/beeref/config/settings.py index 917bdde..c6743de 100644 --- a/beeref/config/settings.py +++ b/beeref/config/settings.py @@ -122,6 +122,11 @@ class BeeSettings(QtCore.QSettings): 'cast': int, 'validate': lambda x: 0 <= x <= 200, }, + 'Items/arrange_default': { + 'default': 'optimal', + 'validate': lambda x: x in ( + 'optimal', 'horizontal', 'vertical', 'square'), + }, 'Items/image_allocation_limit': { 'default': 256, 'cast': int, diff --git a/beeref/scene.py b/beeref/scene.py index cbb4f43..56325c2 100644 --- a/beeref/scene.py +++ b/beeref/scene.py @@ -13,9 +13,10 @@ # You should have received a copy of the GNU General Public License # along with BeeRef. If not, see . -from queue import Queue +from functools import partial import logging import math +from queue import Queue from PyQt6 import QtCore, QtWidgets, QtGui from PyQt6.QtCore import Qt @@ -178,6 +179,17 @@ def normalize_size(self): self.undo_stack.push( commands.NormalizeItems(items, scale_factors)) + def arrange_default(self): + default = self.settings.valueOrDefault('Items/arrange_default') + MAPPING = { + 'optimal': self.arrange_optimal, + 'horizontal': self.arrange, + 'vertical': partial(self.arrange, vertical=True), + 'square': self.arrange_square, + } + + MAPPING[default]() + def arrange(self, vertical=False): """Arrange items in a line (horizontally or vertically).""" diff --git a/beeref/view.py b/beeref/view.py index df9c2e3..b54453a 100644 --- a/beeref/view.py +++ b/beeref/view.py @@ -612,7 +612,7 @@ def on_insert_images_finished(self, new_scene, filename, errors): 'Problem loading images', msg + IMG_LOADING_ERROR_MSG + errornames) self.scene.add_queued_items() - self.scene.arrange_optimal() + self.scene.arrange_default() self.undo_stack.endMacro() if new_scene: self.on_action_fit_scene() diff --git a/beeref/widgets/settings.py b/beeref/widgets/settings.py index b8c2b3f..26bdcf2 100644 --- a/beeref/widgets/settings.py +++ b/beeref/widgets/settings.py @@ -133,6 +133,19 @@ def convert_value_from_qt(self, value): return value == Qt.CheckState.Checked +class ArrangeDefaultWidget(RadioGroup): + TITLE = 'Default Arrange Method:' + HELPTEXT = ('How images are arranged when inserted in batch') + KEY = 'Items/arrange_default' + OPTIONS = ( + ('optimal', 'Optimal', 'Arrange Optimal'), + ('horizontal', 'Horizontal (by filename)', + 'Arrange Horizontal (by filename)'), + ('vertical', 'Vertical (by filename)', + 'Arrange Vertical (by filename)'), + ('square', 'Square (by filename)', 'Arrannge Square (by filename)')) + + class ImageStorageFormatWidget(RadioGroup): TITLE = 'Image Storage Format:' HELPTEXT = ('How images are stored inside bee files.' @@ -191,8 +204,9 @@ def __init__(self, parent): items_layout = QtWidgets.QGridLayout() items.setLayout(items_layout) items_layout.addWidget(ImageStorageFormatWidget(), 0, 0) - items_layout.addWidget(ArrangeGapWidget(), 0, 1) - items_layout.addWidget(AllocationLimitWidget(), 1, 0) + items_layout.addWidget(AllocationLimitWidget(), 0, 1) + items_layout.addWidget(ArrangeGapWidget(), 1, 0) + items_layout.addWidget(ArrangeDefaultWidget(), 1, 1) tabs.addTab(items, '&Images && Items') layout = QtWidgets.QVBoxLayout() diff --git a/tests/test_scene.py b/tests/test_scene.py index 138d905..6bbed5a 100644 --- a/tests/test_scene.py +++ b/tests/test_scene.py @@ -1,6 +1,7 @@ import math from unittest.mock import patch, MagicMock +import pytest from pytest import approx from PyQt6 import QtCore, QtGui, QtWidgets @@ -249,6 +250,20 @@ def test_normalize_size_when_no_items(view): view.scene.cancel_crop_mode.assert_called_once_with() +@pytest.mark.parametrize('value,expected_func,expected_kwargs', + [('optimal', 'arrange_optimal', {}), + ('horizontal', 'arrange', {}), + ('vertical', 'arrange', {'vertical': True}), + ('square', 'arrange_square', {})]) +def test_arrange_default( + value, expected_func, expected_kwargs, settings, view): + settings.setValue('Items/arrange_default', value) + setattr(view.scene, expected_func, MagicMock()) + view.scene.arrange_default() + getattr(view.scene, expected_func).assert_called_once_with( + **expected_kwargs) + + def test_arrange_horizontal(view): item1 = BeePixmapItem(QtGui.QImage()) item1.filename = 'foo.png'