From 8deb807b062eeea88f11e73459f72567f8c08539 Mon Sep 17 00:00:00 2001 From: Rebecca Breu Date: Tue, 13 Jul 2021 18:25:23 +0200 Subject: [PATCH] Flipping an image on mouse press instead of mouse release This should make it more clear to the user that the edges are click-to-flip instead of drag-to-scale. Before, dragging an edge outside of the handle areas would do nothing and seem broken. --- CHANGELOG.rst | 8 ++++-- beeref/selection.py | 16 +++++++---- tests/selection/test_selectable_mixin.py | 35 +++++++++++++++++++----- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5526f23..25d82d5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,14 +1,18 @@ 0.1.1 - (unreleased) ==================== +Changed +------- + +* Flipping an image now happens on mouse press instead of mouse release + Fixed ----- -* Douple click to zoom an item and double-clicking again should now always +* Double click to zoom an item and double-clicking again should now always correctly go back to the previous position - 0.1.0 - 2021-07-10 ================== diff --git a/beeref/selection.py b/beeref/selection.py index 9a5da68..2c7effd 100644 --- a/beeref/selection.py +++ b/beeref/selection.py @@ -396,6 +396,11 @@ class SelectableMixin(BaseItemMixin): if edge['rect'].contains(event.pos()): self.flip_active = True event.accept() + self.scene().undo_stack.push( + commands.FlipItems( + self.selection_action_items(), + self.center_scene_coords, + vertical=self.get_edge_flips_v(edge))) return super().mousePressEvent(event) @@ -474,6 +479,9 @@ class SelectableMixin(BaseItemMixin): event.accept() return if self.flip_active: + # We have already flipped on MousePress, but we + # still need to accept the event here as to not + # initiate an item move event.accept() return @@ -508,11 +516,9 @@ class SelectableMixin(BaseItemMixin): elif self.flip_active and not just_selected: for edge in self.get_flip_bounds(): if edge['rect'].contains(event.pos()): - self.scene().undo_stack.push( - commands.FlipItems( - self.selection_action_items(), - self.center_scene_coords, - vertical=self.get_edge_flips_v(edge))) + # We have already flipped on MousePress, but we + # still need to accept the event here as to not + # initiate an item move event.accept() self.reset_actions() return diff --git a/tests/selection/test_selectable_mixin.py b/tests/selection/test_selectable_mixin.py index b5f8fc1..60994e0 100644 --- a/tests/selection/test_selectable_mixin.py +++ b/tests/selection/test_selectable_mixin.py @@ -767,6 +767,7 @@ def test_mouse_press_event_just_selected(view, item): with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent'): item.mousePressEvent(event) assert item.just_selected is True + event.accept.assert_not_called() def test_mouse_press_event_previously_selected(view, item): @@ -777,6 +778,7 @@ def test_mouse_press_event_previously_selected(view, item): with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent'): item.mousePressEvent(event) assert item.just_selected is False + event.accept.assert_not_called() def test_mouse_press_event_topleft_scale(view, item): @@ -792,6 +794,7 @@ def test_mouse_press_event_topleft_scale(view, item): assert item.event_direction.x() < 0 assert item.event_direction.y() < 0 assert item.scale_orig_factor == 1 + event.accept.assert_called_once_with() def test_mouse_press_event_bottomright_scale(view, item): @@ -811,6 +814,7 @@ def test_mouse_press_event_bottomright_scale(view, item): assert item.event_direction.x() > 0 assert item.event_direction.y() > 0 assert item.scale_orig_factor == 1 + event.accept.assert_called_once_with() def test_mouse_press_event_rotate(view, item): @@ -828,6 +832,7 @@ def test_mouse_press_event_rotate(view, item): assert item.rotate_active is True assert item.event_anchor == QtCore.QPointF(50, 40) assert item.rotate_orig_degrees == 0 + event.accept.assert_called_once_with() def test_mouse_press_event_flip(view, item): @@ -836,13 +841,21 @@ def test_mouse_press_event_flip(view, item): event = MagicMock() event.pos.return_value = QtCore.QPointF(0, 40) event.button.return_value = Qt.MouseButton.LeftButton + view.scene.undo_stack = MagicMock(push=MagicMock()) with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent'): with patch('beeref.items.BeePixmapItem.width', new_callable=PropertyMock, return_value=100): with patch('beeref.items.BeePixmapItem.height', new_callable=PropertyMock, return_value=80): item.mousePressEvent(event) + args = view.scene.undo_stack.push.call_args_list[0][0] + cmd = args[0] + isinstance(cmd, commands.FlipItems) + assert cmd.items == [item] + assert cmd.anchor == QtCore.QPointF(50, 40) + assert cmd.vertical is False assert item.flip_active is True + event.accept.assert_called_once_with() def test_mouse_press_event_not_selected(view, item): @@ -856,6 +869,7 @@ def test_mouse_press_event_not_selected(view, item): assert item.scale_active is False assert item.rotate_active is False assert item.flip_active is False + event.accept.assert_not_called() def test_mouse_press_event_not_in_handles(view, item): @@ -871,6 +885,7 @@ def test_mouse_press_event_not_in_handles(view, item): assert item.scale_active is False assert item.rotate_active is False assert item.flip_active is False + event.accept.assert_not_called() def test_mouse_move_event_when_no_action_reset_prev_transform(view, item): @@ -883,6 +898,7 @@ def test_mouse_move_event_when_no_action_reset_prev_transform(view, item): item.mouseMoveEvent(event) m.assert_called_once_with(event) view.reset_previous_transform.assert_called_once() + event.accept.assert_not_called() def test_mouse_move_event_when_no_action_doesnt_reset_prev_transf(view, item): @@ -895,6 +911,7 @@ def test_mouse_move_event_when_no_action_doesnt_reset_prev_transf(view, item): item.mouseMoveEvent(event) m.assert_called_once_with(event) view.reset_previous_transform.assert_not_called() + event.accept.assert_not_called() def test_mouse_move_event_when_scale_action(view, item): @@ -915,6 +932,7 @@ def test_mouse_move_event_when_scale_action(view, item): item.mouseMoveEvent(event) m.assert_not_called() assert item.scale() == approx(1.5, 0.01) + event.accept.assert_called_once_with() def test_mouse_move_event_when_rotate_action(view, item): @@ -930,6 +948,7 @@ def test_mouse_move_event_when_rotate_action(view, item): item.mouseMoveEvent(event) m.assert_not_called() assert item.rotation() == 318 + event.accept.assert_called_once_with() def test_mouse_move_event_when_flip_action(view, item): @@ -941,6 +960,7 @@ def test_mouse_move_event_when_flip_action(view, item): with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m: item.mouseMoveEvent(event) m.assert_not_called() + event.accept.assert_called_once_with() def test_mouse_release_event_when_no_action(view, item): @@ -953,6 +973,7 @@ def test_mouse_release_event_when_no_action(view, item): item.mouseReleaseEvent(event) m.assert_called_once_with(event) item.flip_active is False + event.accept.assert_not_called() def test_mouse_release_event_when_scale_action(view, item): @@ -980,6 +1001,7 @@ def test_mouse_release_event_when_scale_action(view, item): assert cmd.anchor == QtCore.QPointF(100, 80) assert cmd.ignore_first_redo is True assert item.scale_active is False + event.accept.assert_called_once_with() def test_mouse_release_event_when_scale_action_zero(view, item): @@ -1000,6 +1022,7 @@ def test_mouse_release_event_when_scale_action_zero(view, item): item.mouseReleaseEvent(event) view.scene.undo_stack.push.assert_not_called() assert item.scale_active is False + event.accept.assert_called_once_with() def test_mouse_release_event_when_rotate_action(view, item): @@ -1022,6 +1045,7 @@ def test_mouse_release_event_when_rotate_action(view, item): assert cmd.anchor == QtCore.QPointF(10, 20) assert cmd.ignore_first_redo is True assert item.rotate_active is False + event.accept.assert_called_once_with() def test_mouse_release_event_when_rotate_action_zero(view, item): @@ -1037,6 +1061,7 @@ def test_mouse_release_event_when_rotate_action_zero(view, item): item.mouseReleaseEvent(event) view.scene.undo_stack.push.assert_not_called() assert item.rotate_active is False + event.accept.assert_called_once_with() def test_mouse_release_event_when_flip_action(view, item): @@ -1051,10 +1076,6 @@ def test_mouse_release_event_when_flip_action(view, item): with patch('beeref.items.BeePixmapItem.height', new_callable=PropertyMock, return_value=80): item.mouseReleaseEvent(event) - args = view.scene.undo_stack.push.call_args_list[0][0] - cmd = args[0] - isinstance(cmd, commands.FlipItems) - assert cmd.items == [item] - assert cmd.anchor == QtCore.QPointF(50, 40) - assert cmd.vertical is False - assert item.flip_active is False + view.scene.undo_stack.push.assert_not_called() + assert item.flip_active is False + event.accept.assert_called_once_with()