mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
Small enhancements around rotating
This commit is contained in:
parent
d58b46b08f
commit
2d3e6613bf
5 changed files with 97 additions and 6 deletions
|
|
@ -120,16 +120,11 @@ class RotateItemsBy(QtGui.QUndoCommand):
|
|||
for item in self.items:
|
||||
item.setRotation(item.rotation() + self.delta,
|
||||
item.mapFromScene(self.anchor))
|
||||
item.scene().on_selection_change()
|
||||
|
||||
def undo(self):
|
||||
if self.ignore_first_redo:
|
||||
self.ignore_first_redo = False
|
||||
return
|
||||
for item in self.items:
|
||||
item.setRotation(item.rotation() - self.delta,
|
||||
item.mapFromScene(self.anchor))
|
||||
item.scene().on_selection_change()
|
||||
|
||||
|
||||
class NormalizeItems(QtGui.QUndoCommand):
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class BeeGraphicsScene(QtWidgets.QGraphicsScene):
|
|||
self.multi_select_item = MultiSelectItem()
|
||||
self.rubberband_item = RubberbandItem()
|
||||
self.selectionChanged.connect(self.on_selection_change)
|
||||
self.changed.connect(self.on_change)
|
||||
|
||||
def normalize_width_or_height(self, mode):
|
||||
"""Scale the selected images to have the same width or height, as
|
||||
|
|
@ -186,3 +187,10 @@ class BeeGraphicsScene(QtWidgets.QGraphicsScene):
|
|||
if not self.has_multi_selection() and self.multi_select_item.scene():
|
||||
logger.debug('Removing multi select outline')
|
||||
self.removeItem(self.multi_select_item)
|
||||
|
||||
def on_change(self, region):
|
||||
if (self.multi_select_item.scene()
|
||||
and not self.multi_select_item.scale_active
|
||||
and not self.multi_select_item.rotate_active):
|
||||
self.multi_select_item.fit_selection_area(
|
||||
self.get_selection_rect())
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class SelectableMixin(BaseItemMixin):
|
|||
SELECT_LINE_WIDTH = 4 # line width for the selection box
|
||||
SELECT_HANDLE_SIZE = 15 # size of selection handles for scaling
|
||||
SELECT_RESIZE_SIZE = 20 # size of hover area for scaling
|
||||
SELECT_ROTATE_SIZE = 20 # size of hover area for rotating
|
||||
SELECT_ROTATE_SIZE = 15 # size of hover area for rotating
|
||||
|
||||
def init_selectable(self):
|
||||
self.setAcceptHoverEvents(True)
|
||||
|
|
@ -129,6 +129,7 @@ class SelectableMixin(BaseItemMixin):
|
|||
# If it's a single selection, draw the handles:
|
||||
if self.has_selection_handles():
|
||||
pen.setWidth(self.SELECT_HANDLE_SIZE)
|
||||
pen.setCapStyle(Qt.PenCapStyle.RoundCap)
|
||||
painter.setPen(pen)
|
||||
for corner in self.corners:
|
||||
painter.drawPoint(corner)
|
||||
|
|
|
|||
|
|
@ -150,6 +150,58 @@ class ScaleItemsByTestCase(BeeTestCase):
|
|||
assert item2.pos().y() == 100
|
||||
|
||||
|
||||
class RotateItemsByTestCase(BeeTestCase):
|
||||
|
||||
def test_redo_undo(self):
|
||||
item1 = BeePixmapItem(QtGui.QImage())
|
||||
item1.setRotation(0)
|
||||
|
||||
item2 = BeePixmapItem(QtGui.QImage())
|
||||
item2.setRotation(30)
|
||||
item2.setPos(100, 100)
|
||||
command = commands.RotateItemsBy([item1, item2], -90,
|
||||
QtCore.QPointF(100, 100))
|
||||
command.redo()
|
||||
assert item1.rotation() == -90
|
||||
assert item1.pos().x() == 0
|
||||
assert item1.pos().y() == 200
|
||||
assert item2.rotation() == -60
|
||||
assert item2.pos().x() == 100
|
||||
assert item2.pos().y() == 100
|
||||
command.undo()
|
||||
assert item1.rotation() == 0
|
||||
assert item1.pos().x() == 0
|
||||
assert item1.pos().y() == 0
|
||||
assert item2.rotation() == 30
|
||||
assert item2.pos().x() == 100
|
||||
assert item2.pos().y() == 100
|
||||
|
||||
def test_ignore_first_redo(self):
|
||||
item1 = BeePixmapItem(QtGui.QImage())
|
||||
item1.setRotation(0)
|
||||
|
||||
item2 = BeePixmapItem(QtGui.QImage())
|
||||
item2.setRotation(30)
|
||||
item2.setPos(100, 100)
|
||||
command = commands.RotateItemsBy([item1, item2], -90,
|
||||
QtCore.QPointF(100, 100),
|
||||
ignore_first_redo=True)
|
||||
command.redo()
|
||||
assert item1.rotation() == 0
|
||||
assert item1.pos().x() == 0
|
||||
assert item1.pos().y() == 0
|
||||
assert item2.rotation() == 30
|
||||
assert item2.pos().x() == 100
|
||||
assert item2.pos().y() == 100
|
||||
command.redo()
|
||||
assert item1.rotation() == -90
|
||||
assert item1.pos().x() == 0
|
||||
assert item1.pos().y() == 200
|
||||
assert item2.rotation() == -60
|
||||
assert item2.pos().x() == 100
|
||||
assert item2.pos().y() == 100
|
||||
|
||||
|
||||
class NormalizeItemsTestCase(BeeTestCase):
|
||||
|
||||
def test_redo_undo(self):
|
||||
|
|
|
|||
|
|
@ -412,3 +412,38 @@ class BeeGraphicsSceneTestCase(BeeTestCase):
|
|||
m_item = self.scene.multi_select_item
|
||||
m_item.fit_selection_area.assert_not_called()
|
||||
self.scene.removeItem.assert_called_once_with(m_item)
|
||||
|
||||
def test_on_change_when_multi_select_when_no_scale_no_rotate(self):
|
||||
self.scene.addItem(self.scene.multi_select_item)
|
||||
self.scene.multi_select_item.fit_selection_area = MagicMock()
|
||||
self.scene.get_selection_rect = MagicMock()
|
||||
self.scene.multi_select_item.scale_active = False
|
||||
self.scene.multi_select_item.rotate_active = False
|
||||
self.scene.on_change(None)
|
||||
self.scene.multi_select_item.fit_selection_area.assert_called_once()
|
||||
|
||||
def test_on_change_when_multi_select_when_scale_active(self):
|
||||
self.scene.addItem(self.scene.multi_select_item)
|
||||
self.scene.multi_select_item.fit_selection_area = MagicMock()
|
||||
self.scene.get_selection_rect = MagicMock()
|
||||
self.scene.multi_select_item.scale_active = True
|
||||
self.scene.multi_select_item.rotate_active = False
|
||||
self.scene.on_change(None)
|
||||
self.scene.multi_select_item.fit_selection_area.assert_not_called()
|
||||
|
||||
def test_on_change_when_multi_select_when_rotate_active(self):
|
||||
self.scene.addItem(self.scene.multi_select_item)
|
||||
self.scene.multi_select_item.fit_selection_area = MagicMock()
|
||||
self.scene.get_selection_rect = MagicMock()
|
||||
self.scene.multi_select_item.scale_active = False
|
||||
self.scene.multi_select_item.rotate_active = True
|
||||
self.scene.on_change(None)
|
||||
self.scene.multi_select_item.fit_selection_area.assert_not_called()
|
||||
|
||||
def test_on_change_when_no_multi_select(self):
|
||||
self.scene.multi_select_item.fit_selection_area = MagicMock()
|
||||
self.scene.get_selection_rect = MagicMock()
|
||||
self.scene.multi_select_item.scale_active = True
|
||||
self.scene.multi_select_item.rotate_active = True
|
||||
self.scene.on_change(None)
|
||||
self.scene.multi_select_item.fit_selection_area.assert_not_called()
|
||||
|
|
|
|||
Loading…
Reference in a new issue