mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
432 lines
17 KiB
Python
432 lines
17 KiB
Python
from unittest.mock import patch, MagicMock, PropertyMock
|
|
|
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
from PyQt6.QtCore import Qt
|
|
|
|
from beeref.items import BeePixmapItem
|
|
from beeref.scene import BeeGraphicsScene
|
|
from .base import BeeTestCase
|
|
|
|
|
|
class BeePixmapItemTestCase(BeeTestCase):
|
|
|
|
def setUp(self):
|
|
self.scene = BeeGraphicsScene(None)
|
|
|
|
def test_init(self):
|
|
item = BeePixmapItem(
|
|
QtGui.QImage(self.imgfilename3x3), self.imgfilename3x3)
|
|
assert item.save_id is None
|
|
assert item.width == 3
|
|
assert item.height == 3
|
|
assert item.scale() == 1
|
|
assert item.flags() == (
|
|
QtWidgets.QGraphicsItem.GraphicsItemFlags.ItemIsMovable
|
|
| QtWidgets.QGraphicsItem.GraphicsItemFlags.ItemIsSelectable)
|
|
assert item.filename == self.imgfilename3x3
|
|
|
|
def test_set_scale(self):
|
|
item = BeePixmapItem(
|
|
QtGui.QImage(self.imgfilename3x3), self.imgfilename3x3)
|
|
item.prepareGeometryChange = MagicMock()
|
|
item.setScale(3)
|
|
assert item.scale() == 3
|
|
assert item.pos().x() == 0
|
|
assert item.pos().y() == 0
|
|
item.prepareGeometryChange.assert_called_once()
|
|
|
|
def test_set_scale_ignores_zero(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
item.setScale(0)
|
|
assert item.scale() == 1
|
|
|
|
def test_set_scale_ignores_negative(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
item.setScale(-0.1)
|
|
assert item.scale() == 1
|
|
|
|
def test_set_pos_center(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
with patch('beeref.items.BeePixmapItem.width',
|
|
new_callable=PropertyMock, return_value=200):
|
|
with patch('beeref.items.BeePixmapItem.height',
|
|
new_callable=PropertyMock, return_value=100):
|
|
item.set_pos_center(0, 0)
|
|
assert item.pos().x() == -100
|
|
assert item.pos().y() == -50
|
|
|
|
def test_set_zvalue_sets_new_max(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
self.scene.addItem(item)
|
|
item.setZValue(1.1)
|
|
assert item.zValue() == 1.1
|
|
assert self.scene.max_z == 1.1
|
|
|
|
def test_set_zvalue_keeps_old_max(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
self.scene.addItem(item)
|
|
self.scene.max_z = 3.3
|
|
item.setZValue(1.1)
|
|
assert item.zValue() == 1.1
|
|
assert self.scene.max_z == 3.3
|
|
|
|
def test_bring_to_front(self):
|
|
item1 = BeePixmapItem(QtGui.QImage())
|
|
self.scene.addItem(item1)
|
|
item1.setZValue(3.3)
|
|
item2 = BeePixmapItem(QtGui.QImage())
|
|
self.scene.addItem(item2)
|
|
item2.bring_to_front()
|
|
assert item2.zValue() > item1.zValue()
|
|
assert item2.zValue() == self.scene.max_z
|
|
|
|
def test_on_view_scale_change(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
with patch('beeref.items.BeePixmapItem.prepareGeometryChange') as m:
|
|
item.on_view_scale_change()
|
|
m.assert_called_once()
|
|
|
|
|
|
class BeePixmapItemWithViewBaseTestCase(BeeTestCase):
|
|
|
|
def setUp(self):
|
|
self.scene = BeeGraphicsScene(None)
|
|
self.item = BeePixmapItem(QtGui.QImage())
|
|
self.scene.addItem(self.item)
|
|
self.view = MagicMock(get_scale=MagicMock(return_value=1))
|
|
views_patcher = patch('beeref.scene.BeeGraphicsScene.views',
|
|
return_value=[self.view])
|
|
views_patcher.start()
|
|
self.addCleanup(views_patcher.stop)
|
|
width_patcher = patch('beeref.items.BeePixmapItem.width',
|
|
new_callable=PropertyMock,
|
|
return_value=100)
|
|
width_patcher.start()
|
|
self.addCleanup(width_patcher.stop)
|
|
height_patcher = patch('beeref.items.BeePixmapItem.height',
|
|
new_callable=PropertyMock,
|
|
return_value=80)
|
|
height_patcher.start()
|
|
self.addCleanup(height_patcher.stop)
|
|
|
|
|
|
class BeePixmapItemPaintstuffTestCase(BeePixmapItemWithViewBaseTestCase):
|
|
|
|
def test_fixed_length_for_viewport_when_default_scales(self):
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
assert self.item.fixed_length_for_viewport(100) == 100
|
|
assert self.item._view_scale == 1
|
|
|
|
def test_fixed_length_for_viewport_when_viewport_scaled(self):
|
|
self.view.get_scale = MagicMock(return_value=2)
|
|
assert self.item.fixed_length_for_viewport(100) == 50
|
|
assert self.item._view_scale == 2
|
|
|
|
def test_fixed_length_for_viewport_when_item_scaled(self):
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.setScale(5)
|
|
assert self.item.fixed_length_for_viewport(100) == 20
|
|
assert self.item._view_scale == 1
|
|
|
|
def test_fixed_length_for_viewport_when_no_scene(self):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
item._view_scale = 0.5
|
|
assert item.fixed_length_for_viewport(100) == 200
|
|
|
|
def test_resize_size_when_scaled(self):
|
|
self.view.get_scale = MagicMock(return_value=2)
|
|
self.item.setScale(2)
|
|
self.item.SELECT_RESIZE_SIZE = 100
|
|
assert self.item.select_resize_size == 25
|
|
|
|
def test_rotate_size_when_scaled(self):
|
|
self.view.get_scale = MagicMock(return_value=2)
|
|
self.item.setScale(2)
|
|
self.item.SELECT_ROTATE_SIZE = 100
|
|
assert self.item.select_rotate_size == 25
|
|
|
|
def test_paint_when_not_selected(self):
|
|
painter = MagicMock()
|
|
self.item.setSelected(False)
|
|
self.item.pixmap = MagicMock(return_value='pixmap')
|
|
self.item.paint(painter, None, None)
|
|
painter.drawPixmap.assert_called_once_with(0, 0, 'pixmap')
|
|
painter.drawRect.assert_not_called()
|
|
painter.drawPoint.assert_not_called()
|
|
|
|
def test_paint_when_selected_single_selection(self):
|
|
painter = MagicMock()
|
|
self.item.setSelected(True)
|
|
self.item.paint(painter, None, None)
|
|
painter.drawPixmap.assert_called_once()
|
|
painter.drawRect.assert_called_once()
|
|
painter.drawPoint.assert_called()
|
|
|
|
def test_paint_when_selected_multi_selection(self):
|
|
item2 = BeePixmapItem(QtGui.QImage())
|
|
item2.setSelected(True)
|
|
self.scene.addItem(item2)
|
|
painter = MagicMock()
|
|
self.item.setSelected(True)
|
|
self.item.paint(painter, None, None)
|
|
painter.drawPixmap.assert_called_once()
|
|
painter.drawRect.assert_called_once()
|
|
painter.drawPoint.assert_not_called()
|
|
|
|
def test_corners(self):
|
|
assert set(self.item.corners) == set((
|
|
(0, 0),
|
|
(100, 0),
|
|
(0, 80),
|
|
(100, 80)))
|
|
|
|
def test_get_scale_bounds(self):
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.SELECT_RESIZE_SIZE = 10
|
|
rect = self.item.get_scale_bounds((100, 100))
|
|
assert rect.topLeft().x() == 95
|
|
assert rect.topLeft().y() == 95
|
|
assert rect.bottomRight().x() == 105
|
|
assert rect.bottomRight().y() == 105
|
|
|
|
def test_bottom_right_rotate_bounds(self):
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.SELECT_RESIZE_SIZE = 10
|
|
self.item.SELECT_ROTATE_SIZE = 10
|
|
rect = self.item.bottom_right_rotate_bounds
|
|
assert rect.topLeft().x() == 105
|
|
assert rect.topLeft().y() == 85
|
|
assert rect.bottomRight().x() == 115
|
|
assert rect.bottomRight().y() == 95
|
|
|
|
def test_bounding_rect_when_not_selected(self):
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.setSelected(False)
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.boundingRect',
|
|
return_value=QtCore.QRectF(0, 0, 100, 80)):
|
|
rect = self.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(self):
|
|
self.item.SELECT_RESIZE_SIZE = 10
|
|
self.item.SELECT_ROTATE_SIZE = 10
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.setSelected(True)
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.boundingRect',
|
|
return_value=QtCore.QRectF(0, 0, 100, 80)):
|
|
rect = self.item.boundingRect()
|
|
assert rect.topLeft().x() == -15
|
|
assert rect.topLeft().y() == -15
|
|
assert rect.bottomRight().x() == 115
|
|
assert rect.bottomRight().y() == 95
|
|
|
|
def test_shape_when_not_selected(self):
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.setSelected(False)
|
|
path = QtGui.QPainterPath()
|
|
path.addRect(QtCore.QRectF(0, 0, 100, 80))
|
|
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.shape',
|
|
return_value=path):
|
|
shape = self.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(self):
|
|
self.item.SELECT_RESIZE_SIZE = 10
|
|
self.item.SELECT_ROTATE_SIZE = 10
|
|
self.view.get_scale = MagicMock(return_value=1)
|
|
self.item.setSelected(True)
|
|
path = QtGui.QPainterPath()
|
|
path.addRect(QtCore.QRectF(0, 0, 100, 80))
|
|
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.shape',
|
|
return_value=path):
|
|
shape = self.item.shape().boundingRect()
|
|
assert shape.topLeft().x() == -5
|
|
assert shape.topLeft().y() == -5
|
|
assert shape.bottomRight().x() == 115
|
|
assert shape.bottomRight().y() == 95
|
|
|
|
|
|
class BeePixmapItemScalingTestCase(BeePixmapItemWithViewBaseTestCase):
|
|
|
|
def test_get_scale_delta_bottomright(self):
|
|
self.item.scale_start = QtCore.QPoint(10, 10)
|
|
event = MagicMock()
|
|
event.scenePos = MagicMock(return_value=QtCore.QPoint(20, 90))
|
|
assert self.item.get_scale_delta(event, (100, 80)) == 0.5
|
|
|
|
def test_get_scale_delta_topleft(self):
|
|
self.item.scale_start = QtCore.QPoint(10, 10)
|
|
event = MagicMock()
|
|
event.scenePos = MagicMock(return_value=QtCore.QPoint(-10, -60))
|
|
assert self.item.get_scale_delta(event, (0, 0)) == 0.5
|
|
|
|
def test_get_scale_anchor_topleft(self):
|
|
assert self.item.get_scale_anchor((0, 0)) == (100, 80)
|
|
|
|
def test_get_scale_anchor_bottomright(self):
|
|
assert self.item.get_scale_anchor((100, 80)) == (0, 0)
|
|
|
|
def test_get_scale_anchor_topright(self):
|
|
assert self.item.get_scale_anchor((100, 0)) == (0, 80)
|
|
|
|
def test_get_scale_anchor_bottomleft(self):
|
|
assert self.item.get_scale_anchor((0, 80)) == (100, 0)
|
|
|
|
def test_get_scale_direction_topleft(self):
|
|
assert self.item.get_scale_direction((0, 0)) == (-1, -1)
|
|
|
|
def test_get_scale_direction_bottomright(self):
|
|
assert self.item.get_scale_direction((100, 80)) == (1, 1)
|
|
|
|
def test_get_scale_direction_topright(self):
|
|
assert self.item.get_scale_direction((100, 0)) == (1, -1)
|
|
|
|
def test_get_scale_direction_bottomleft(self):
|
|
assert self.item.get_scale_direction((0, 80)) == (-1, 1)
|
|
|
|
def test_translate_for_scale_anchor(self):
|
|
pos = QtCore.QPoint(50, 70)
|
|
self.item.translate_for_scale_anchor(pos, 2, (100, 80))
|
|
assert self.item.pos().x() == -150
|
|
assert self.item.pos().y() == -90
|
|
|
|
|
|
class BeePixmapItemEventsstuffTestCase(BeePixmapItemWithViewBaseTestCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.event = MagicMock()
|
|
self.item.setCursor = MagicMock()
|
|
|
|
def test_hover_move_event_no_selection(self):
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(0, 0))
|
|
self.item.hoverMoveEvent(self.event)
|
|
self.item.setCursor.assert_not_called()
|
|
|
|
def test_hover_move_event_topleft_scale(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(0, 0))
|
|
self.item.hoverMoveEvent(self.event)
|
|
self.item.setCursor.assert_called_once_with(
|
|
Qt.CursorShape.SizeFDiagCursor)
|
|
|
|
def test_hover_move_event_bottomright_scale(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(100, 80))
|
|
self.item.hoverMoveEvent(self.event)
|
|
self.item.setCursor.assert_called_once_with(
|
|
Qt.CursorShape.SizeFDiagCursor)
|
|
|
|
def test_hover_move_event_topright_scale(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(100, 0))
|
|
self.item.hoverMoveEvent(self.event)
|
|
self.item.setCursor.assert_called_once_with(
|
|
Qt.CursorShape.SizeBDiagCursor)
|
|
|
|
def test_hover_move_event_not_in_handles(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(50, 50))
|
|
self.item.hoverMoveEvent(self.event)
|
|
self.item.setCursor.assert_called_once_with(
|
|
Qt.CursorShape.ArrowCursor)
|
|
|
|
def test_hover_enter_event_when_selected(self):
|
|
self.item.setSelected(True)
|
|
self.item.hoverEnterEvent(self.event)
|
|
self.item.setCursor.assert_not_called()
|
|
|
|
def test_hover_enter_event_when_not_selected(self):
|
|
self.item.setSelected(False)
|
|
self.item.hoverEnterEvent(self.event)
|
|
self.item.setCursor.assert_called_once_with(
|
|
Qt.CursorShape.ArrowCursor)
|
|
|
|
def test_mouse_press_event_topleft_scale(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(2, 2))
|
|
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(66, 99))
|
|
self.event.button = MagicMock(
|
|
return_value=Qt.MouseButtons.LeftButton)
|
|
self.item.mousePressEvent(self.event)
|
|
assert self.item.scale_active_corner == (0, 0)
|
|
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)
|
|
|
|
def test_mouse_press_event_bottomright_scale(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(99, 79))
|
|
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(66, 99))
|
|
self.event.button = MagicMock(
|
|
return_value=Qt.MouseButtons.LeftButton)
|
|
self.item.mousePressEvent(self.event)
|
|
assert self.item.scale_active_corner == (100, 80)
|
|
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)
|
|
|
|
def test_mouse_press_event_not_selected(self):
|
|
self.item.setSelected(False)
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
|
|
self.item.mousePressEvent(self.event)
|
|
m.assert_called_once_with(self.event)
|
|
assert self.item.scale_active_corner is None
|
|
|
|
def test_mouse_press_not_in_handles(self):
|
|
self.item.setSelected(True)
|
|
self.event.pos = MagicMock(return_value=QtCore.QPointF(50, 40))
|
|
self.event.button = MagicMock(
|
|
return_value=Qt.MouseButtons.LeftButton)
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mousePressEvent') as m:
|
|
self.item.mousePressEvent(self.event)
|
|
m.assert_called_once_with(self.event)
|
|
assert self.item.scale_active_corner is None
|
|
|
|
def test_mouse_move_event_when_no_action(self):
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem.mouseMoveEvent') as m:
|
|
self.item.mouseMoveEvent(self.event)
|
|
m.assert_called_once_with(self.event)
|
|
|
|
def test_move_event_when_scale_action(self):
|
|
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90))
|
|
self.item.scale_active_corner = (100, 80)
|
|
self.item.scale_start = QtCore.QPointF(10, 10)
|
|
self.item.scale_orig_factor = 1
|
|
self.item.scale_orig_pos = QtCore.QPointF(0, 0)
|
|
|
|
self.item.mouseMoveEvent(self.event)
|
|
assert self.item.scale() == 1.5
|
|
|
|
def test_mouse_release_event_when_no_action(self):
|
|
with patch('PyQt6.QtWidgets.QGraphicsPixmapItem'
|
|
'.mouseReleaseEvent') as m:
|
|
self.item.mouseReleaseEvent(self.event)
|
|
m.assert_called_once_with(self.event)
|
|
|
|
def test_mouse_release_event_when_scale_action(self):
|
|
self.event.scenePos = MagicMock(return_value=QtCore.QPointF(20, 90))
|
|
self.item.scale_active_corner = (100, 80)
|
|
self.item.scale_start = QtCore.QPointF(10, 10)
|
|
self.item.scale_orig_factor = 1
|
|
self.item.scale_orig_pos = QtCore.QPointF(0, 0)
|
|
self.scene.undo_stack = MagicMock()
|
|
self.scene.undo_stack.push = MagicMock()
|
|
|
|
self.item.mouseReleaseEvent(self.event)
|
|
self.scene.undo_stack.push.assert_called_once()
|
|
args = self.scene.undo_stack.push.call_args_list[0][0]
|
|
cmd = args[0]
|
|
assert cmd.items == [self.item]
|
|
assert cmd.delta == 0.5
|
|
assert cmd.anchor == (0, 0)
|
|
assert cmd.ignore_first_redo is True
|
|
assert self.item.scale_active_corner is None
|