From 740e9bab8783695ac914a7941d161a6c1fc5e9dd Mon Sep 17 00:00:00 2001 From: grossmj Date: Sat, 2 Mar 2019 16:26:41 +0700 Subject: [PATCH] Handle locking/unlocking items independently from the layer position. --- gns3/graphics_view.py | 43 +++++++++++------------------- gns3/items/drawing_item.py | 25 ++++++++++++----- gns3/items/ellipse_item.py | 9 +------ gns3/items/image_item.py | 7 ----- gns3/items/label_item.py | 13 --------- gns3/items/line_item.py | 15 +++-------- gns3/items/node_item.py | 25 ++++++++++++++--- gns3/items/rectangle_item.py | 7 ----- gns3/items/shape_item.py | 8 +++--- gns3/items/text_item.py | 7 ----- gns3/main_window.py | 20 +++++++------- gns3/node.py | 16 ++++++++--- gns3/topology.py | 4 +-- tests/items/test_line_item.py | 1 + tests/items/test_rectangle_item.py | 1 + tests/test_node.py | 4 +++ tests/test_topology.py | 12 ++++++--- 17 files changed, 101 insertions(+), 116 deletions(-) diff --git a/gns3/graphics_view.py b/gns3/graphics_view.py index 09bc21b8..08b5fedf 100644 --- a/gns3/graphics_view.py +++ b/gns3/graphics_view.py @@ -466,13 +466,8 @@ class GraphicsView(QtWidgets.QGraphicsView): if not event.modifiers() & QtCore.Qt.ControlModifier: for it in self.scene().items(): it.setSelected(False) - if item.zValue() < 0: - item.setFlag(item.ItemIsSelectable, True) item.setSelected(True) self._showDeviceContextualMenu(QtGui.QCursor.pos()) - if not sip.isdeleted(item) and item.zValue() < 0: - item.setFlag(item.ItemIsSelectable, False) - else: self._showDeviceContextualMenu(QtGui.QCursor.pos()) # when more than one item is selected display the contextual menu even if mouse is not above an item @@ -1461,11 +1456,7 @@ class GraphicsView(QtWidgets.QGraphicsView): for item in self.scene().selectedItems(): if item.parentItem() is None: - current_zvalue = item.zValue() - if not (item.flags() & QtWidgets.QGraphicsItem.ItemIsMovable): - log.error("Cannot move object to a upper layer because it is locked") - continue - item.setZValue(current_zvalue + 1) + item.setZValue(item.zValue() + 1) item.updateNode() item.update() @@ -1477,17 +1468,10 @@ class GraphicsView(QtWidgets.QGraphicsView): for item in self.scene().selectedItems(): if item.parentItem() is None: - current_zvalue = item.zValue() - if not (item.flags() & QtWidgets.QGraphicsItem.ItemIsMovable): - log.error("Cannot move object to a lower layer because it is locked") - continue - item.setZValue(current_zvalue - 1) + item.setZValue(item.zValue() - 1) item.updateNode() item.update() - if item.zValue() == -1: - self._background_warning_msgbox.showMessage("Object moved to a background layer. You will now have to use the right-click action to select this object in the future and raise it to layer 0 to be able to move it") - def lockActionSlot(self): """ Slot to receive events from the lock action in the @@ -1495,8 +1479,11 @@ class GraphicsView(QtWidgets.QGraphicsView): """ for item in self.scene().selectedItems(): - if not isinstance(item, LinkItem): - item.setZValue(-(item.zValue() + 1)) + if not isinstance(item, LinkItem) and not isinstance(item, LabelItem): + if item.locked() is True: + item.setLocked(False) + else: + item.setLocked(True) if item.parentItem() is None: item.updateNode() item.update() @@ -1557,9 +1544,9 @@ class GraphicsView(QtWidgets.QGraphicsView): pos = self.mapToScene(pos) return TemplateManager().instance().createNodeFromTemplateId(self._topology.project(), template_id, pos.x(), pos.y()) - def createNodeItem(self, node, symbol, x, y, z): + def createNodeItem(self, node, symbol, x, y): node.setSymbol(symbol) - node.setPos(x, y, z) + node.setPos(x, y) node_item = NodeItem(node) self.scene().addItem(node_item) @@ -1582,18 +1569,18 @@ class GraphicsView(QtWidgets.QGraphicsView): if self._main_window and not sip.isdeleted(self._main_window): QtWidgets.QMessageBox.critical(self._main_window, name, message.strip()) - def createDrawingItem(self, type, x, y, z, rotation=0, svg=None, drawing_id=None): + def createDrawingItem(self, type, x, y, z, locked=False, rotation=0, svg=None, drawing_id=None): if type == "ellipse": - item = EllipseItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = EllipseItem(pos=QtCore.QPoint(x, y), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "rect": - item = RectangleItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = RectangleItem(pos=QtCore.QPoint(x, y), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "line": - item = LineItem(pos=QtCore.QPoint(x, y), dst=QtCore.QPoint(200, 0), z=z, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = LineItem(pos=QtCore.QPoint(x, y), dst=QtCore.QPoint(200, 0), z=z, locked=locked, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "image": - item = ImageItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = ImageItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, locked=locked, project=self._topology.project(), drawing_id=drawing_id, svg=svg) elif type == "text": - item = TextItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, project=self._topology.project(), drawing_id=drawing_id, svg=svg) + item = TextItem(pos=QtCore.QPoint(x, y), z=z, rotation=rotation, locked=locked, project=self._topology.project(), drawing_id=drawing_id, svg=svg) if drawing_id is None: item.create() diff --git a/gns3/items/drawing_item.py b/gns3/items/drawing_item.py index 2b7d1b19..204921e9 100644 --- a/gns3/items/drawing_item.py +++ b/gns3/items/drawing_item.py @@ -41,9 +41,10 @@ class DrawingItem: Base class for non emulation item """ - def __init__(self, project=None, pos=None, drawing_id=None, svg=None, z=0, rotation=0, **kws): + def __init__(self, project=None, pos=None, drawing_id=None, svg=None, z=0, locked=False, rotation=0, **kws): self._id = drawing_id self._deleting = False + self._locked = locked if self._id is None: self._id = str(uuid.uuid4()) self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsFocusable | QtWidgets.QGraphicsItem.ItemIsSelectable | QtWidgets.QGraphicsItem.ItemSendsGeometryChanges) @@ -65,6 +66,8 @@ class DrawingItem: if rotation: self.setRotation(rotation) + self.setLocked(locked) + def drawing_id(self): return self._id @@ -106,6 +109,7 @@ class DrawingItem: return False self.setPos(QtCore.QPoint(result["x"], result["y"])) self.setZValue(result["z"]) + self.setLocked(result["locked"]) self.setRotation(result["rotation"]) if "svg" in result: self.fromSvg(result["svg"]) @@ -149,6 +153,7 @@ class DrawingItem: "x": int(self.pos().x()), "y": int(self.pos().y()), "z": int(self.zValue()), + "locked": self._locked, "rotation": int(self.rotation()) } svg = self.toSvg() @@ -158,23 +163,29 @@ class DrawingItem: self._hash_svg = hash_svg return data - def setZValue(self, value): + def locked(self): """ - Sets a new Z value. + Is the drawing locked + """ + + return self._locked + + def setLocked(self, locked): + """ + Sets the locked value. :param value: Z value """ - QtWidgets.QGraphicsItem.setZValue(self, value) - - if self.zValue() < 0: + if locked is True: self.setFlag(self.ItemIsMovable, False) else: self.setFlag(self.ItemIsMovable, True) + self._locked = locked def deleting(self): """ - Is the link being deleted + Is the drawing being deleted """ return self._deleting diff --git a/gns3/items/ellipse_item.py b/gns3/items/ellipse_item.py index ea8a4259..b22ba554 100644 --- a/gns3/items/ellipse_item.py +++ b/gns3/items/ellipse_item.py @@ -22,7 +22,7 @@ Graphical representation of an ellipse on the QGraphicsScene. import math import xml.etree.ElementTree as ET -from ..qt import QtCore, QtGui, QtWidgets +from ..qt import QtWidgets from .shape_item import ShapeItem @@ -48,13 +48,6 @@ class EllipseItem(QtWidgets.QGraphicsEllipseItem, ShapeItem): super().paint(painter, option, widget) self.drawLayerInfo(painter) - def setZValue(self, value): - """ - Sets Z value of the item - :param value: z layer - """ - return ShapeItem.setZValue(self, value) - def toSvg(self): """ Return an SVG version of the shape diff --git a/gns3/items/image_item.py b/gns3/items/image_item.py index 3a8879ff..1dd78219 100644 --- a/gns3/items/image_item.py +++ b/gns3/items/image_item.py @@ -67,13 +67,6 @@ class ImageItem(QtSvg.QGraphicsSvgItem, DrawingItem): super().paint(painter, option, widget) self.drawLayerInfo(painter) - def setZValue(self, value): - """ - Sets Z value of the item - :param value: z layer - """ - return DrawingItem.setZValue(self, value) - def fromSvg(self, svg): renderer = QImageSvgRenderer(svg) self.setSharedRenderer(renderer) diff --git a/gns3/items/label_item.py b/gns3/items/label_item.py index 8f73027a..345c741a 100644 --- a/gns3/items/label_item.py +++ b/gns3/items/label_item.py @@ -170,19 +170,6 @@ class LabelItem(QtWidgets.QGraphicsTextItem): zval = str(int(self.zValue())) painter.drawText(QtCore.QPointF(center.x(), center.y()), zval) - def setZValue(self, value): - """ - Sets a new Z value. - - :param value: Z value - """ - - super().setZValue(value) - if self.zValue() < 0: - self.setFlag(self.ItemIsMovable, False) - else: - self.setFlag(self.ItemIsMovable, True) - def setStyle(self, new_style): """ Set text style using a SVG style diff --git a/gns3/items/line_item.py b/gns3/items/line_item.py index afe14af2..cc51bee4 100644 --- a/gns3/items/line_item.py +++ b/gns3/items/line_item.py @@ -63,13 +63,6 @@ class LineItem(QtWidgets.QGraphicsLineItem, DrawingItem): super().paint(painter, option, widget) self.drawLayerInfo(painter) - def setZValue(self, value): - """ - Sets Z value of the item - :param value: z layer - """ - return DrawingItem.setZValue(self, value) - def toSvg(self): """ Return an SVG version of the shape @@ -126,8 +119,8 @@ class LineItem(QtWidgets.QGraphicsLineItem, DrawingItem): :param event: QGraphicsSceneHoverEvent instance """ - # objects on the background layer don't need cursors - if self.zValue() >= 0: + # locked objects don't need cursors + if not self.locked(): if self._isHorizontalLine(): if event.pos().x() > (self.line().x2() - self._border): @@ -218,6 +211,6 @@ class LineItem(QtWidgets.QGraphicsLineItem, DrawingItem): :param event: QGraphicsSceneHoverEvent instance """ - # objects on the background layer don't need cursors - if self.zValue() >= 0: + # locked objects don't need cursors + if not self.locked(): self._graphics_view.setCursor(QtCore.Qt.ArrowCursor) diff --git a/gns3/items/node_item.py b/gns3/items/node_item.py index e475c596..5ef9e773 100644 --- a/gns3/items/node_item.py +++ b/gns3/items/node_item.py @@ -50,6 +50,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem): # link items connected to this node item. self._links = [] self._symbol = None + self._locked = False # says if the attached node has been initialized # by the server. @@ -78,7 +79,8 @@ class NodeItem(QtSvg.QGraphicsSvgItem): self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges) self.setAcceptHoverEvents(True) - # update z value and set proper flags - not movable in case z < 0 + # update z value and locked state + self.setLocked(self._node.locked()) self.setZValue(self._node.z()) # connect signals to know about some events @@ -272,7 +274,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem): self.setSymbol(self._node.settings().get("symbol")) self.setPos(self._node.settings().get("x", 0), self._node.settings().get("y", 0)) self.setZValue(self._node.settings().get("z", 0)) - + self.setLocked(self._node.settings().get("locked", False)) self._updateLabel() # update the link tooltips in case the @@ -388,7 +390,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem): self._node_label.setStyle(style) self._node_label.setRotation(label_data.get("rotation", 0)) - if self._node.z() < 0: + if self._node.locked(): self._node_label.setFlag(self.ItemIsMovable, False) if label_data["x"] is None: @@ -531,7 +533,21 @@ class NodeItem(QtSvg.QGraphicsSvgItem): """ super().setZValue(value) - if self.zValue() < 0: + for link in self._links: + link.adjust() + + def locked(self): + + return self._locked + + def setLocked(self, locked): + """ + Sets the locked value. + + :param value: Z value + """ + + if locked is True: self.setFlag(self.ItemIsMovable, False) if self._node_label: self._node_label.setFlag(self.ItemIsMovable, False) @@ -541,6 +557,7 @@ class NodeItem(QtSvg.QGraphicsSvgItem): self._node_label.setFlag(self.ItemIsMovable, True) for link in self._links: link.adjust() + self._locked = locked def hoverEnterEvent(self, event): """ diff --git a/gns3/items/rectangle_item.py b/gns3/items/rectangle_item.py index 274191d2..ba94b04e 100644 --- a/gns3/items/rectangle_item.py +++ b/gns3/items/rectangle_item.py @@ -46,13 +46,6 @@ class RectangleItem(QtWidgets.QGraphicsRectItem, ShapeItem): super().paint(painter, option, widget) self.drawLayerInfo(painter) - def setZValue(self, value): - """ - Sets Z value of the item - :param value: z layer - """ - return ShapeItem.setZValue(self, value) - def toSvg(self): """ Return an SVG version of the shape diff --git a/gns3/items/shape_item.py b/gns3/items/shape_item.py index dfe56220..4a51ffb2 100644 --- a/gns3/items/shape_item.py +++ b/gns3/items/shape_item.py @@ -147,8 +147,8 @@ class ShapeItem(DrawingItem): :param event: QGraphicsSceneHoverEvent instance """ - # objects on the background layer don't need cursors - if self.zValue() >= 0: + # locked objects don't need cursors + if not self.locked(): if event.pos().x() > (self.rect().right() - self._border): self._graphics_view.setCursor(QtCore.Qt.SizeHorCursor) elif event.pos().x() < (self.rect().left() + self._border): @@ -167,8 +167,8 @@ class ShapeItem(DrawingItem): :param event: QGraphicsSceneHoverEvent instance """ - # objects on the background layer don't need cursors - if self.zValue() >= 0: + # locked objects don't need cursors + if not self.locked(): self._graphics_view.setCursor(QtCore.Qt.ArrowCursor) def fromSvg(self, svg): diff --git a/gns3/items/text_item.py b/gns3/items/text_item.py index e21e9a69..6df5cd4c 100644 --- a/gns3/items/text_item.py +++ b/gns3/items/text_item.py @@ -111,13 +111,6 @@ class TextItem(QtWidgets.QGraphicsTextItem, DrawingItem): super().paint(painter, option, widget) self.drawLayerInfo(painter) - def setZValue(self, value): - """ - Sets Z value of the item - :param value: z layer - """ - return DrawingItem.setZValue(self, value) - def toSvg(self): """ Return an SVG version of the text diff --git a/gns3/main_window.py b/gns3/main_window.py index 0f148491..402f5b54 100644 --- a/gns3/main_window.py +++ b/gns3/main_window.py @@ -44,6 +44,7 @@ from .settings import GENERAL_SETTINGS from .items.node_item import NodeItem from .items.link_item import LinkItem from .items.shape_item import ShapeItem +from .items.label_item import LabelItem from .topology import Topology from .http_client import HTTPClient from .progress import Progress @@ -363,17 +364,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): """ for item in self.uiGraphicsView.items(): - if not isinstance(item, LinkItem): - if self.uiLockAllAction.isChecked() and item.zValue() >= 0: - item.setZValue(-(item.zValue() + 1)) - if item.parentItem() is None: - item.updateNode() - item.update() - elif not self.uiLockAllAction.isChecked() and item.zValue() < 0: - item.setZValue(-(item.zValue() + 1)) - if item.parentItem() is None: - item.updateNode() - item.update() + if not isinstance(item, LinkItem) and not isinstance(item, LabelItem): + if self.uiLockAllAction.isChecked() and not item.locked(): + item.setLocked(True) + elif not self.uiLockAllAction.isChecked() and item.locked(): + item.setLocked(False) + if item.parentItem() is None: + item.updateNode() + item.update() def analyticsClient(self): """ diff --git a/gns3/node.py b/gns3/node.py index acce3aff..4d984364 100644 --- a/gns3/node.py +++ b/gns3/node.py @@ -46,7 +46,8 @@ class Node(BaseNode): self._settings = {"name": "", "x": None, "y": None, - "z": 1} + "z": 1, + "locked": False} def settings(self): """ @@ -148,6 +149,13 @@ class Node(BaseNode): return self._settings["z"] + def locked(self): + """ + Is the node locked + """ + + return self._settings["locked"] + def setSymbol(self, symbol): """ Sets the symbol for this node. @@ -373,6 +381,7 @@ class Node(BaseNode): "x", "y", "z", + "locked", "symbol", "label", "port_name_format", @@ -529,7 +538,7 @@ class Node(BaseNode): del result["properties"] # Update common element of all nodes - for key in ["x", "y", "z", "symbol", "label", "console_host", "console", "console_type", "console_auto_start", "custom_adapters"]: + for key in ["x", "y", "z", "locked", "symbol", "label", "console_host", "console", "console_type", "console_auto_start", "custom_adapters"]: if key in result: self._settings[key] = result[key] @@ -578,7 +587,8 @@ class Node(BaseNode): data = {"x": int(node_item.pos().x()), "y": int(node_item.pos().y()), "z": int(node_item.zValue()), - "symbol": node_item.symbol()} + "symbol": node_item.symbol(), + "locked": node_item.locked()} if node_item.label() is not None: data["label"] = node_item.label().dump() diff --git a/gns3/topology.py b/gns3/topology.py index 9951e7e4..209ca71e 100644 --- a/gns3/topology.py +++ b/gns3/topology.py @@ -541,7 +541,7 @@ It is your responsability to check if you have the right to distribute the image node = node_module.instantiateNode(node_class, ComputeManager.instance().getCompute(node_data["compute_id"]), self._project) node.createNodeCallback(node_data) - self._main_window.uiGraphicsView.createNodeItem(node, node_data["symbol"], node_data["x"], node_data["y"], node_data.get("z", 1)) + self._main_window.uiGraphicsView.createNodeItem(node, node_data["symbol"], node_data["x"], node_data["y"]) def createLink(self, link_data): source_port = None @@ -597,7 +597,7 @@ It is your responsability to check if you have the right to distribute the image except IndexError: # If unknow we render it as a raw SVG image type = "image" - self._main_window.uiGraphicsView.createDrawingItem(type, drawing_data["x"], drawing_data["y"], drawing_data["z"], rotation=drawing_data["rotation"], drawing_id=drawing_data["drawing_id"], svg=drawing_data["svg"]) + self._main_window.uiGraphicsView.createDrawingItem(type, drawing_data["x"], drawing_data["y"], drawing_data["z"], locked=drawing_data["locked"], rotation=drawing_data["rotation"], drawing_id=drawing_data["drawing_id"], svg=drawing_data["svg"]) @staticmethod def instance(): diff --git a/tests/items/test_line_item.py b/tests/items/test_line_item.py index ea9d168b..8934f681 100644 --- a/tests/items/test_line_item.py +++ b/tests/items/test_line_item.py @@ -110,6 +110,7 @@ def test_create(project, controller): "x": 0, "y": 0, "z": 0, + "locked": rect.locked(), "svg": rect.toSvg(), "rotation": int(rect.rotation()) } diff --git a/tests/items/test_rectangle_item.py b/tests/items/test_rectangle_item.py index 9856326c..a078eadb 100644 --- a/tests/items/test_rectangle_item.py +++ b/tests/items/test_rectangle_item.py @@ -75,6 +75,7 @@ def test_create(project, controller): "x": 0, "y": 0, "z": 0, + "locked": rect.locked(), "svg": rect.toSvg(), "rotation": int(rect.rotation()) } diff --git a/tests/test_node.py b/tests/test_node.py index 49409911..aecc6101 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -158,6 +158,9 @@ def test_node_setGraphics(vpcs_device): zValue=MagicMock( return_value=2 ), + locked=MagicMock( + return_value=False + ), symbol=MagicMock( return_value="symbol.svg" ) @@ -172,6 +175,7 @@ def test_node_setGraphics(vpcs_device): vpcs_device.setSettingValue('x', 10) vpcs_device.setSettingValue('y', 20) vpcs_device.setSettingValue('z', 2) + vpcs_device.setSettingValue('locked', False) vpcs_device.setSettingValue('symbol', "symbol.svg") vpcs_device.setSettingValue('label', node.label().dump()) diff --git a/tests/test_topology.py b/tests/test_topology.py index 19328b7e..23c31597 100644 --- a/tests/test_topology.py +++ b/tests/test_topology.py @@ -40,13 +40,14 @@ def test_createDrawing_ellipse(): "x": 42, "y": 12, "z": 0, + "locked": False, "rotation": 0, "drawing_id": str(uuid.uuid4()), "svg": "", } topology._main_window = MagicMock() topology.createDrawing(shape_data) - topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("ellipse", 42, 12, 0, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) + topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("ellipse", 42, 12, 0, locked=False, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) def test_createDrawing_rect(): @@ -55,13 +56,14 @@ def test_createDrawing_rect(): "x": 42, "y": 12, "z": 0, + "locked": False, "rotation": 0, "drawing_id": str(uuid.uuid4()), "svg": "", } topology._main_window = MagicMock() topology.createDrawing(shape_data) - topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("rect", 42, 12, 0, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) + topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("rect", 42, 12, 0, locked=False, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) def test_createDrawing_text(): @@ -70,13 +72,14 @@ def test_createDrawing_text(): "x": 42, "y": 12, "z": 0, + "locked": False, "rotation": 0, "drawing_id": str(uuid.uuid4()), "svg": "", } topology._main_window = MagicMock() topology.createDrawing(shape_data) - topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("text", 42, 12, 0, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) + topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("text", 42, 12, 0, locked=False, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) def test_createDrawing_svg(): @@ -88,11 +91,12 @@ def test_createDrawing_svg(): "x": 42, "y": 12, "z": 0, + "locked": False, "rotation": 0, "drawing_id": str(uuid.uuid4()), "svg": "", } topology._main_window = MagicMock() topology.createDrawing(shape_data) - topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("image", 42, 12, 0, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"]) + topology._main_window.uiGraphicsView.createDrawingItem.assert_called_with("image", 42, 12, 0, locked=False, rotation=0, svg=shape_data["svg"], drawing_id=shape_data["drawing_id"])