Add Flip action to menu

This commit is contained in:
Rebecca Breu 2021-04-11 17:25:56 +02:00
parent 0d4b5da84b
commit 27813f5bd8
6 changed files with 67 additions and 0 deletions

View file

@ -98,4 +98,20 @@ actions = [
'group': 'active_when_selection',
'enabled': False,
},
{
'id': 'flip_horizontally',
'text': 'Flip &Horizontally',
'shortcuts': ['H'],
'callback': 'on_action_flip_horizontally',
'group': 'active_when_selection',
'enabled': False,
},
{
'id': 'flip_vertically',
'text': 'Flip &Vertically',
'shortcuts': ['V'],
'callback': 'on_action_flip_vertically',
'group': 'active_when_selection',
'enabled': False,
},
]

View file

@ -36,6 +36,13 @@ menu_structure = [
'delete',
],
},
{
'menu': '&Transform',
'items': [
'flip_horizontally',
'flip_vertically',
],
},
{
'menu': '&Normalize',
'items': [

View file

@ -86,6 +86,13 @@ class BeeGraphicsScene(QtWidgets.QGraphicsScene):
self.undo_stack.push(
commands.NormalizeItems(self.selectedItems(), scale_factors))
def flip_items(self, vertical=False):
"""Flip selected items."""
self.undo_stack.push(
commands.FlipItems(self.selectedItems(),
self.get_selection_center(),
vertical=vertical))
def has_selection(self):
"""Checks whether there are currently items selected."""
@ -176,6 +183,10 @@ class BeeGraphicsScene(QtWidgets.QGraphicsScene):
QtCore.QPointF(min(x), min(y)),
QtCore.QPointF(max(x), max(y)))
def get_selection_center(self):
rect = self.get_selection_rect()
return (rect.topLeft() + rect.bottomRight()) / 2
def on_selection_change(self):
if self.has_multi_selection():
self.multi_select_item.fit_selection_area(

View file

@ -124,6 +124,12 @@ class BeeGraphicsView(QtWidgets.QGraphicsView, ActionsMixin):
def on_action_normalize_size(self):
self.scene.normalize_size()
def on_action_flip_horizontally(self):
self.scene.flip_items(vertical=False)
def on_action_flip_vertically(self):
self.scene.flip_items(vertical=True)
def open_from_file(self, filename):
logger.info(f'Opening file {filename}')
self.scene.clear()

View file

@ -6,6 +6,7 @@ from pytest import approx
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtCore import Qt
from beeref import commands
from beeref.items import BeePixmapItem
from beeref.scene import BeeGraphicsScene
from .base import BeeTestCase
@ -66,6 +67,21 @@ class BeeGraphicsSceneTestCase(BeeTestCase):
def test_normalize_size_when_no_items(self):
self.scene.normalize_size()
def test_flip_items(self):
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
item.setSelected(True)
self.scene.undo_stack = MagicMock(push=MagicMock())
with patch('beeref.scene.BeeGraphicsScene.get_selection_rect',
return_value=QtCore.QRectF(10, 20, 100, 60)):
self.scene.flip_items(vertical=True)
args = self.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(60, 50)
assert cmd.vertical is True
def test_has_selection_when_no_selection(self):
item = BeePixmapItem(QtGui.QImage())
self.scene.addItem(item)
@ -256,6 +272,7 @@ class BeeGraphicsSceneTestCase(BeeTestCase):
self.scene.undo_stack.push.assert_called_once()
args = self.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
isinstance(cmd, commands.MoveItemsBy)
assert cmd.items == [item]
assert cmd.ignore_first_redo is True
assert cmd.delta.x() == 10
@ -368,6 +385,12 @@ class BeeGraphicsSceneTestCase(BeeTestCase):
assert rect.bottomRight().x() == approx(math.sqrt(2) * 100)
assert rect.bottomRight().y() == approx(math.sqrt(2) * 50)
def test_get_selection_center(self):
with patch('beeref.scene.BeeGraphicsScene.get_selection_rect',
return_value=QtCore.QRectF(10, 20, 100, 60)):
center = self.scene.get_selection_center()
assert center == QtCore.QPointF(60, 50)
def test_on_selection_change_when_multi_selection_new(self):
self.scene.has_multi_selection = MagicMock(return_value=True)
self.scene.multi_select_item.fit_selection_area = MagicMock()

View file

@ -6,6 +6,7 @@ from PyQt6 import QtCore, QtGui
from PyQt6.QtCore import Qt
from beeref.assets import BeeAssets
from beeref import commands
from beeref.items import BeePixmapItem
from beeref.scene import BeeGraphicsScene
from beeref.selection import MultiSelectItem, RubberbandItem
@ -780,6 +781,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase):
self.scene.undo_stack.push.assert_called_once()
args = self.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
isinstance(cmd, commands.ScaleItemsBy)
assert cmd.items == [self.item]
assert cmd.factor == approx(1.5, 0.01)
assert cmd.anchor == QtCore.QPointF(100, 80)
@ -797,6 +799,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase):
self.item.mouseReleaseEvent(self.event)
args = self.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
isinstance(cmd, commands.RotateItemsBy)
assert cmd.items == [self.item]
assert cmd.delta == -42
assert cmd.anchor == QtCore.QPointF(10, 20)
@ -811,6 +814,7 @@ class SelectableMixinMouseEventsTestCase(SelectableMixinBaseTestCase):
self.item.mouseReleaseEvent(self.event)
args = self.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
isinstance(cmd, commands.FlipItems)
assert cmd.items == [self.item]
assert cmd.anchor == QtCore.QPointF(50, 40)
assert cmd.vertical is False