mirror of
https://github.com/rbreu/beeref.git
synced 2026-03-11 08:54:28 +00:00
Fix color sampling while multiple items are selected
This commit is contained in:
parent
2af6a75cc3
commit
5f4c5088f0
5 changed files with 97 additions and 4 deletions
|
|
@ -43,9 +43,6 @@ def register_item(cls):
|
|||
class BeeItemMixin(SelectableMixin):
|
||||
"""Base for all items added by the user."""
|
||||
|
||||
def sample_color_at(self, pos):
|
||||
return None
|
||||
|
||||
def set_pos_center(self, pos):
|
||||
"""Sets the position using the item's center as the origin point."""
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,9 @@ class BaseItemMixin:
|
|||
if self.scene():
|
||||
self.scene().cursor_cleared.emit()
|
||||
|
||||
def sample_color_at(self, pos):
|
||||
return None
|
||||
|
||||
|
||||
class SelectableMixin(BaseItemMixin):
|
||||
"""Common code for selectable items: Selection outline, handles etc."""
|
||||
|
|
@ -640,7 +643,15 @@ class MultiSelectItem(SelectableMixin,
|
|||
def selection_action_items(self):
|
||||
"""The items affected by selection actions like scaling and rotating.
|
||||
"""
|
||||
return list(self.scene().selectedItems())
|
||||
if self.scene():
|
||||
return list(self.scene().selectedItems())
|
||||
return []
|
||||
|
||||
def lower_behind_selection(self):
|
||||
items = self.selection_action_items()
|
||||
if items:
|
||||
min_z = min(item.zValue() for item in items)
|
||||
self.setZValue(min_z - self.scene().Z_STEP)
|
||||
|
||||
def fit_selection_area(self, rect):
|
||||
"""Updates itself to fit the given selection area."""
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ class BeeGraphicsView(MainControlsMixin,
|
|||
if hasattr(self, 'sample_color_widget'):
|
||||
self.sample_color_widget.hide()
|
||||
del self.sample_color_widget
|
||||
if self.scene.has_multi_selection():
|
||||
self.scene.multi_select_item.bring_to_front()
|
||||
|
||||
def update_window_title(self):
|
||||
clean = self.undo_stack.isClean()
|
||||
|
|
@ -358,6 +360,11 @@ class BeeGraphicsView(MainControlsMixin,
|
|||
self.viewport().setCursor(Qt.CursorShape.CrossCursor)
|
||||
self.active_mode = self.SAMPLE_COLOR_MODE
|
||||
|
||||
if self.scene.has_multi_selection():
|
||||
# We don't want to sample the multi select item, so
|
||||
# temporarily send it to the back:
|
||||
self.scene.multi_select_item.lower_behind_selection()
|
||||
|
||||
pos = self.mapFromGlobal(self.cursor().pos())
|
||||
self.sample_color_widget = widgets.SampleColorWidget(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,46 @@ def test_selection_action_items(view):
|
|||
assert action_items == {item1, item2, view.scene.multi_select_item}
|
||||
|
||||
|
||||
def test_lower_behind_selection_when_selection(view):
|
||||
item1 = BeePixmapItem(QtGui.QImage())
|
||||
view.scene.addItem(item1)
|
||||
item1.setSelected(True)
|
||||
item2 = BeePixmapItem(QtGui.QImage())
|
||||
view.scene.addItem(item2)
|
||||
item2.setSelected(True)
|
||||
item3 = BeePixmapItem(QtGui.QImage())
|
||||
view.scene.addItem(item3)
|
||||
item3.setSelected(False)
|
||||
|
||||
item1.setZValue(3)
|
||||
item2.setZValue(4)
|
||||
item3.setZValue(1)
|
||||
|
||||
view.scene.multi_select_item.setZValue(5)
|
||||
view.scene.multi_select_item.lower_behind_selection()
|
||||
assert view.scene.multi_select_item.zValue() == 2.999
|
||||
|
||||
|
||||
def test_lower_behind_selection_when_no_selection(view):
|
||||
item1 = BeePixmapItem(QtGui.QImage())
|
||||
view.scene.addItem(item1)
|
||||
item1.setSelected(False)
|
||||
item2 = BeePixmapItem(QtGui.QImage())
|
||||
view.scene.addItem(item2)
|
||||
item2.setSelected(False)
|
||||
item3 = BeePixmapItem(QtGui.QImage())
|
||||
view.scene.addItem(item3)
|
||||
item3.setSelected(False)
|
||||
|
||||
item1.setZValue(3)
|
||||
item2.setZValue(4)
|
||||
item3.setZValue(1)
|
||||
|
||||
view.scene.multi_select_item.setZValue(5)
|
||||
view.scene.multi_select_item.lower_behind_selection()
|
||||
assert view.scene.multi_select_item.zValue() == 5
|
||||
|
||||
|
||||
def test_fit_selection_area():
|
||||
item = MultiSelectItem()
|
||||
item.setScale(5)
|
||||
|
|
|
|||
|
|
@ -658,6 +658,24 @@ def test_on_action_sample_color(view):
|
|||
view.cancel_active_modes.assert_called_once_with()
|
||||
|
||||
|
||||
def test_on_action_sample_color_when_multi_selection(view, item):
|
||||
view.scene.addItem(item)
|
||||
item.setSelected(True)
|
||||
item2 = BeeTextItem('foo')
|
||||
view.scene.addItem(item2)
|
||||
item2.setSelected(True)
|
||||
|
||||
view.cancel_active_modes = MagicMock()
|
||||
view.scene.multi_select_item.lower_behind_selection = MagicMock()
|
||||
view.on_action_sample_color()
|
||||
assert view.active_mode == view.SAMPLE_COLOR_MODE
|
||||
assert isinstance(view.sample_color_widget, widgets.SampleColorWidget)
|
||||
assert view.viewport().cursor() == Qt.CursorShape.CrossCursor
|
||||
view.cancel_active_modes.assert_called_once_with()
|
||||
view.scene.multi_select_item.lower_behind_selection\
|
||||
.assert_called_once_with()
|
||||
|
||||
|
||||
@patch('PyQt6.QtWidgets.QWidget.create')
|
||||
@patch('PyQt6.QtWidgets.QWidget.destroy')
|
||||
@patch('PyQt6.QtWidgets.QWidget.show')
|
||||
|
|
@ -815,6 +833,26 @@ def test_cancel_active_modes_when_sample_color_mode(view):
|
|||
assert view.viewport().cursor() == Qt.CursorShape.ArrowCursor
|
||||
|
||||
|
||||
def test_cancel_sample_color_mode_when_multi_selection(view, item):
|
||||
view.scene.addItem(item)
|
||||
item.setSelected(True)
|
||||
item2 = BeeTextItem('foo')
|
||||
view.scene.addItem(item2)
|
||||
item2.setSelected(True)
|
||||
|
||||
view.scene.multi_select_item.bring_to_front = MagicMock()
|
||||
view.active_mode = view.SAMPLE_COLOR_MODE
|
||||
view.sample_color_widget = widgets.SampleColorWidget(
|
||||
view, MagicMock(), MagicMock())
|
||||
view.viewport().setCursor(Qt.CursorShape.CrossCursor)
|
||||
view.cancel_active_modes()
|
||||
|
||||
assert view.active_mode is None
|
||||
assert hasattr(view, 'sample_color_widget') is False
|
||||
assert view.viewport().cursor() == Qt.CursorShape.ArrowCursor
|
||||
view.scene.multi_select_item.bring_to_front.assert_called_once()
|
||||
|
||||
|
||||
@patch('PyQt6.QtGui.QUndoStack.isClean', return_value=True)
|
||||
def test_update_window_title_no_changes_no_filename(clear_mock, view):
|
||||
view.filename = None
|
||||
|
|
|
|||
Loading…
Reference in a new issue