mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
924 lines
32 KiB
Python
924 lines
32 KiB
Python
import pytest
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
from PyQt6.QtCore import Qt
|
|
|
|
from beeref.items import BeePixmapItem, item_registry
|
|
|
|
|
|
def test_in_item_registry():
|
|
assert item_registry['pixmap'] == BeePixmapItem
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.init_selectable')
|
|
def test_init(selectable_mock, qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3), imgfilename3x3)
|
|
assert item.save_id is None
|
|
assert item.width == 3
|
|
assert item.height == 3
|
|
assert item.scale() == 1
|
|
assert item.filename == imgfilename3x3
|
|
assert item.crop == QtCore.QRectF(0, 0, 3, 3)
|
|
assert item.is_image is True
|
|
assert item.crop_mode is False
|
|
selectable_mock.assert_called_once()
|
|
|
|
|
|
def test_set_pos_center(qapp, item):
|
|
with patch.object(item, 'bounding_rect_unselected',
|
|
return_value=QtCore.QRectF(0, 0, 200, 100)):
|
|
item.set_pos_center(QtCore.QPointF(0, 0))
|
|
assert item.pos().x() == -100
|
|
assert item.pos().y() == -50
|
|
|
|
|
|
def test_set_pos_center_when_scaled(qapp, item):
|
|
item.setScale(2)
|
|
with patch.object(item, 'bounding_rect_unselected',
|
|
return_value=QtCore.QRectF(0, 0, 200, 100)):
|
|
item.set_pos_center(QtCore.QPointF(0, 0))
|
|
assert item.pos().x() == -200
|
|
assert item.pos().y() == -100
|
|
|
|
|
|
def test_set_pos_center_when_rotated(qapp, item):
|
|
item.setRotation(90)
|
|
with patch.object(item, 'bounding_rect_unselected',
|
|
return_value=QtCore.QRectF(0, 0, 200, 100)):
|
|
item.set_pos_center(QtCore.QPointF(0, 0))
|
|
assert item.pos().x() == 50
|
|
assert item.pos().y() == -100
|
|
|
|
|
|
def test_set_crop(qapp, item):
|
|
item.update = MagicMock()
|
|
item.prepareGeometryChange = MagicMock()
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
item.update.assert_called_once_with()
|
|
item.prepareGeometryChange.assert_called_once_with()
|
|
|
|
|
|
def test_set_grayscale_true(qapp, item):
|
|
item.grayscale = True
|
|
assert item.grayscale is True
|
|
assert item._grayscale_pixmap is not None
|
|
|
|
|
|
def test_set_grayscale_false(qapp, item):
|
|
item._grayscale_pixmap = QtGui.QPixmap()
|
|
item.grayscale = False
|
|
assert item.grayscale is False
|
|
assert item._grayscale_pixmap is None
|
|
|
|
|
|
def test_bounding_rect_unselected(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(1, 1, 2, 2)
|
|
assert item.bounding_rect_unselected() == QtCore.QRectF(1, 1, 2, 2)
|
|
|
|
|
|
def test_bounding_rect_unselected_in_crop_mode(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(1, 1, 2, 2)
|
|
item.crop_mode = True
|
|
assert item.bounding_rect_unselected() == QtCore.QRectF(-0.5, -0.5, 4, 4)
|
|
|
|
|
|
def test_get_extra_save_data(item):
|
|
item.filename = 'foobar.png'
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
item.setOpacity(0.75)
|
|
item.grayscale = True
|
|
assert item.get_extra_save_data() == {
|
|
'filename': 'foobar.png',
|
|
'crop': [10, 20, 30, 40],
|
|
'opacity': 0.75,
|
|
'grayscale': True
|
|
}
|
|
|
|
|
|
def test_get_filename_for_export_when_save_id_and_filename(item):
|
|
item.filename = 'foo.png'
|
|
item.save_id = 5
|
|
assert item.get_filename_for_export('jpg', 8) == '0005-foo.jpg'
|
|
|
|
|
|
def test_get_filename_for_export_when_save_id_and_no_filename(item):
|
|
item.filename = None
|
|
item.save_id = 5
|
|
assert item.get_filename_for_export('jpg', 8) == '0005.jpg'
|
|
|
|
|
|
def test_get_filename_for_export_when_no_save_id_and_filename(item):
|
|
item.filename = 'foo.png'
|
|
item.save_id = None
|
|
assert item.get_filename_for_export('jpg', 8) == '0008-foo.jpg'
|
|
|
|
|
|
def test_get_filename_for_export_when_no_save_id_and_no_filename(item):
|
|
item.filename = None
|
|
item.save_id = None
|
|
assert item.get_filename_for_export('jpg', 8) == '0008.jpg'
|
|
|
|
|
|
def test_get_filename_for_export_when_save_id_and_no_default(item):
|
|
item.filename = 'foo.png'
|
|
item.save_id = 5
|
|
assert item.get_filename_for_export('jpg') == '0005-foo.jpg'
|
|
|
|
|
|
def test_get_filename_for_export_when_no_save_id_and_no_default(item):
|
|
item.filename = 'foo.png'
|
|
item.save_id = None
|
|
with pytest.raises(AssertionError):
|
|
assert item.get_filename_for_export('jpg')
|
|
|
|
|
|
def test_get_imgformat_test_with_real_image(
|
|
qapp, imgfilename3x3, item, settings):
|
|
settings.setValue('Items/image_storage_format', 'best')
|
|
img = QtGui.QImage(imgfilename3x3)
|
|
assert item.get_imgformat(img) == 'png'
|
|
|
|
|
|
def test_get_imgformat_unknown_option_defaults_to_best(
|
|
qapp, imgfilename3x3, item, settings):
|
|
settings.setValue('Items/image_storage_format', 'foo')
|
|
img = QtGui.QImage(imgfilename3x3)
|
|
assert item.get_imgformat(img) == 'png'
|
|
|
|
|
|
def test_get_imgformat_jpg_for_large_nonalpha_image_when_setting_best(
|
|
qapp, settings, item):
|
|
settings.setValue('Items/image_storage_format', 'best')
|
|
img = MagicMock(
|
|
hasAlphaChannel=MagicMock(return_value=False),
|
|
height=MagicMock(return_value=1600),
|
|
width=MagicMock(return_value=1200))
|
|
assert item.get_imgformat(img) == 'jpg'
|
|
|
|
|
|
def test_get_imgformat_png_for_large_alpha_image_when_setting_best(
|
|
qapp, settings, item):
|
|
settings.setValue('Items/image_storage_format', 'best')
|
|
img = MagicMock(
|
|
hasAlphaChannel=MagicMock(return_value=True),
|
|
height=MagicMock(return_value=1600),
|
|
width=MagicMock(return_value=1200))
|
|
assert item.get_imgformat(img) == 'png'
|
|
|
|
|
|
def test_get_imgformat_png_for_small_nonalpha_image_when_setting_best(
|
|
qapp, settings, item):
|
|
settings.setValue('Items/image_storage_format', 'best')
|
|
img = MagicMock(
|
|
hasAlphaChannel=MagicMock(return_value=False),
|
|
height=MagicMock(return_value=100),
|
|
width=MagicMock(return_value=100))
|
|
assert item.get_imgformat(img) == 'png'
|
|
|
|
|
|
def test_get_imgformat_jpg_when_setting_jpg(
|
|
qapp, settings, item):
|
|
settings.setValue('Items/image_storage_format', 'jpg')
|
|
img = MagicMock(
|
|
hasAlphaChannel=MagicMock(return_value=True),
|
|
height=MagicMock(return_value=100),
|
|
width=MagicMock(return_value=100))
|
|
assert item.get_imgformat(img) == 'jpg'
|
|
|
|
|
|
def test_get_imgformat_png_when_setting_png(
|
|
qapp, settings, item):
|
|
settings.setValue('Items/image_storage_format', 'png')
|
|
img = MagicMock(
|
|
hasAlphaChannel=MagicMock(return_value=False),
|
|
height=MagicMock(return_value=1600),
|
|
width=MagicMock(return_value=1020))
|
|
assert item.get_imgformat(img) == 'png'
|
|
|
|
|
|
def test_pixmap_to_bytes_png(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(0, 0, 2, 2)
|
|
item.grayscale = True
|
|
data, imgformat = item.pixmap_to_bytes()
|
|
assert imgformat == 'png'
|
|
assert data.startswith(b'\x89PNG')
|
|
pixmap = QtGui.QPixmap()
|
|
pixmap.loadFromData(data)
|
|
img = pixmap.toImage()
|
|
assert img.allGray() is False
|
|
assert img.size() == QtCore.QSize(3, 3)
|
|
|
|
|
|
def test_pixmap_to_bytes_jpg(qapp, imgfilename3x3, settings):
|
|
settings.setValue('Items/image_storage_format', 'jpg')
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(0, 0, 2, 2)
|
|
item.grayscale = True
|
|
data, imgformat = item.pixmap_to_bytes()
|
|
assert imgformat == 'jpg'
|
|
assert data.startswith(b'\xff\xd8\xff\xe0\x00\x10JFIF')
|
|
pixmap = QtGui.QPixmap()
|
|
pixmap.loadFromData(data)
|
|
img = pixmap.toImage()
|
|
assert img.allGray() is False
|
|
assert img.size() == QtCore.QSize(3, 3)
|
|
|
|
|
|
def test_pixmap_to_bytes_apply_grayscale(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(0, 0, 2, 2)
|
|
item.grayscale = True
|
|
data, imgformat = item.pixmap_to_bytes(apply_grayscale=True)
|
|
assert imgformat == 'png'
|
|
assert data.startswith(b'\x89PNG')
|
|
pixmap = QtGui.QPixmap()
|
|
pixmap.loadFromData(data)
|
|
img = pixmap.toImage()
|
|
assert img.allGray() is True
|
|
assert img.size() == QtCore.QSize(3, 3)
|
|
|
|
|
|
def test_pixmap_to_bytes_apply_crop(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(0, 0, 2, 2)
|
|
item.grayscale = True
|
|
data, imgformat = item.pixmap_to_bytes(apply_crop=True)
|
|
assert imgformat == 'png'
|
|
assert data.startswith(b'\x89PNG')
|
|
pixmap = QtGui.QPixmap()
|
|
pixmap.loadFromData(data)
|
|
img = pixmap.toImage()
|
|
assert img.allGray() is False
|
|
assert img.size() == QtCore.QSize(2, 2)
|
|
|
|
|
|
def test_pixmap_to_bytes_apply_grayscale_crop_when_not_set(
|
|
qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
data, imgformat = item.pixmap_to_bytes(apply_grayscale=True,
|
|
apply_crop=False)
|
|
assert imgformat == 'png'
|
|
assert data.startswith(b'\x89PNG')
|
|
pixmap = QtGui.QPixmap()
|
|
pixmap.loadFromData(data)
|
|
img = pixmap.toImage()
|
|
assert img.allGray() is False
|
|
assert img.size() == QtCore.QSize(3, 3)
|
|
|
|
|
|
def test_pixmap_from_bytes(qapp, item, imgfilename3x3):
|
|
with open(imgfilename3x3, 'rb') as f:
|
|
imgdata = f.read()
|
|
item.pixmap_from_bytes(imgdata)
|
|
assert item.width == 3
|
|
assert item.height == 3
|
|
assert item.crop == QtCore.QRectF(0, 0, 3, 3)
|
|
|
|
|
|
def test_has_selection_outline_when_not_selected(view, item):
|
|
view.scene.addItem(item)
|
|
item.setSelected(False)
|
|
item.has_selection_outline() is False
|
|
|
|
|
|
def test_has_selection_outline_when_selected(view, item):
|
|
view.scene.addItem(item)
|
|
item.setSelected(True)
|
|
item.has_selection_outline() is True
|
|
|
|
|
|
def test_has_selection_handles_when_not_selected(view, item):
|
|
view.scene.addItem(item)
|
|
item.setSelected(False)
|
|
item2 = BeePixmapItem(QtGui.QImage())
|
|
view.scene.addItem(item2)
|
|
item2.setSelected(False)
|
|
item.has_selection_handles() is False
|
|
|
|
|
|
def test_has_selection_handles_when_selected_single(view, item):
|
|
view.scene.addItem(item)
|
|
item.setSelected(True)
|
|
item2 = BeePixmapItem(QtGui.QImage())
|
|
view.scene.addItem(item2)
|
|
item2.setSelected(False)
|
|
item.has_selection_handles() is True
|
|
|
|
|
|
def test_has_selection_handles_when_selected_multi(view, item):
|
|
view.scene.addItem(item)
|
|
item.setSelected(True)
|
|
item2 = BeePixmapItem(QtGui.QImage())
|
|
view.scene.addItem(item2)
|
|
item2.setSelected(True)
|
|
item.has_selection_handles() is False
|
|
|
|
|
|
def test_selection_action_items(qapp):
|
|
item = BeePixmapItem(QtGui.QImage())
|
|
assert item.selection_action_items() == [item]
|
|
|
|
|
|
def test_update_from_data(item):
|
|
item.update_from_data(
|
|
save_id=3,
|
|
x=11,
|
|
y=22,
|
|
z=1.2,
|
|
scale=2.5,
|
|
rotation=45,
|
|
flip=-1)
|
|
assert item.save_id == 3
|
|
assert item.pos() == QtCore.QPointF(11, 22)
|
|
assert item.zValue() == 1.2
|
|
assert item.rotation() == 45
|
|
assert item.flip() == -1
|
|
|
|
|
|
def test_update_from_data_keeps_flip(item):
|
|
item.do_flip()
|
|
item.update_from_data(flip=-1)
|
|
assert item.flip() == -1
|
|
|
|
|
|
def test_update_from_data_keeps_unset_values(item):
|
|
item.setScale(3)
|
|
item.update_from_data(rotation=45)
|
|
assert item.scale() == 3
|
|
assert item.flip() == 1
|
|
|
|
|
|
def test_create_from_minimal_data(qapp, item, imgfilename3x3):
|
|
with open(imgfilename3x3, 'rb') as f:
|
|
imgdata = f.read()
|
|
item.pixmap_from_bytes(imgdata)
|
|
|
|
new_item = BeePixmapItem.create_from_data(
|
|
item=item, data={'filename': 'foobar.png'})
|
|
assert new_item is item
|
|
assert item.filename == 'foobar.png'
|
|
assert item.crop == QtCore.QRectF(0, 0, 3, 3)
|
|
assert item.opacity() == 1
|
|
assert item.grayscale is False
|
|
|
|
|
|
def test_create_from_data_with_crop(item):
|
|
new_item = BeePixmapItem.create_from_data(
|
|
item=item, data={'filename': 'foobar.png', 'crop': [10, 20, 30, 40]})
|
|
assert new_item is item
|
|
assert item.filename == 'foobar.png'
|
|
assert item.crop == QtCore.QRectF(10, 20, 30, 40)
|
|
|
|
|
|
def test_create_from_data_with_opacity(item):
|
|
new_item = BeePixmapItem.create_from_data(
|
|
item=item, data={'filename': 'foobar.png', 'opacity': 0.7})
|
|
assert new_item is item
|
|
assert item.filename == 'foobar.png'
|
|
assert item.opacity() == 0.7
|
|
|
|
|
|
def test_create_from_data_with_grayscale(item):
|
|
new_item = BeePixmapItem.create_from_data(
|
|
item=item, data={'filename': 'foobar.png', 'grayscale': True})
|
|
assert new_item is item
|
|
assert item.filename == 'foobar.png'
|
|
assert item.grayscale is True
|
|
|
|
|
|
def test_create_copy(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3), 'foo.png')
|
|
item.setPos(20, 30)
|
|
item.setRotation(33)
|
|
item.do_flip()
|
|
item.setZValue(0.5)
|
|
item.setScale(2.2)
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
item.setOpacity(0.7)
|
|
item.grayscale = True
|
|
|
|
copy = item.create_copy()
|
|
assert copy.pixmap_to_bytes() == item.pixmap_to_bytes()
|
|
assert copy.filename == 'foo.png'
|
|
assert copy.pos() == QtCore.QPointF(20, 30)
|
|
assert copy.rotation() == 33
|
|
assert copy.flip() == -1
|
|
assert copy.zValue() == 0.5
|
|
assert copy.scale() == 2.2
|
|
assert copy.crop == QtCore.QRectF(10, 20, 30, 40)
|
|
assert copy.opacity() == 0.7
|
|
assert copy.grayscale is True
|
|
|
|
|
|
def test_color_gamut_finds_colors(qapp):
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(QtGui.QColor(0, 0, 0))
|
|
img.setPixelColor(1, 1, QtGui.QColor(255, 0, 0))
|
|
img.setPixelColor(5, 5, QtGui.QColor(0, 255, 0))
|
|
img.setPixelColor(5, 6, QtGui.QColor(0, 50, 0))
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
assert item.color_gamut == {(0, 255): 1, (120, 255): 2}
|
|
|
|
|
|
def test_color_gamut_ignores_almost_black(qapp):
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(QtGui.QColor(3, 3, 3))
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
assert item.color_gamut == {}
|
|
|
|
|
|
def test_color_gamut_ignores_almost_white(qapp):
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(QtGui.QColor(253, 253, 253))
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
assert item.color_gamut == {}
|
|
|
|
|
|
def test_color_gamut_ignores_almost_transparent(qapp):
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(QtGui.QColor(255, 0, 0, 3))
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
assert item.color_gamut == {}
|
|
|
|
|
|
def test_copy_to_clipboard(qapp, imgfilename3x3):
|
|
clipboard = QtWidgets.QApplication.clipboard()
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3), 'foo.png')
|
|
item.copy_to_clipboard(clipboard)
|
|
assert clipboard.pixmap().size() == item.pixmap().size()
|
|
|
|
|
|
def test_reset_crop(qapp, imgfilename3x3):
|
|
item = BeePixmapItem(QtGui.QImage(imgfilename3x3))
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
item.reset_crop()
|
|
assert item.crop == QtCore.QRectF(0, 0, 3, 3)
|
|
|
|
|
|
def test_crop_handle_topleft(qapp, item):
|
|
item.crop_temp = QtCore.QRectF(100, 200, 300, 400)
|
|
assert item.crop_handle_topleft() == QtCore.QRectF(100, 200, 15, 15)
|
|
|
|
|
|
def test_crop_handle_bottomleft(qapp, item):
|
|
item.crop_temp = QtCore.QRectF(100, 200, 300, 400)
|
|
assert item.crop_handle_bottomleft() == QtCore.QRectF(100, 585, 15, 15)
|
|
|
|
|
|
def test_crop_handle_bottomright(qapp, item):
|
|
item.crop_temp = QtCore.QRectF(100, 200, 300, 400)
|
|
assert item.crop_handle_bottomright() == QtCore.QRectF(385, 585, 15, 15)
|
|
|
|
|
|
def test_crop_handle_topright(qapp, item):
|
|
item.crop_temp = QtCore.QRectF(100, 200, 300, 400)
|
|
assert item.crop_handle_topright() == QtCore.QRectF(385, 200, 15, 15)
|
|
|
|
|
|
@pytest.mark.parametrize('edge,rotation,expected',
|
|
[('crop_edge_top', 0, 'SizeVerCursor'),
|
|
('crop_edge_top', 90, 'SizeHorCursor'),
|
|
('crop_edge_top', 180, 'SizeVerCursor'),
|
|
('crop_edge_top', 270, 'SizeHorCursor'),
|
|
('crop_edge_bottom', 0, 'SizeVerCursor'),
|
|
('crop_edge_bottom', 90, 'SizeHorCursor'),
|
|
('crop_edge_bottom', 180, 'SizeVerCursor'),
|
|
('crop_edge_bottom', 270, 'SizeHorCursor'),
|
|
('crop_edge_left', 0, 'SizeHorCursor'),
|
|
('crop_edge_left', 90, 'SizeVerCursor'),
|
|
('crop_edge_left', 180, 'SizeHorCursor'),
|
|
('crop_edge_left', 270, 'SizeVerCursor'),
|
|
('crop_edge_right', 0, 'SizeHorCursor'),
|
|
('crop_edge_right', 90, 'SizeVerCursor'),
|
|
('crop_edge_right', 180, 'SizeHorCursor'),
|
|
('crop_edge_right', 270, 'SizeVerCursor')])
|
|
def test_get_crop_edge_cursor(edge, rotation, expected, qapp, item):
|
|
item.setRotation(rotation)
|
|
cursor = item.get_crop_edge_cursor(getattr(item, edge))
|
|
assert cursor == getattr(Qt.CursorShape, expected)
|
|
|
|
|
|
def test_paint(qapp, item):
|
|
item.pixmap = MagicMock()
|
|
item.paint_selectable = MagicMock()
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
painter = MagicMock(
|
|
combinedTransform=MagicMock(
|
|
return_value=MagicMock(
|
|
m11=MagicMock(return_value=0.5))))
|
|
item.paint(painter, None, None)
|
|
item.paint_selectable.assert_called_once()
|
|
painter.drawPixmap.assert_called_with(
|
|
QtCore.QRectF(10, 20, 30, 40),
|
|
item.pixmap(),
|
|
QtCore.QRectF(10, 20, 30, 40))
|
|
|
|
|
|
def test_paint_when_crop_mode(qapp, item):
|
|
item.pixmap = MagicMock()
|
|
item.paint_selectable = MagicMock()
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(11, 22, 29, 39)
|
|
painter = MagicMock(
|
|
combinedTransform=MagicMock(
|
|
return_value=MagicMock(
|
|
m11=MagicMock(return_value=0.5))))
|
|
item.paint(painter, None, None)
|
|
item.paint_selectable.assert_not_called()
|
|
painter.drawPixmap.assert_called_with(0, 0, item.pixmap())
|
|
|
|
|
|
def test_enter_crop_mode(view, item):
|
|
view.scene.addItem(item)
|
|
item.crop = QtCore.QRectF(10, 20, 30, 40)
|
|
item.update = MagicMock()
|
|
item.prepareGeometryChange = MagicMock()
|
|
item.grabKeyboard = MagicMock()
|
|
|
|
item.enter_crop_mode()
|
|
assert item.crop_mode is True
|
|
assert item.crop_temp == QtCore.QRectF(10, 20, 30, 40)
|
|
assert item.crop_mode_move is None
|
|
assert item.crop_mode_event_start is None
|
|
item.update.assert_called_once_with()
|
|
item.prepareGeometryChange.assert_called_once_with()
|
|
item.grabKeyboard.assert_called_once_with()
|
|
assert view.scene.crop_item == item
|
|
|
|
|
|
def test_exit_crop_mode_confirmed(view, item):
|
|
view.scene.addItem(item)
|
|
item.update = MagicMock()
|
|
item.prepareGeometryChange = MagicMock()
|
|
item.ungrabKeyboard = MagicMock()
|
|
item.crop = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_temp = QtCore.QRectF(10, 20, 30, 40)
|
|
item.crop_mode = True
|
|
item.crop_mode_move = 'topleft'
|
|
item.crop_mode_event_start = QtCore.QRectF(1, 1, 1, 1)
|
|
|
|
item.exit_crop_mode(confirm=True)
|
|
item.crop == QtCore.QRectF(10, 20, 30, 40)
|
|
assert item.crop_mode is False
|
|
assert item.crop_temp is None
|
|
assert item.crop_mode_move is None
|
|
assert item.crop_mode_event_start is None
|
|
item.update.assert_called()
|
|
item.prepareGeometryChange.assert_called()
|
|
item.ungrabKeyboard.assert_called_once_with()
|
|
assert view.scene.crop_item is None
|
|
view.scene.undo_stack.canUndo() is True
|
|
|
|
|
|
def test_exit_crop_mode_confirmed_no_change(view, item):
|
|
view.scene.addItem(item)
|
|
item.crop = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_mode = True
|
|
|
|
item.exit_crop_mode(confirm=True)
|
|
assert item.crop == QtCore.QRectF(0, 0, 100, 80)
|
|
view.scene.undo_stack.canUndo() is False
|
|
|
|
|
|
def test_exit_crop_mode_not_confirmed(view, item):
|
|
view.scene.addItem(item)
|
|
item.update = MagicMock()
|
|
item.prepareGeometryChange = MagicMock()
|
|
item.ungrabKeyboard = MagicMock()
|
|
item.crop = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_temp = QtCore.QRectF(10, 20, 30, 40)
|
|
item.crop_mode = True
|
|
item.crop_mode_move = 'topleft'
|
|
item.crop_mode_event_start = QtCore.QRectF(1, 1, 1, 1)
|
|
|
|
item.exit_crop_mode(confirm=False)
|
|
item.crop == QtCore.QRectF(0, 0, 100, 80)
|
|
assert item.crop_mode is False
|
|
assert item.crop_temp is None
|
|
assert item.crop_mode_move is None
|
|
assert item.crop_mode_event_start is None
|
|
item.update.assert_called()
|
|
item.prepareGeometryChange.assert_called()
|
|
item.ungrabKeyboard.assert_called_once_with()
|
|
assert view.scene.crop_item is None
|
|
view.scene.undo_stack.canUndo() is False
|
|
|
|
|
|
@patch('PyQt6.QtWidgets.QGraphicsPixmapItem.keyPressEvent')
|
|
def test_key_press_event_return(key_mock, qapp, item):
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.key.return_value = Qt.Key.Key_Return
|
|
item.keyPressEvent(event)
|
|
item.exit_crop_mode.assert_called_once_with(confirm=True)
|
|
key_mock.assert_not_called()
|
|
|
|
|
|
@patch('PyQt6.QtWidgets.QGraphicsPixmapItem.keyPressEvent')
|
|
def test_key_press_event_escape(key_mock, qapp, item):
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.key.return_value = Qt.Key.Key_Escape
|
|
item.keyPressEvent(event)
|
|
item.exit_crop_mode.assert_called_once_with(confirm=False)
|
|
key_mock.assert_not_called()
|
|
|
|
|
|
@patch('PyQt6.QtWidgets.QGraphicsPixmapItem.keyPressEvent')
|
|
def test_key_press_event_other(key_mock, qapp, item):
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.key.return_value = Qt.Key.Key_Space
|
|
item.keyPressEvent(event)
|
|
item.exit_crop_mode.assert_not_called()
|
|
key_mock.assert_called_once_with(event)
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.hoverMoveEvent')
|
|
def test_hover_move_event_when_not_crop_mode(hover_mock, qapp, item):
|
|
item.crop_mode = False
|
|
event = MagicMock()
|
|
|
|
item.hoverMoveEvent(event)
|
|
hover_mock.assert_called_once_with(event)
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.hoverMoveEvent')
|
|
def test_hover_move_event_crop_mode_inside_handle(hover_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(5, 5)
|
|
|
|
item.hoverMoveEvent(event)
|
|
item.cursor() == Qt.CursorShape.SizeFDiagCursor
|
|
hover_mock.assert_not_called()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.hoverMoveEvent')
|
|
def test_hover_move_event_crop_mode_inside_edge(hover_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(5, 40)
|
|
|
|
item.hoverMoveEvent(event)
|
|
item.cursor() == Qt.CursorShape.SizeHorCursor
|
|
hover_mock.assert_not_called()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.hoverMoveEvent')
|
|
def test_hover_move_event_crop_mode_outside_handle(hover_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
item.setCursor(Qt.CursorShape.SizeFDiagCursor)
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(50, 50)
|
|
|
|
item.hoverMoveEvent(event)
|
|
item.cursor() == Qt.CursorShape.ArrowCursor
|
|
hover_mock.assert_not_called()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mousePressEvent')
|
|
def test_mouse_press_event_when_not_crop_mode(mouse_mock, qapp, item):
|
|
item.crop_mode = False
|
|
item.crop_mode_move = None
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
|
|
item.mousePressEvent(event)
|
|
assert item.crop_mode_move is None
|
|
item.exit_crop_mode.assert_not_called()
|
|
mouse_mock.assert_called_once_with(event)
|
|
event.accept.assert_not_called()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mousePressEvent')
|
|
def test_mouse_press_event_crop_mode_inside_handle(mouse_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_mode_move = None
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(5, 5)
|
|
|
|
item.mousePressEvent(event)
|
|
assert item.crop_mode_move == item.crop_handle_topleft
|
|
assert item.crop_mode_event_start == QtCore.QPointF(5, 5)
|
|
item.exit_crop_mode.assert_not_called()
|
|
mouse_mock.assert_not_called()
|
|
event.accept.assert_called_once_with()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mousePressEvent')
|
|
def test_mouse_press_event_crop_mode_inside_edge(mouse_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_mode_move = None
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(5, 40)
|
|
|
|
item.mousePressEvent(event)
|
|
assert item.crop_mode_move == item.crop_edge_left
|
|
assert item.crop_mode_event_start == QtCore.QPointF(5, 40)
|
|
item.exit_crop_mode.assert_not_called()
|
|
mouse_mock.assert_not_called()
|
|
event.accept.assert_called_once_with()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mousePressEvent')
|
|
def test_mouse_press_event_crop_mode_outside_handle_inside_crop(
|
|
mouse_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_mode_move = None
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(50, 50)
|
|
|
|
item.mousePressEvent(event)
|
|
assert item.crop_mode_move is None
|
|
item.exit_crop_mode.assert_called_once_with(confirm=True)
|
|
mouse_mock.assert_not_called()
|
|
event.accept.assert_called_once_with()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mousePressEvent')
|
|
def test_mouse_press_event_crop_mode_outside_handle_outside_crop(
|
|
mouse_mock, qapp, item):
|
|
item.crop_mode = True
|
|
item.crop_temp = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_mode_move = None
|
|
item.exit_crop_mode = MagicMock()
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(150, 150)
|
|
|
|
item.mousePressEvent(event)
|
|
assert item.crop_mode_move is None
|
|
item.exit_crop_mode.assert_called_once_with(confirm=False)
|
|
mouse_mock.assert_not_called()
|
|
event.accept.assert_called_once_with()
|
|
|
|
|
|
@pytest.mark.parametrize('point,handle,expected',
|
|
[((25, 40), 'crop_handle_topleft', (25, 40)),
|
|
((0, 0), 'crop_handle_topleft', (0, 0)),
|
|
((-5, -5), 'crop_handle_topleft', (0, 0)),
|
|
((40, 60), 'crop_handle_topleft', (40, 60)),
|
|
((100, 80), 'crop_handle_topleft', (40, 60)),
|
|
((25, 40), 'crop_handle_bottomleft', (25, 40)),
|
|
((0, 80), 'crop_handle_bottomleft', (0, 80)),
|
|
((-5, 85), 'crop_handle_bottomleft', (0, 80)),
|
|
((40, 20), 'crop_handle_bottomleft', (40, 20)),
|
|
((45, 15), 'crop_handle_bottomleft', (40, 20)),
|
|
((25, 40), 'crop_handle_bottomright', (25, 40)),
|
|
((10, 20), 'crop_handle_bottomright', (10, 20)),
|
|
((5, 15), 'crop_handle_bottomright', (10, 20)),
|
|
((100, 80), 'crop_handle_bottomright', (100, 80)),
|
|
((105, 85), 'crop_handle_bottomright', (100, 80)),
|
|
((25, 40), 'crop_handle_topright', (25, 40)),
|
|
((10, 0), 'crop_handle_topright', (10, 0)),
|
|
((5, -5), 'crop_handle_topright', (10, 0)),
|
|
((100, 60), 'crop_handle_topright', (100, 60)),
|
|
((105, 65), 'crop_handle_topright', (100, 60)),
|
|
((25, 40), 'crop_edge_top', (25, 40)),
|
|
((0, 0), 'crop_edge_top', (0, 0)),
|
|
((-5, -5), 'crop_edge_top', (0, 0)),
|
|
((100, 60), 'crop_edge_top', (100, 60)),
|
|
((105, 65), 'crop_edge_top', (100, 60)),
|
|
((25, 40), 'crop_edge_bottom', (25, 40)),
|
|
((0, 20), 'crop_edge_bottom', (0, 20)),
|
|
((-5, 15), 'crop_edge_bottom', (0, 20)),
|
|
((100, 80), 'crop_edge_bottom', (100, 80)),
|
|
((105, 85), 'crop_edge_bottom', (100, 80)),
|
|
((25, 40), 'crop_edge_left', (25, 40)),
|
|
((0, 0), 'crop_edge_left', (0, 0)),
|
|
((-5, -5), 'crop_edge_left', (0, 0)),
|
|
((40, 80), 'crop_edge_left', (40, 80)),
|
|
((45, 85), 'crop_edge_left', (40, 80)),
|
|
((25, 40), 'crop_edge_right', (25, 40)),
|
|
((10, 0), 'crop_edge_right', (10, 0)),
|
|
((5, -5), 'crop_edge_right', (10, 0)),
|
|
((100, 80), 'crop_edge_right', (100, 80)),
|
|
((105, 85), 'crop_edge_right', (100, 80))])
|
|
def test_ensure_point_within_crop_bounds(
|
|
point, handle, expected, qapp, item):
|
|
pixmap = MagicMock()
|
|
pixmap.size.return_value = QtCore.QRectF(0, 0, 100, 80)
|
|
item.pixmap = MagicMock(return_value=pixmap)
|
|
item.crop_temp = QtCore.QRectF(10, 20, 30, 40)
|
|
result = item.ensure_point_within_crop_bounds(
|
|
QtCore.QPointF(*point), getattr(item, handle))
|
|
assert result == QtCore.QPointF(*expected)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'start,pos,handle,expected',
|
|
[[(10, 10), (5, 5), 'crop_handle_topleft', (5, 15, 35, 45)],
|
|
[(10, 60), (5, 55), 'crop_handle_bottomleft', (5, 20, 35, 35)],
|
|
[(40, 60), (35, 55), 'crop_handle_bottomright', (10, 20, 25, 35)],
|
|
[(40, 10), (35, 5), 'crop_handle_topright', (10, 15, 25, 45)],
|
|
[(25, 10), (20, 5), 'crop_edge_top', (10, 15, 30, 45)],
|
|
[(10, 40), (5, 35), 'crop_edge_left', (5, 20, 35, 40)],
|
|
[(35, 25), (30, 20), 'crop_edge_bottom', (10, 20, 30, 35)],
|
|
[(40, 40), (35, 35), 'crop_edge_right', (10, 20, 25, 40)]])
|
|
@patch('beeref.selection.SelectableMixin.mouseMoveEvent')
|
|
def test_mouse_move_when_crop_mode_inside_handle(
|
|
mouse_mock, start, pos, handle, expected, qapp, item):
|
|
pixmap = MagicMock()
|
|
pixmap.size.return_value = QtCore.QRectF(0, 0, 100, 80)
|
|
item.crop_mode = True
|
|
item.pixmap = MagicMock(return_value=pixmap)
|
|
item.crop_temp = QtCore.QRectF(10, 20, 30, 40)
|
|
item.crop_mode_event_start = QtCore.QPointF(*start)
|
|
item.crop_mode_move = getattr(item, handle)
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(*pos)
|
|
|
|
item.mouseMoveEvent(event)
|
|
assert item.crop_temp == QtCore.QRectF(*expected)
|
|
event.accept.assert_called_once()
|
|
mouse_mock.assert_not_called()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mouseMoveEvent')
|
|
def test_mouse_move_when_not_crop_mode(mouse_mock, qapp, item):
|
|
event = MagicMock()
|
|
event.pos.return_value = QtCore.QPointF(30, 50)
|
|
|
|
item.mouseMoveEvent(event)
|
|
event.accept.assert_not_called()
|
|
mouse_mock.assert_called_once_with(event)
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mouseReleaseEvent')
|
|
def test_mouse_release_event_when_crop_mode(mouse_mock, qapp, item):
|
|
event = MagicMock()
|
|
item.crop_mode = True
|
|
item.crop_mode_move = item.crop_handle_topright
|
|
item.crop_mode_event_start = QtCore.QPointF(44, 55)
|
|
|
|
item.mouseReleaseEvent(event)
|
|
assert item.crop_mode is True
|
|
assert item.crop_mode_move is None
|
|
assert item.crop_mode_event_start is None
|
|
event.accept.assert_called_once()
|
|
mouse_mock.assert_not_called()
|
|
|
|
|
|
@patch('beeref.selection.SelectableMixin.mouseReleaseEvent')
|
|
def test_mouse_release_event_when_not_crop_mode(mouse_mock, qapp, item):
|
|
event = MagicMock()
|
|
item.crop_mode = False
|
|
|
|
item.mouseReleaseEvent(event)
|
|
assert item.crop_mode is False
|
|
event.accept.assert_not_called()
|
|
mouse_mock.assert_called_once_with(event)
|
|
|
|
|
|
def test_sample_color_at_returns_color(qapp, view):
|
|
color = QtGui.QColor(255, 0, 0, 3)
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(color)
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
view.scene.addItem(item)
|
|
assert item.sample_color_at(QtCore.QPointF(2, 2)) == color
|
|
|
|
|
|
def test_sample_color_at_returns_none_when_fully_transparent(qapp, view):
|
|
color = QtGui.QColor(255, 0, 0, 0)
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(color)
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
view.scene.addItem(item)
|
|
assert item.sample_color_at(QtCore.QPointF(2, 2)) is None
|
|
|
|
|
|
def test_sample_color_in_greyscale_mode(qapp, view):
|
|
color = QtGui.QColor(255, 0, 0)
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(color)
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
item.grayscale = True
|
|
view.scene.addItem(item)
|
|
gray = item.sample_color_at(QtCore.QPointF(2, 2))
|
|
print(gray.red(), gray.green(), gray.blue(), gray.alpha())
|
|
assert gray == QtGui.QColor(130, 130, 130)
|
|
|
|
|
|
def test_sample_color_at_returns_none_when_transparent(qapp, view):
|
|
color = QtGui.QColor(255, 0, 0, 0)
|
|
img = QtGui.QImage(10, 10, QtGui.QImage.Format.Format_ARGB32)
|
|
img.fill(color)
|
|
item = BeePixmapItem(img, 'foo.png')
|
|
view.scene.addItem(item)
|
|
assert item.sample_color_at(QtCore.QPointF(2, 2)) is None
|