From e08f0433610921a59cd2b2008374ccb1e7c3c2af Mon Sep 17 00:00:00 2001 From: Rebecca Breu Date: Sat, 4 Sep 2021 15:50:26 +0200 Subject: [PATCH] Fit view when pasting/loading images into empty scene --- CHANGELOG.rst | 4 ++-- beeref/view.py | 19 +++++++++++++++++-- tests/test_view.py | 43 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 873a6a0..c9f5585 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,8 +8,8 @@ Added * You can now add plain text notes and paste text from the clipboard * You can now open bee files from finder on MacOS (by David Andrs) -* You can now drag bee files onto an empty scene to open them - +* Dragging bee files onto an empty scene will now open them +* Adding the first image(s) to a new scene centers the view Changed ------- diff --git a/beeref/view.py b/beeref/view.py index 4f7c3c2..64b7095 100644 --- a/beeref/view.py +++ b/beeref/view.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU General Public License # along with BeeRef. If not, see . +from functools import partial import logging import os import os.path @@ -380,7 +381,14 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): def on_action_debuglog(self): gui.DebugLogDialog(self) - def on_insert_images_finished(self, filename, errors): + def on_insert_images_finished(self, new_scene, filename, errors): + """Callback for when loading of images is finished. + + :param new_scene: True if the scene was empty before, else False + :param filename: Not used, for compability only + :param errors: List of filenames that couldn't be loaded + """ + logger.debug('Insert images finished') if errors: errornames = [ @@ -396,6 +404,8 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): self.scene.add_queued_items() self.scene.arrange_optimal() self.undo_stack.endMacro() + if new_scene: + self.on_action_fit_scene() def do_insert_images(self, filenames, pos=None): if not pos: @@ -408,7 +418,9 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): self.mapToScene(pos), self.scene) self.worker.progress.connect(self.on_items_loaded) - self.worker.finished.connect(self.on_insert_images_finished) + self.worker.finished.connect( + partial(self.on_insert_images_finished, + not self.scene.items())) self.progress = gui.BeeProgressDialog( 'Loading images', worker=self.worker, @@ -464,6 +476,9 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): if not img.isNull(): item = BeePixmapItem(img) self.undo_stack.push(commands.InsertItems(self.scene, [item], pos)) + if len(self.scene.items()) == 1: + # This is the first image in the scene + self.on_action_fit_scene() return text = clipboard.text() if text: diff --git a/tests/test_view.py b/tests/test_view.py index 8a73301..31732c0 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -291,7 +291,7 @@ def test_on_action_debuglog(show_mock, view): @patch('beeref.scene.BeeGraphicsScene.clearSelection') @patch('PyQt6.QtWidgets.QFileDialog.getOpenFileNames') -def test_on_action_insert_images( +def test_on_action_insert_images_new_scene( dialog_mock, clear_mock, view, imgfilename3x3, qtbot): dialog_mock.return_value = ([imgfilename3x3], None) view.on_insert_images_finished = MagicMock() @@ -302,7 +302,24 @@ def test_on_action_insert_images( assert item.isSelected() is True assert item.pixmap() clear_mock.assert_called_once_with() - view.on_insert_images_finished.assert_called_once_with('', []) + view.on_insert_images_finished.assert_called_once_with(True, '', []) + + +@patch('beeref.scene.BeeGraphicsScene.clearSelection') +@patch('PyQt6.QtWidgets.QFileDialog.getOpenFileNames') +def test_on_action_insert_images_existing_scene( + dialog_mock, clear_mock, view, imgfilename3x3, qtbot, item): + view.scene.addItem(item) + dialog_mock.return_value = ([imgfilename3x3], None) + view.on_insert_images_finished = MagicMock() + view.on_action_insert_images() + qtbot.waitUntil(lambda: view.on_insert_images_finished.called is True) + assert len(view.scene.items()) == 2 + item = view.scene.items()[0] + assert item.isSelected() is True + assert item.pixmap() + clear_mock.assert_called_once_with() + view.on_insert_images_finished.assert_called_once_with(False, '', []) @patch('beeref.scene.BeeGraphicsScene.clearSelection') @@ -319,7 +336,7 @@ def test_on_action_insert_images_when_error( assert item.pixmap() clear_mock.assert_called_once_with() view.on_insert_images_finished.assert_called_once_with( - '', ['iaeiae', 'trntrn']) + True, '', ['iaeiae', 'trntrn']) @patch('beeref.scene.BeeGraphicsScene.clearSelection') @@ -360,14 +377,30 @@ def test_on_action_copy_text(clipboard_mock, view, imgfilename3x3): assert mimedata.data('beeref/items') == b'1' +@patch('beeref.view.BeeGraphicsView.on_action_fit_scene') @patch('beeref.scene.BeeGraphicsScene.clearSelection') @patch('PyQt6.QtGui.QClipboard.image') -def test_on_action_paste_external( - clipboard_mock, clear_mock, view, imgfilename3x3): +def test_on_action_paste_external_new_scene( + clipboard_mock, clear_mock, fit_mock, view, imgfilename3x3): clipboard_mock.return_value = QtGui.QImage(imgfilename3x3) view.on_action_paste() assert len(view.scene.items()) == 1 assert view.scene.items()[0].isSelected() is True + fit_mock.assert_called_once_with() + + +@patch('beeref.view.BeeGraphicsView.on_action_fit_scene') +@patch('beeref.scene.BeeGraphicsScene.clearSelection') +@patch('PyQt6.QtGui.QClipboard.image') +def test_on_action_paste_external_existing_scene( + clipboard_mock, clear_mock, fit_mock, view, item, imgfilename3x3): + view.scene.addItem(item) + clipboard_mock.return_value = QtGui.QImage(imgfilename3x3) + view.on_action_paste() + assert len(view.scene.items()) == 2 + assert view.scene.items()[0].isSelected() is True + assert view.scene.items()[1].isSelected() is False + fit_mock.assert_not_called() @patch('beeref.scene.BeeGraphicsScene.clearSelection')