diff --git a/beeref/commands.py b/beeref/commands.py index ae489b8..f89790a 100644 --- a/beeref/commands.py +++ b/beeref/commands.py @@ -55,11 +55,10 @@ class DeleteItems(QtGui.QUndoCommand): class MoveItemsBy(QtGui.QUndoCommand): - def __init__(self, items, x, y, ignore_first_redo=False): + def __init__(self, items, delta, ignore_first_redo=False): super().__init__('Move items') self.items = items - self.delta_x = x - self.delta_y = y + self.delta = delta self.ignore_first_redo = ignore_first_redo def redo(self): @@ -67,11 +66,11 @@ class MoveItemsBy(QtGui.QUndoCommand): self.ignore_first_redo = False return for item in self.items: - item.moveBy(self.delta_x, self.delta_y) + item.moveBy(self.delta.x(), self.delta.y()) def undo(self): for item in self.items: - item.moveBy(-self.delta_x, -self.delta_y) + item.moveBy(-self.delta.x(), -self.delta.y()) class ScaleItemsBy(QtGui.QUndoCommand): diff --git a/beeref/scene.py b/beeref/scene.py index 3147c45..956ebb3 100644 --- a/beeref/scene.py +++ b/beeref/scene.py @@ -117,7 +117,7 @@ class BeeGraphicsScene(QtWidgets.QGraphicsScene): if not delta.isNull(): self.undo_stack.push( commands.MoveItemsBy(self.selectedItems(), - delta.x(), delta.y(), + delta, ignore_first_redo=True)) self.move_active = False super().mouseReleaseEvent(event) diff --git a/beeref/selection.py b/beeref/selection.py index c02bd60..3851445 100644 --- a/beeref/selection.py +++ b/beeref/selection.py @@ -178,7 +178,7 @@ class SelectableMixin: # See if we need to change the cursor for scale areas if self.get_scale_bounds(corner).contains(event.pos()): direction = self.get_scale_direction(corner) - if direction[0] == direction[1]: + if direction.x() == direction.y(): self.setCursor(Qt.CursorShape.SizeFDiagCursor) else: self.setCursor(Qt.CursorShape.SizeBDiagCursor) @@ -218,7 +218,7 @@ class SelectableMixin: imgsize = self.width + self.height p = event.scenePos() - self.scale_start direction = self.scale_direction - delta = (direction[0] * p.x() + direction[1] * p.y()) / imgsize + delta = QtCore.QPointF.dotProduct(direction, p) / imgsize return (self.scale_orig_factor + delta) / self.scale_orig_factor def get_scale_anchor(self, item, corner): @@ -228,9 +228,8 @@ class SelectableMixin: def get_scale_direction(self, corner): """Get the direction in which the scale for this corner increases""" - x = 1 if corner.x() > 0 else -1 - y = 1 if corner.y() > 0 else -1 - return (x, y) + return QtCore.QPointF(1 if corner.x() > 0 else -1, + 1 if corner.y() > 0 else -1) def translate_for_scale_anchor(self, scale_factor): """Adjust the item's position so that a scale with the given scale diff --git a/tests/test_commands.py b/tests/test_commands.py index e9f089a..1ec5c5a 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -57,7 +57,7 @@ class MoveItemsByTestCase(BeeTestCase): item1.setPos(0, 0) item2 = BeePixmapItem(QtGui.QImage()) item2.setPos(30, 40) - command = commands.MoveItemsBy([item1, item2], 50, 100) + command = commands.MoveItemsBy([item1, item2], QtCore.QPointF(50, 100)) command.redo() assert item1.pos().x() == 50 assert item1.pos().y() == 100 @@ -75,7 +75,9 @@ class MoveItemsByTestCase(BeeTestCase): item1.setPos(0, 0) item2 = BeePixmapItem(QtGui.QImage()) item2.setPos(30, 40) - command = commands.MoveItemsBy([item1, item2], 50, 100, True) + command = commands.MoveItemsBy([item1, item2], + QtCore.QPointF(50, 100), + ignore_first_redo=True) command.redo() assert item1.pos().x() == 0 assert item1.pos().y() == 0 diff --git a/tests/test_scene.py b/tests/test_scene.py index ad77211..9dccf3d 100644 --- a/tests/test_scene.py +++ b/tests/test_scene.py @@ -155,8 +155,8 @@ class BeeGraphicsSceneNormalizeTestCase(BeeTestCase): cmd = args[0] assert cmd.items == [item] assert cmd.ignore_first_redo is True - assert cmd.delta_x == 10 - assert cmd.delta_y == 20 + assert cmd.delta.x() == 10 + assert cmd.delta.y() == 20 mouse_mock.assert_called_once_with(event) assert self.scene.move_active is False diff --git a/tests/test_selection.py b/tests/test_selection.py index 3987c4f..35d8dc3 100644 --- a/tests/test_selection.py +++ b/tests/test_selection.py @@ -258,19 +258,19 @@ class SelectableMixinTestCase(SelectableMixinBaseTestCase): class SelectableMixinScalingTestCase(SelectableMixinBaseTestCase): def test_get_scale_factor_bottomright(self): - self.item.scale_start = QtCore.QPoint(10, 10) - self.item.scale_direction = (1, 1) + self.item.scale_start = QtCore.QPointF(10, 10) + self.item.scale_direction = QtCore.QPointF(1, 1) self.item.scale_orig_factor = 1 event = MagicMock() - event.scenePos = MagicMock(return_value=QtCore.QPoint(20, 90)) + event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90)) assert self.item.get_scale_factor(event) == 1.5 def test_get_scale_factor_topleft(self): - self.item.scale_start = QtCore.QPoint(10, 10) - self.item.scale_direction = (-1, -1) + self.item.scale_start = QtCore.QPointF(10, 10) + self.item.scale_direction = QtCore.QPointF(-1, -1) self.item.scale_orig_factor = 0.5 event = MagicMock() - event.scenePos = MagicMock(return_value=QtCore.QPoint(-10, -60)) + event.scenePos = MagicMock(return_value=QtCore.QPointF(-10, -60)) assert self.item.get_scale_factor(event) == 2 def test_get_scale_anchor_topleft(self): @@ -301,16 +301,20 @@ class SelectableMixinScalingTestCase(SelectableMixinBaseTestCase): assert anchor.y() == 47 def test_get_scale_direction_topleft(self): - assert self.item.get_scale_direction(QtCore.QPointF(0, 0)) == (-1, -1) + assert self.item.get_scale_direction( + QtCore.QPointF(0, 0)) == QtCore.QPointF(-1, -1) def test_get_scale_direction_bottomright(self): - assert self.item.get_scale_direction(QtCore.QPointF(100, 80)) == (1, 1) + assert self.item.get_scale_direction( + QtCore.QPointF(100, 80)) == QtCore.QPointF(1, 1) def test_get_scale_direction_topright(self): - assert self.item.get_scale_direction(QtCore.QPointF(100, 0)) == (1, -1) + assert self.item.get_scale_direction( + QtCore.QPointF(100, 0)) == QtCore.QPointF(1, -1) def test_get_scale_direction_bottomleft(self): - assert self.item.get_scale_direction(QtCore.QPointF(0, 80)) == (-1, 1) + assert self.item.get_scale_direction( + QtCore.QPointF(0, 80)) == QtCore.QPointF(-1, 1) def test_translate_for_scale_anchor(self): self.item.scale_orig_pos = QtCore.QPoint(50, 70) @@ -381,7 +385,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase): self.item.mousePressEvent(self.event) assert self.item.scale_active is True assert self.item.scale_start == QtCore.QPointF(66, 99) - assert self.item.scale_direction == (-1, -1) + assert self.item.scale_direction == QtCore.QPointF(-1, -1) assert self.item.scale_orig_factor == 1 assert self.item.scale_orig_pos == QtCore.QPointF(0, 0) @@ -393,7 +397,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase): return_value=Qt.MouseButtons.LeftButton) self.item.mousePressEvent(self.event) assert self.item.scale_active is True - assert self.item.scale_direction == (1, 1) + assert self.item.scale_direction == QtCore.QPointF(1, 1) assert self.item.scale_start == QtCore.QPointF(66, 99) assert self.item.scale_orig_factor == 1 assert self.item.scale_orig_pos == QtCore.QPointF(0, 0) @@ -423,7 +427,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase): def test_move_event_when_scale_action(self): self.event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90)) self.item.scale_active = True - self.item.scale_direction = (1, 1) + self.item.scale_direction = QtCore.QPointF(1, 1) self.item.scale_anchor = QtCore.QPointF(100, 80) self.item.scale_start = QtCore.QPointF(10, 10) self.item.scale_orig_factor = 1 @@ -441,7 +445,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase): def test_mouse_release_event_when_scale_action(self): self.event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90)) self.item.scale_active = True - self.item.scale_direction = (1, 1) + self.item.scale_direction = QtCore.QPointF(1, 1) self.item.scale_anchor = QtCore.QPointF(100, 80) self.item.scale_start = QtCore.QPointF(10, 10) self.item.scale_orig_factor = 1