beeref/tests/selection/test_selectable_mixin.py

1088 lines
41 KiB
Python
Raw Normal View History

2021-05-31 16:11:45 +00:00
import math
from pytest import approx, mark
2021-10-07 13:23:37 +00:00
from unittest.mock import patch, MagicMock
2021-05-31 16:11:45 +00:00
from PyQt6 import QtCore, QtGui
from PyQt6.QtCore import Qt
from beeref.assets import BeeAssets
from beeref import commands
from beeref.items import BeePixmapItem
def test_init_selectable(view):
item = BeePixmapItem(QtGui.QImage())
assert item.viewport_scale == 1
assert item.active_mode is None
2021-05-31 16:11:45 +00:00
def test_on_view_scale_change(view, item):
with patch('beeref.items.BeePixmapItem.prepareGeometryChange') as m:
item.on_view_scale_change()
m.assert_called_once()
def test_fixed_length_for_viewport_when_default_scale(view, item):
view.scene.addItem(item)
assert item.fixed_length_for_viewport(100) == 100
assert item._view_scale == 1
def test_fixed_length_for_viewport_when_viewport_scaled(view, item):
view.scene.addItem(item)
view.scale(2, 2)
assert item.fixed_length_for_viewport(100) == 50
assert item._view_scale == 2
def test_fixed_length_for_viewport_when_item_scaled(view, item):
view.scene.addItem(item)
item.setScale(5)
assert item.fixed_length_for_viewport(100) == 20
assert item._view_scale == 1
def test_fixed_length_for_viewport_when_no_scene(view, item):
item._view_scale = 0.5
assert item.fixed_length_for_viewport(100) == 200
def test_resize_size_when_scaled(view, item):
view.scene.addItem(item)
view.scale(2, 2)
item.setScale(2)
item.SELECT_RESIZE_SIZE = 100
assert item.select_resize_size == 25
def test_rotate_size_when_scaled(view, item):
view.scene.addItem(item)
view.scale(2, 2)
item.setScale(2)
item.SELECT_ROTATE_SIZE = 100
assert item.select_rotate_size == 25
def test_select_handle_free_center(view, item):
view.scene.addItem(item)
view.scale(0.5, 0.5)
item.SELECT_FREE_CENTER = 10
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.select_handle_free_center() == QtCore.QRectF(
40, 30, 20, 20)
2021-05-31 16:11:45 +00:00
def test_draw_debug_shape_rect(view, item):
view.scene.addItem(item)
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
2021-05-31 16:11:45 +00:00
item.draw_debug_shape(
painter,
QtCore.QRectF(5, 6, 20, 30),
255, 0, 0)
painter.fillRect.assert_called_once()
painter.fillPath.assert_not_called()
def test_draw_debug_shape_path(view, item):
view.scene.addItem(item)
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
2021-05-31 16:11:45 +00:00
path = QtGui.QPainterPath()
path.addRect(QtCore.QRectF(5, 6, 20, 30))
item.draw_debug_shape(
painter,
path,
0, 255, 0)
painter.fillPath.assert_called_once()
painter.fillRect.assert_not_called()
@patch('beeref.items.BeePixmapItem.draw_debug_shape')
def test_paint_when_not_selected(debug_mock, view, item):
view.scene.addItem(item)
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
2021-05-31 16:11:45 +00:00
item.setSelected(False)
item.paint(painter, None, None)
2021-05-31 16:46:53 +00:00
painter.drawPixmap.assert_called_once()
2021-05-31 16:11:45 +00:00
painter.drawRect.assert_not_called()
painter.drawPoint.assert_not_called()
debug_mock.assert_not_called()
def test_paint_when_selected_single_selection(view, item):
view.scene.addItem(item)
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
2021-05-31 16:11:45 +00:00
item.setSelected(True)
item.paint(painter, None, None)
painter.drawPixmap.assert_called_once()
painter.drawRect.assert_called_once()
assert painter.drawPoint.call_count == 4
def test_paint_when_selected_multi_selection(view, item):
view.scene.addItem(item)
item2 = BeePixmapItem(QtGui.QImage())
item2.setSelected(True)
view.scene.addItem(item2)
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
2021-05-31 16:11:45 +00:00
item.setSelected(True)
item.paint(painter, None, None)
painter.drawPixmap.assert_called_once()
painter.drawRect.assert_called_once()
painter.drawPoint.assert_not_called()
def test_paint_when_debug_shapes(view):
with patch('beeref.selection.commandline_args') as args_mock:
with patch('beeref.items.BeePixmapItem.draw_debug_shape') as m:
args_mock.debug_shapes = True
args_mock.debug_boundingrects = False
args_mock.debug_handles = False
item = BeePixmapItem(QtGui.QImage())
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
item.paint(painter, None, None)
2021-05-31 16:11:45 +00:00
m.assert_called_once()
def test_paint_when_debug_boundingrects(view):
with patch('beeref.selection.commandline_args') as args_mock:
with patch('beeref.items.BeePixmapItem.draw_debug_shape') as m:
args_mock.debug_shapes = False
args_mock.debug_boundingrects = True
args_mock.debug_handles = False
item = BeePixmapItem(QtGui.QImage())
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
item.paint(painter, None, None)
2021-05-31 16:11:45 +00:00
m.assert_called_once()
def test_paint_when_debug_handles(view):
with patch('beeref.selection.commandline_args') as args_mock:
with patch('beeref.items.BeePixmapItem.draw_debug_shape') as m:
args_mock.debug_shapes = False
args_mock.debug_boundingrects = False
args_mock.debug_handles = True
item = BeePixmapItem(QtGui.QImage())
view.scene.addItem(item)
item.setSelected(True)
painter = MagicMock(
combinedTransform=MagicMock(
return_value=MagicMock(
m11=MagicMock(return_value=0.5))))
item.paint(painter, None, None)
2021-05-31 16:11:45 +00:00
m.assert_called()
def test_corners(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert len(item.corners) == 4
assert QtCore.QPointF(0, 0) in item.corners
assert QtCore.QPointF(100, 0) in item.corners
assert QtCore.QPointF(0, 80) in item.corners
assert QtCore.QPointF(100, 80) in item.corners
2021-05-31 16:11:45 +00:00
def test_corners_scene_coords_translated(view, item):
item.setPos(5, 5)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
corners = item.corners_scene_coords
assert len(corners) == 4
assert QtCore.QPointF(5, 5) in corners
assert QtCore.QPointF(105, 5) in corners
assert QtCore.QPointF(5, 85) in corners
assert QtCore.QPointF(105, 85) in corners
2021-05-31 16:11:45 +00:00
def test_corners_scene_coords_scaled(view, item):
item.setScale(2)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
corners = item.corners_scene_coords
assert len(corners) == 4
assert QtCore.QPointF(0, 0) in corners
assert QtCore.QPointF(200, 0) in corners
assert QtCore.QPointF(0, 160) in corners
assert QtCore.QPointF(200, 160) in corners
2021-05-31 16:11:45 +00:00
def test_get_scale_bounds(view, item):
item.SELECT_RESIZE_SIZE = 10
rect = item.get_scale_bounds(
QtCore.QPointF(100, 80)).boundingRect()
assert rect.topLeft().x() == 95
assert rect.topLeft().y() == 75
assert rect.bottomRight().x() == 105
assert rect.bottomRight().y() == 85
def test_get_scale_bounds_with_margin(view, item):
item.SELECT_RESIZE_SIZE = 10
rect = item.get_scale_bounds(
QtCore.QPointF(100, 80), margin=1).boundingRect()
assert rect.topLeft().x() == 94
assert rect.topLeft().y() == 74
assert rect.bottomRight().x() == 106
assert rect.bottomRight().y() == 86
def test_rotate_bounds_bottomright(view, item):
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
path = item.get_rotate_bounds(QtCore.QPointF(100, 80))
assert path.boundingRect().topLeft().x() == 95
assert path.boundingRect().topLeft().y() == 75
assert path.boundingRect().bottomRight().x() == 115
assert path.boundingRect().bottomRight().y() == 95
assert path.contains(QtCore.QPointF(104, 84)) is False
def test_rotate_bounds_topleft(view, item):
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
path = item.get_rotate_bounds(QtCore.QPointF(0, 0))
assert path.boundingRect().topLeft().x() == -15
assert path.boundingRect().topLeft().y() == -15
assert path.boundingRect().bottomRight().x() == 5
assert path.boundingRect().bottomRight().y() == 5
assert path.contains(QtCore.QPointF(-4, -4)) is False
def test_get_flip_bounds(view, item):
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
edges = item.get_flip_bounds()
assert edges[0]['rect'].topLeft() == QtCore.QPointF(5, -5)
assert edges[0]['rect'].bottomRight() == QtCore.QPointF(95, 5)
assert edges[0]['flip_v'] is True
assert edges[1]['rect'].topLeft() == QtCore.QPointF(5, 75)
assert edges[1]['rect'].bottomRight() == QtCore.QPointF(95, 85)
assert edges[1]['flip_v'] is True
assert edges[2]['rect'].topLeft() == QtCore.QPointF(-5, 5)
assert edges[2]['rect'].bottomRight() == QtCore.QPointF(5, 75)
assert edges[2]['flip_v'] is False
assert edges[3]['rect'].topLeft() == QtCore.QPointF(95, 5)
assert edges[3]['rect'].bottomRight() == QtCore.QPointF(105, 75)
assert edges[3]['flip_v'] is False
def test_get_flip_bounds_cropped_item(view, item):
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
edges = item.get_flip_bounds()
assert edges[0]['rect'].topLeft() == QtCore.QPointF(10, 0)
assert edges[0]['rect'].bottomRight() == QtCore.QPointF(100, 10)
assert edges[0]['flip_v'] is True
assert edges[1]['rect'].topLeft() == QtCore.QPointF(10, 80)
assert edges[1]['rect'].bottomRight() == QtCore.QPointF(100, 90)
assert edges[1]['flip_v'] is True
assert edges[2]['rect'].topLeft() == QtCore.QPointF(0, 10)
assert edges[2]['rect'].bottomRight() == QtCore.QPointF(10, 80)
assert edges[2]['flip_v'] is False
assert edges[3]['rect'].topLeft() == QtCore.QPointF(100, 10)
assert edges[3]['rect'].bottomRight() == QtCore.QPointF(110, 80)
assert edges[3]['flip_v'] is False
2021-05-31 16:11:45 +00:00
def test_bounding_rect_when_not_selected(view, item):
item.setSelected(False)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
2021-05-31 16:11:45 +00:00
rect = item.boundingRect()
assert rect.topLeft().x() == 0
assert rect.topLeft().y() == 0
assert rect.bottomRight().x() == 100
assert rect.bottomRight().y() == 80
def test_bounding_rect_when_selected(view, item):
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
item.setSelected(True)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
rect = item.boundingRect()
assert rect.topLeft().x() == -15
assert rect.topLeft().y() == -15
assert rect.bottomRight().x() == 115
assert rect.bottomRight().y() == 95
2021-05-31 16:11:45 +00:00
def test_shape_when_not_selected(view, item):
view.scene.addItem(item)
item.setSelected(False)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
2021-05-31 16:11:45 +00:00
shape = item.shape().boundingRect()
assert shape.topLeft().x() == 0
assert shape.topLeft().y() == 0
assert shape.bottomRight().x() == 100
assert shape.bottomRight().y() == 80
def test_shape_when_selected_single(view, item):
view.scene.addItem(item)
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
item.setSelected(True)
path = QtGui.QPainterPath()
path.addRect(QtCore.QRectF(0, 0, 100, 80))
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
shape = item.shape().boundingRect()
assert shape.topLeft().x() == -15
assert shape.topLeft().y() == -15
assert shape.bottomRight().x() == 115
assert shape.bottomRight().y() == 95
2021-05-31 16:11:45 +00:00
def test_shape_when_selected_multi(view, item):
view.scene.addItem(item)
item2 = BeePixmapItem(QtGui.QImage())
view.scene.addItem(item2)
item2.setSelected(True)
item.SELECT_RESIZE_SIZE = 10
item.SELECT_ROTATE_SIZE = 10
item.setSelected(True)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
2021-05-31 16:11:45 +00:00
shape = item.shape().boundingRect()
assert shape.topLeft().x() == 0
assert shape.topLeft().y() == 0
assert shape.bottomRight().x() == 100
assert shape.bottomRight().y() == 80
def test_get_scale_factor_bottomright(view, item):
item.event_start = QtCore.QPointF(10, 10)
item.event_direction = QtCore.QPointF(1, 1) / math.sqrt(2)
item.scale_orig_factor = 1
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(20, 90)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.get_scale_factor(event) == approx(1.5, 0.01)
def test_get_scale_factor_bottomright_cropped_item(view, item):
item.event_start = QtCore.QPointF(15, 15)
item.event_direction = QtCore.QPointF(1, 1) / math.sqrt(2)
item.scale_orig_factor = 1
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(25, 95)
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
assert item.get_scale_factor(event) == approx(1.5, 0.01)
2021-05-31 16:11:45 +00:00
def test_get_scale_factor_topleft(view, item):
item.event_start = QtCore.QPointF(10, 10)
item.event_direction = QtCore.QPointF(-1, -1) / math.sqrt(2)
item.scale_orig_factor = 0.5
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(-10, -60)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.get_scale_factor(event) == approx(2, 0.01)
def test_get_scale_factor_topleft_cropped_item(view, item):
item.event_start = QtCore.QPointF(15, 15)
item.event_direction = QtCore.QPointF(-1, -1) / math.sqrt(2)
item.scale_orig_factor = 0.5
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(-5, -55)
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
assert item.get_scale_factor(event) == approx(2, 0.01)
2021-05-31 16:11:45 +00:00
def test_get_scale_anchor_topleft(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(0, 0))
assert anchor.x() == 100
assert anchor.y() == 80
def test_get_scale_anchor_topleft_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(5, 5))
assert anchor.x() == 105
assert anchor.y() == 85
2021-05-31 16:11:45 +00:00
def test_get_scale_anchor_bottomright(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(100, 80))
assert anchor.x() == 0
assert anchor.y() == 0
def test_get_scale_anchor_bottomright_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(105, 85))
assert anchor.x() == 5
assert anchor.y() == 5
2021-05-31 16:11:45 +00:00
def test_get_scale_anchor_topright(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(100, 0))
assert anchor.x() == 0
assert anchor.y() == 80
def test_get_scale_anchor_topright_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(105, 5))
assert anchor.x() == 5
assert anchor.y() == 85
2021-05-31 16:11:45 +00:00
def test_get_scale_anchor_bottomleft(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(0, 80))
assert anchor.x() == 100
assert anchor.y() == 0
def test_get_scale_anchor_bottomleft_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
anchor = item.get_scale_anchor(QtCore.QPointF(5, 85))
assert anchor.x() == 105
assert anchor.y() == 5
2021-05-31 16:11:45 +00:00
def test_get_corner_direction_topleft(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(0, 0)) == QtCore.QPointF(-1, -1)
def test_get_corner_direction_topleft_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(5, 5)) == QtCore.QPointF(-1, -1)
2021-05-31 16:11:45 +00:00
def test_get_corner_direction_bottomright(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(100, 80)) == QtCore.QPointF(1, 1)
def test_get_corner_direction_bottomright_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(105, 85)) == QtCore.QPointF(1, 1)
2021-05-31 16:11:45 +00:00
def test_get_corner_direction_topright(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(100, 0)) == QtCore.QPointF(1, -1)
def test_get_corner_direction_topright_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(105, 5)) == QtCore.QPointF(1, -1)
2021-05-31 16:11:45 +00:00
def test_get_corner_direction_bottomleft(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(0, 80)) == QtCore.QPointF(-1, 1)
2021-05-31 16:11:45 +00:00
2021-10-07 13:23:37 +00:00
def test_get_corner_direction_bottomleft_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
assert item.get_corner_direction(
QtCore.QPointF(5, 85)) == QtCore.QPointF(-1, 1)
2021-05-31 16:11:45 +00:00
def test_get_direction_from_center_topleft(view, item):
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
direction = item.get_direction_from_center(QtCore.QPointF(0, -10))
assert direction == approx(QtCore.QPointF(-1, -1) / math.sqrt(2))
def test_get_direction_from_center_topleft_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
direction = item.get_direction_from_center(QtCore.QPointF(5, -5))
assert direction == approx(QtCore.QPointF(-1, -1) / math.sqrt(2))
def test_get_direction_from_center_bottomright(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
direction = item.get_direction_from_center(QtCore.QPointF(100, 90))
assert direction == approx(QtCore.QPointF(1, 1) / math.sqrt(2))
def test_get_direction_from_center_bottomright_cropped_item(view, item):
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(5, 5, 100, 80)):
direction = item.get_direction_from_center(QtCore.QPointF(105, 95))
assert direction == approx(QtCore.QPointF(1, 1) / math.sqrt(2))
2021-05-31 16:11:45 +00:00
def test_get_direction_from_center_bottomright_when_rotated_180(view, item):
item.setRotation(180, QtCore.QPointF(50, 40))
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
direction = item.get_direction_from_center(QtCore.QPointF(100, 90))
assert direction == approx(QtCore.QPointF(1, 1) / math.sqrt(2))
2021-05-31 16:11:45 +00:00
def test_get_rotate_angle(view, item):
item.event_anchor = QtCore.QPointF(10, 20)
assert item.get_rotate_angle(QtCore.QPointF(15, 25)) == -45
def test_get_rotate_delta(view, item):
item.event_anchor = QtCore.QPointF(10, 20)
item.rotate_start_angle = -3
assert item.get_rotate_delta(QtCore.QPointF(15, 25)) == -42
def test_get_rotate_delta_snaps(view, item):
item.event_anchor = QtCore.QPointF(10, 20)
item.rotate_start_angle = -3
item.rotate_orig_degrees = 5
assert item.get_rotate_delta(QtCore.QPointF(15, 25), snap=True) == -35
def test_edge_flips_v_when_item_horizontal(view, item):
item.setRotation(20)
assert item.get_edge_flips_v({'flip_v': True}) is True
def test_edge_flips_v_when_item_horizontal_upside_down(view, item):
item.setRotation(200)
assert item.get_edge_flips_v({'flip_v': True}) is True
def test_edge_flips_v_when_item_vertical_cw(view, item):
item.setRotation(80)
assert item.get_edge_flips_v({'flip_v': True}) is False
def test_edge_flips_v_when_item_vertical_ccw(view, item):
item.setRotation(120)
assert item.get_edge_flips_v({'flip_v': True}) is False
def test_hover_move_event_no_selection(view, item):
view.scene.addItem(item)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(0, 0)
item.set_cursor = MagicMock()
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
item.set_cursor.assert_not_called()
2021-05-31 16:11:45 +00:00
def test_hover_move_event_small_item_inside_handle_free_center(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(10, 10)
item.unset_cursor = MagicMock()
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 20, 20)):
item.hoverMoveEvent(event)
item.unset_cursor.assert_called_once_with()
@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')])
2021-10-07 13:23:37 +00:00
def test_hover_move_event_scale(
pos, flipped, rotation, expected, view, item):
2021-05-31 16:11:45 +00:00
view.scene.addItem(item)
item.setSelected(True)
if flipped:
item.do_flip()
item.setRotation(rotation)
2021-05-31 16:11:45 +00:00
event = MagicMock()
event.pos.return_value = QtCore.QPointF(*pos)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == getattr(Qt.CursorShape, expected)
2021-05-31 16:11:45 +00:00
2021-10-07 13:23:37 +00:00
def test_hover_move_event_scale_bottomright_very_wide_item(view, item):
2021-05-31 16:11:45 +00:00
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(1000, 100)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 1000, 100)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == Qt.CursorShape.SizeFDiagCursor
2021-05-31 16:11:45 +00:00
def test_hover_move_event_rotate(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(115, 95)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_rotate
2021-05-31 16:11:45 +00:00
def test_hover_flip_event_top_edge(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(50, 0)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_flip_v
2021-05-31 16:11:45 +00:00
def test_hover_flip_event_bottom_edge(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(50, 80)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_flip_v
2021-05-31 16:11:45 +00:00
def test_hover_flip_event_left_edge(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(0, 50)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_flip_h
2021-05-31 16:11:45 +00:00
def test_hover_flip_event_right_edge(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(100, 50)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_flip_h
2021-05-31 16:11:45 +00:00
def test_hover_flip_event_top_edge_rotated_90(view, item):
view.scene.addItem(item)
item.setSelected(True)
item.setRotation(90)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(50, 0)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_flip_h
2021-05-31 16:11:45 +00:00
def test_hover_flip_event_left_edge_when_rotated_90(view, item):
view.scene.addItem(item)
event = MagicMock()
item.setSelected(True)
item.setRotation(90)
event.pos.return_value = QtCore.QPointF(0, 50)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.hoverMoveEvent(event)
assert view.viewport().cursor() == BeeAssets().cursor_flip_v
2021-05-31 16:11:45 +00:00
def test_hover_move_event_not_in_handles(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(50, 50)
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 1000, 800)):
2021-10-07 13:23:37 +00:00
item.hoverMoveEvent(event)
assert view.viewport().cursor() == Qt.CursorShape.ArrowCursor
2021-05-31 16:11:45 +00:00
def test_hover_leave_event(view, item):
2021-05-31 16:11:45 +00:00
view.scene.addItem(item)
event = MagicMock()
item.setSelected(True)
item.unset_cursor = MagicMock()
item.hoverLeaveEvent(event)
item.unset_cursor.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_just_selected(view, item):
view.scene.addItem(item)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(0, 0)
event.button.return_value = Qt.MouseButton.LeftButton
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mousePressEvent(event)
event.accept.assert_not_called()
m.assert_called_once_with(event)
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_small_item_inside_handle_free_center(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(10, 10)
event.button.return_value = Qt.MouseButton.LeftButton
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 20, 20)):
item.mousePressEvent(event)
event.accept.assert_not_called()
m.assert_called_once_with(event)
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_topleft_scale(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(2, 2)
event.scenePos.return_value = QtCore.QPointF(-1, -1)
event.button.return_value = Qt.MouseButton.LeftButton
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mousePressEvent(event)
assert item.active_mode == item.SCALE_MODE
assert item.event_start == QtCore.QPointF(-1, -1)
assert item.event_direction.x() < 0
assert item.event_direction.y() < 0
assert item.scale_orig_factor == 1
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_bottomright_scale(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(99, 79)
event.scenePos.return_value = QtCore.QPointF(101, 81)
event.button.return_value = Qt.MouseButton.LeftButton
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mousePressEvent(event)
assert item.active_mode == item.SCALE_MODE
2021-10-07 13:23:37 +00:00
assert item.event_start == QtCore.QPointF(101, 81)
assert item.event_direction.x() > 0
assert item.event_direction.y() > 0
assert item.scale_orig_factor == 1
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_rotate(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(111, 91)
event.scenePos.return_value = QtCore.QPointF(66, 99)
event.button.return_value = Qt.MouseButton.LeftButton
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent'):
2021-05-31 16:11:45 +00:00
item.mousePressEvent(event)
assert item.active_mode == item.ROTATE_MODE
2021-05-31 16:11:45 +00:00
assert item.event_anchor == QtCore.QPointF(50, 40)
assert item.rotate_orig_degrees == 0
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_flip(view, item):
view.scene.addItem(item)
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(0, 40)
event.button.return_value = Qt.MouseButton.LeftButton
view.scene.undo_stack = MagicMock(push=MagicMock())
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent'):
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.active_mode == item.FLIP_MODE
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_press_event_not_in_handles(view, item):
view.scene.addItem(item)
view.reset_previous_transform = MagicMock()
item.setSelected(True)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(50, 40)
event.button.return_value = Qt.MouseButton.LeftButton
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
item.mousePressEvent(event)
m.assert_called_once_with(event)
assert item.active_mode is None
event.accept.assert_not_called()
2021-05-31 16:11:45 +00:00
def test_mouse_move_event_when_no_action_reset_prev_transform(view, item):
view.scene.addItem(item)
view.reset_previous_transform = MagicMock()
event = MagicMock()
item.event_start = QtCore.QPointF(10, 10)
event.scenePos.return_value = QtCore.QPointF(50, 40)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
item.mouseMoveEvent(event)
m.assert_called_once_with(event)
view.reset_previous_transform.assert_called_once()
event.accept.assert_not_called()
2021-05-31 16:11:45 +00:00
def test_mouse_move_event_when_no_action_doesnt_reset_prev_transf(view, item):
view.scene.addItem(item)
view.reset_previous_transform = MagicMock()
event = MagicMock()
item.event_start = QtCore.QPointF(10, 10)
event.scenePos.return_value = QtCore.QPointF(11, 11)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
item.mouseMoveEvent(event)
m.assert_called_once_with(event)
view.reset_previous_transform.assert_not_called()
event.accept.assert_not_called()
2021-05-31 16:11:45 +00:00
def test_mouse_move_event_when_scale_action(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(20, 90)
item.active_mode = item.SCALE_MODE
2021-05-31 16:11:45 +00:00
item.event_direction = QtCore.QPointF(1, 1) / math.sqrt(2)
item.event_anchor = QtCore.QPointF(100, 80)
item.event_start = QtCore.QPointF(10, 10)
item.scale_orig_factor = 1
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mouseMoveEvent(event)
m.assert_not_called()
assert item.scale() == approx(1.5, 0.01)
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_move_event_when_rotate_action(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(15, 25)
item.event_start = QtCore.QPointF(10, 10)
item.active_mode = item.ROTATE_MODE
2021-05-31 16:11:45 +00:00
item.rotate_orig_degrees = 0
item.rotate_start_angle = -3
item.event_anchor = QtCore.QPointF(10, 20)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
item.mouseMoveEvent(event)
m.assert_not_called()
assert item.rotation() == 318
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_move_event_when_flip_action(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(15, 25)
item.event_start = QtCore.QPointF(10, 10)
item.active_mode = item.FLIP_MODE
2021-05-31 16:11:45 +00:00
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
item.mouseMoveEvent(event)
m.assert_not_called()
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_release_event_when_no_action(view, item):
view.scene.addItem(item)
event = MagicMock()
item.active_mode = item.FLIP_MODE
2021-05-31 16:11:45 +00:00
event.pos.return_value = QtCore.QPointF(-100, -100)
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem'
'.mouseReleaseEvent') as m:
item.mouseReleaseEvent(event)
m.assert_called_once_with(event)
item.active_mode is None
event.accept.assert_not_called()
2021-05-31 16:11:45 +00:00
def test_mouse_release_event_when_scale_action(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(20, 90)
item.active_mode = item.SCALE_MODE
2021-05-31 16:11:45 +00:00
item.event_direction = QtCore.QPointF(1, 1) / math.sqrt(2)
item.event_anchor = QtCore.QPointF(100, 80)
item.event_start = QtCore.QPointF(10, 10)
item.scale_orig_factor = 1
view.scene.undo_stack = MagicMock(push=MagicMock())
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mouseReleaseEvent(event)
view.scene.undo_stack.push.assert_called_once()
args = view.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
isinstance(cmd, commands.ScaleItemsBy)
assert cmd.items == [item]
assert cmd.factor == approx(1.5, 0.01)
assert cmd.anchor == QtCore.QPointF(100, 80)
assert cmd.ignore_first_redo is True
assert item.active_mode is None
2021-10-07 13:23:37 +00:00
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_release_event_when_scale_action_zero(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(20, 90)
item.active_mode = item.SCALE_MODE
2021-05-31 16:11:45 +00:00
item.event_direction = QtCore.QPointF(1, 1) / math.sqrt(2)
item.event_anchor = QtCore.QPointF(100, 80)
item.event_start = QtCore.QPointF(20, 90)
item.scale_orig_factor = 1
view.scene.undo_stack = MagicMock(push=MagicMock())
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mouseReleaseEvent(event)
view.scene.undo_stack.push.assert_not_called()
assert item.active_mode is None
2021-10-07 13:23:37 +00:00
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_release_event_when_rotate_action(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(15, 25)
item.active_mode = item.ROTATE_MODE
2021-05-31 16:11:45 +00:00
item.rotate_orig_degrees = 0
item.rotate_start_angle = -3
item.event_anchor = QtCore.QPointF(10, 20)
view.scene.undo_stack = MagicMock(push=MagicMock())
item.mouseReleaseEvent(event)
view.scene.undo_stack.push.assert_called_once()
args = view.scene.undo_stack.push.call_args_list[0][0]
cmd = args[0]
isinstance(cmd, commands.RotateItemsBy)
assert cmd.items == [item]
assert cmd.delta == -42
assert cmd.anchor == QtCore.QPointF(10, 20)
assert cmd.ignore_first_redo is True
assert item.active_mode is None
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_release_event_when_rotate_action_zero(view, item):
view.scene.addItem(item)
event = MagicMock()
event.scenePos.return_value = QtCore.QPointF(15, 25)
item.active_mode = item.ROTATE_MODE
2021-05-31 16:11:45 +00:00
item.rotate_orig_degrees = 0
item.rotate_start_angle = -45
item.event_anchor = QtCore.QPointF(10, 20)
view.scene.undo_stack = MagicMock(push=MagicMock())
item.mouseReleaseEvent(event)
view.scene.undo_stack.push.assert_not_called()
assert item.active_mode is None
event.accept.assert_called_once_with()
2021-05-31 16:11:45 +00:00
def test_mouse_release_event_when_flip_action(view, item):
view.scene.addItem(item)
event = MagicMock()
event.pos.return_value = QtCore.QPointF(0, 40)
item.active_mode = item.FLIP_MODE
2021-05-31 16:11:45 +00:00
view.scene.undo_stack = MagicMock(push=MagicMock())
2021-10-07 13:23:37 +00:00
with patch.object(item, 'bounding_rect_unselected',
return_value=QtCore.QRectF(0, 0, 100, 80)):
item.mouseReleaseEvent(event)
view.scene.undo_stack.push.assert_not_called()
assert item.active_mode is None
event.accept.assert_called_once_with()