From 1b14e186581207a846c13494764d674584f6c112 Mon Sep 17 00:00:00 2001 From: Rebecca Breu Date: Thu, 29 Jul 2021 20:41:13 +0200 Subject: [PATCH] Fix hover on scale areas for narrows items --- CHANGELOG.rst | 5 ++ README.rst | 2 +- beeref/selection.py | 43 ++++++--- beeref/view.py | 1 - tests/selection/test_selectable_mixin.py | 108 ++++++++--------------- 5 files changed, 76 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5796cad..1fe1685 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,11 @@ Changed * Make debug log file less verbose +Fixed +----- + +* Hovering over the scale handles of very narrow items now displays correct cursor + 0.1.1 - 2021-07-18 ================== diff --git a/README.rst b/README.rst index be98dd0..f4ace54 100644 --- a/README.rst +++ b/README.rst @@ -46,7 +46,7 @@ To get the current delevopment version, you need to have a working Python 3 envi Then run ``beeref`` or ``beeref filename.bee``. -If there are issues starting the application, run it with the environment varibale ``QT_DEBUG_PLUGINS`` set to 1, for example from a Linux shell:: +If there are issues starting the application, run it with the environment variable ``QT_DEBUG_PLUGINS`` set to 1, for example from a Linux shell:: QT_DEBUG_PLUGINS=1 beeref diff --git a/beeref/selection.py b/beeref/selection.py index 2d9ab8e..82683e0 100644 --- a/beeref/selection.py +++ b/beeref/selection.py @@ -333,16 +333,7 @@ class SelectableMixin(BaseItemMixin): for corner in self.corners: # See if we need to change the cursor for interactable areas if self.get_scale_bounds(corner).contains(event.pos()): - self.event_anchor = self.center_scene_coords - angle = self.get_rotate_angle(self.mapToScene(corner)) - if abs(angle) >= 157.5 or abs(angle) <= 22.5: - self.setCursor(Qt.CursorShape.SizeVerCursor) - elif 112.5 <= angle <= 157.5 or -67.5 <= angle <= -22.5: - self.setCursor(Qt.CursorShape.SizeFDiagCursor) - elif 67.5 <= abs(angle) <= 112.5: - self.setCursor(Qt.CursorShape.SizeHorCursor) - else: - self.setCursor(Qt.CursorShape.SizeBDiagCursor) + self.setCursor(self.get_corner_scale_cursor(corner)) return elif self.get_rotate_bounds(corner).contains(event.pos()): self.setCursor(BeeAssets().cursor_rotate) @@ -450,9 +441,39 @@ class SelectableMixin(BaseItemMixin): return delta + def get_corner_scale_cursor(self, corner): + """Gets the scale cursor for the given corner.""" + + rotation = self.rotation() % 180 + flipped = self.flip() == -1 + + if corner in (QtCore.QPointF(0, 0), + QtCore.QPointF(self.width, self.height)): + if 22.5 < rotation < 67.5: + return Qt.CursorShape.SizeVerCursor + elif 67.5 < rotation < 112.5: + return (Qt.CursorShape.SizeFDiagCursor if flipped + else Qt.CursorShape.SizeBDiagCursor) + elif 112.5 < rotation < 157.5: + return Qt.CursorShape.SizeHorCursor + else: + return (Qt.CursorShape.SizeBDiagCursor if flipped + else Qt.CursorShape.SizeFDiagCursor) + else: + if 22.5 < rotation < 67.5: + return Qt.CursorShape.SizeHorCursor + elif 67.5 < rotation < 112.5: + return (Qt.CursorShape.SizeBDiagCursor if flipped + else Qt.CursorShape.SizeFDiagCursor) + elif 112.5 < rotation < 157.5: + return Qt.CursorShape.SizeVerCursor + else: + return (Qt.CursorShape.SizeFDiagCursor if flipped + else Qt.CursorShape.SizeBDiagCursor) + def get_edge_flips_v(self, edge): """Returns ``True`` if the given edge invokes a horizontal flip, - ``False`` if it invokes a vertacal flip.""" + ``False`` if it invokes a vertical flip.""" if 45 < self.rotation() < 135 or 225 < self.rotation() < 315: return not edge['flip_v'] diff --git a/beeref/view.py b/beeref/view.py index 8563e5f..654059f 100644 --- a/beeref/view.py +++ b/beeref/view.py @@ -125,7 +125,6 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin): for f in cls.supportedImageFormats(): string = f'*.{f.data().decode()}' formats.extend((string, string.upper())) - print(formats) return ' '.join(formats) def get_view_center(self): diff --git a/tests/selection/test_selectable_mixin.py b/tests/selection/test_selectable_mixin.py index 60994e0..cd24db8 100644 --- a/tests/selection/test_selectable_mixin.py +++ b/tests/selection/test_selectable_mixin.py @@ -556,87 +556,55 @@ def test_hover_move_event_no_selection(view, item): item.setCursor.assert_not_called() -def test_hover_move_event_topleft_scale(view, item): +@mark.parametrize('pos,flipped,rotation, expected', + [((0, 0), False, 0, 'SizeFDiagCursor'), + ((100, 80), False, 0, 'SizeFDiagCursor'), + ((100, 0), False, 0, 'SizeBDiagCursor'), + ((0, 0), False, 90, 'SizeBDiagCursor'), + ((0, 0), False, 45, 'SizeVerCursor'), + ((0, 0), False, 135, 'SizeHorCursor'), + ((0, 80), False, 45, 'SizeHorCursor'), + ((0, 80), False, 90, 'SizeFDiagCursor'), + ((0, 80), False, 135, 'SizeVerCursor'), + ((0, 80), True, 0, 'SizeFDiagCursor'), + ((100, 0), True, 0, 'SizeFDiagCursor'), + ((100, 80), True, 0, 'SizeBDiagCursor'), + ((0, 80), True, 90, 'SizeBDiagCursor'), + ((0, 80), True, 45, 'SizeHorCursor'), + ((0, 0), True, 135, 'SizeHorCursor'), + ((0, 0), True, 45, 'SizeVerCursor'), + ((0, 0), True, 90, 'SizeFDiagCursor'), + ((0, 0), True, 135, 'SizeHorCursor')]) +def test_hover_move_event_topleft_scale( + pos, flipped, rotation, expected, view, item): view.scene.addItem(item) item.setSelected(True) + if flipped: + item.do_flip() + item.setRotation(rotation) event = MagicMock() - event.pos.return_value = QtCore.QPointF(0, 0) + event.pos.return_value = QtCore.QPointF(*pos) 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.hoverMoveEvent(event) + assert item.cursor() == getattr(Qt.CursorShape, expected) + + +def test_hover_move_event_bottomright_scale_very_wide_item(view, item): + view.scene.addItem(item) + item.setSelected(True) + event = MagicMock() + event.pos.return_value = QtCore.QPointF(1000, 100) + with patch('beeref.items.BeePixmapItem.width', + new_callable=PropertyMock, return_value=1000): + with patch('beeref.items.BeePixmapItem.height', + new_callable=PropertyMock, return_value=100): + item.hoverMoveEvent(event) assert item.cursor() == Qt.CursorShape.SizeFDiagCursor -def test_hover_move_event_bottomright_scale(view, item): - view.scene.addItem(item) - item.setSelected(True) - event = MagicMock() - event.pos.return_value = QtCore.QPointF(100, 80) - 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.hoverMoveEvent(event) - assert item.cursor() == Qt.CursorShape.SizeFDiagCursor - - -def test_hover_move_event_topright_scale(view, item): - view.scene.addItem(item) - item.setSelected(True) - event = MagicMock() - event.pos.return_value = QtCore.QPointF(100, 0) - 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.hoverMoveEvent(event) - assert item.cursor() == Qt.CursorShape.SizeBDiagCursor - - -def test_hover_move_event_topright_scale_rotated_90(view, item): - view.scene.addItem(item) - item.setRotation(90) - item.setSelected(True) - event = MagicMock() - event.pos.return_value = QtCore.QPointF(0, 0) - 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.hoverMoveEvent(event) - assert item.cursor() == Qt.CursorShape.SizeBDiagCursor - - -def test_hover_move_event_top_scale_rotated_45(view, item): - view.scene.addItem(item) - item.setRotation(45) - item.setSelected(True) - event = MagicMock() - event.pos.return_value = QtCore.QPointF(0, 0) - 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.hoverMoveEvent(event) - assert item.cursor() == Qt.CursorShape.SizeVerCursor - - -def test_hover_move_event_left_scale_rotated_45(view, item): - view.scene.addItem(item) - item.setRotation(45) - item.setSelected(True) - event = MagicMock() - event.pos.return_value = QtCore.QPointF(0, 80) - 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.hoverMoveEvent(event) - assert item.cursor() == Qt.CursorShape.SizeHorCursor - - def test_hover_move_event_rotate(view, item): view.scene.addItem(item) item.setSelected(True)