2014-01-31 16:22:31 -07:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
#
|
|
|
|
|
# Copyright (C) 2014 GNS3 Technologies Inc.
|
|
|
|
|
#
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
Graphical representation of a node on the QGraphicsScene.
|
|
|
|
|
"""
|
|
|
|
|
|
2015-06-22 15:56:29 -06:00
|
|
|
from ..qt import QtCore, QtGui, QtWidgets
|
2014-06-20 09:52:21 -06:00
|
|
|
from .note_item import NoteItem
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2015-06-07 11:01:38 -06:00
|
|
|
import logging
|
|
|
|
|
log = logging.getLogger(__name__)
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2015-06-22 15:56:29 -06:00
|
|
|
|
|
|
|
|
class NodeItem():
|
2015-01-28 11:13:10 +01:00
|
|
|
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
Node for the scene.
|
|
|
|
|
|
2014-09-23 17:43:59 -06:00
|
|
|
:param node: Node instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
2014-08-30 18:41:06 -06:00
|
|
|
show_layer = False
|
|
|
|
|
|
2015-06-22 15:56:29 -06:00
|
|
|
def __init__(self, node):
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
# attached node
|
2014-01-31 16:22:31 -07:00
|
|
|
self._node = node
|
|
|
|
|
|
2014-06-20 09:52:21 -06:00
|
|
|
# node label
|
|
|
|
|
self._node_label = None
|
|
|
|
|
|
2014-08-30 18:41:06 -06:00
|
|
|
# link items connected to this node item.
|
|
|
|
|
self._links = []
|
|
|
|
|
|
2015-06-22 15:56:29 -06:00
|
|
|
effect = QtWidgets.QGraphicsColorizeEffect()
|
|
|
|
|
effect.setColor(QtGui.QColor("black"))
|
|
|
|
|
effect.setStrength(0.8)
|
|
|
|
|
#effect = QtWidgets.QGraphicsDropShadowEffect()
|
2015-11-09 12:39:14 +01:00
|
|
|
# effect.setColor(QtGui.QColor("darkGray"))
|
|
|
|
|
# effect.setBlurRadius(0)
|
2015-06-22 15:56:29 -06:00
|
|
|
#effect.setOffset(3, 3)
|
|
|
|
|
self.setGraphicsEffect(effect)
|
|
|
|
|
self.graphicsEffect().setEnabled(False)
|
|
|
|
|
|
2014-01-31 16:22:31 -07:00
|
|
|
# set graphical settings for this node
|
2015-06-22 15:56:29 -06:00
|
|
|
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
|
|
|
|
|
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable)
|
|
|
|
|
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable)
|
|
|
|
|
self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges)
|
2015-04-17 12:14:21 +02:00
|
|
|
self.setAcceptHoverEvents(True)
|
2014-01-31 16:22:31 -07:00
|
|
|
self.setZValue(1)
|
|
|
|
|
|
|
|
|
|
# connect signals to know about some events
|
|
|
|
|
# e.g. when the node has been started, stopped or suspended etc.
|
2014-02-27 21:45:56 -07:00
|
|
|
node.created_signal.connect(self.createdSlot)
|
2014-01-31 16:22:31 -07:00
|
|
|
node.started_signal.connect(self.startedSlot)
|
|
|
|
|
node.stopped_signal.connect(self.stoppedSlot)
|
|
|
|
|
node.suspended_signal.connect(self.suspendedSlot)
|
2014-02-27 21:45:56 -07:00
|
|
|
node.updated_signal.connect(self.updatedSlot)
|
2014-03-20 20:03:42 -06:00
|
|
|
node.deleted_signal.connect(self.deletedSlot)
|
2014-01-31 16:22:31 -07:00
|
|
|
node.delete_links_signal.connect(self.deleteLinksSlot)
|
2014-04-29 18:21:33 -06:00
|
|
|
node.error_signal.connect(self.errorSlot)
|
2014-04-29 12:24:52 -06:00
|
|
|
node.server_error_signal.connect(self.serverErrorSlot)
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
# used when a port has been selected from the contextual menu
|
|
|
|
|
self._selected_port = None
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
# says if the attached node has been initialized
|
|
|
|
|
# by the server.
|
|
|
|
|
self._initialized = False
|
|
|
|
|
|
2014-03-29 21:39:15 -06:00
|
|
|
# contains the last error message received
|
|
|
|
|
# from the server.
|
|
|
|
|
self._last_error = None
|
|
|
|
|
|
2015-03-06 17:36:19 -07:00
|
|
|
from ..main_window import MainWindow
|
|
|
|
|
self._main_window = MainWindow.instance()
|
|
|
|
|
self._settings = self._main_window.uiGraphicsView.settings()
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
def setUnsavedState(self):
|
|
|
|
|
"""
|
|
|
|
|
Indicates the project is in a unsaved state.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from ..main_window import MainWindow
|
|
|
|
|
main_window = MainWindow.instance()
|
|
|
|
|
main_window.setUnsavedState()
|
|
|
|
|
|
2014-01-31 16:22:31 -07:00
|
|
|
def node(self):
|
|
|
|
|
"""
|
|
|
|
|
Returns the node attached to this node item.
|
|
|
|
|
|
|
|
|
|
:returns: Node instance
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return self._node
|
|
|
|
|
|
|
|
|
|
def addLink(self, link):
|
|
|
|
|
"""
|
|
|
|
|
Adds a link items to this node item.
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:param link: LinkItem instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self._links.append(link)
|
2014-03-20 20:03:42 -06:00
|
|
|
self._node.updated_signal.emit()
|
2014-02-27 21:45:56 -07:00
|
|
|
self.setUnsavedState()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def removeLink(self, link):
|
|
|
|
|
"""
|
|
|
|
|
Removes a link items from this node item.
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:param link: LinkItem instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
2014-04-25 18:27:32 -06:00
|
|
|
if link in self._links:
|
|
|
|
|
self._links.remove(link)
|
2014-02-27 21:45:56 -07:00
|
|
|
self.setUnsavedState()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def links(self):
|
|
|
|
|
"""
|
|
|
|
|
Returns all the link items attached to this node item.
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:returns: list of LinkItem instances
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return self._links
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
def createdSlot(self, node_id):
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
2014-02-27 21:45:56 -07:00
|
|
|
when a the node has been created/initialized.
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:param node_id: node identifier (integer)
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
self._initialized = True
|
|
|
|
|
self.update()
|
2014-06-20 09:52:21 -06:00
|
|
|
self._showLabel()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def startedSlot(self):
|
|
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when a the node has started.
|
|
|
|
|
"""
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
for link in self._links:
|
|
|
|
|
link.update()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def stoppedSlot(self):
|
|
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when a the node has stopped.
|
|
|
|
|
"""
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
for link in self._links:
|
|
|
|
|
link.update()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def suspendedSlot(self):
|
|
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when a the node has suspended.
|
|
|
|
|
"""
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
for link in self._links:
|
|
|
|
|
link.update()
|
|
|
|
|
|
|
|
|
|
def updatedSlot(self):
|
2014-06-07 09:57:12 -06:00
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when a the node has been updated.
|
|
|
|
|
"""
|
2014-02-27 21:45:56 -07:00
|
|
|
|
2016-02-10 11:33:23 +01:00
|
|
|
if self is None:
|
|
|
|
|
return
|
2014-11-09 16:09:42 -07:00
|
|
|
if self._node_label:
|
2015-01-11 18:25:36 -07:00
|
|
|
if self._node_label.toPlainText() != self._node.name():
|
|
|
|
|
self._node_label.setPlainText(self._node.name())
|
|
|
|
|
self._centerLabel()
|
2014-02-27 21:45:56 -07:00
|
|
|
self.setUnsavedState()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2014-06-07 09:57:12 -06:00
|
|
|
# update the link tooltips in case the
|
|
|
|
|
# node name has changed
|
|
|
|
|
for link in self._links:
|
|
|
|
|
link.setCustomToolTip()
|
|
|
|
|
|
2014-01-31 16:22:31 -07:00
|
|
|
def deleteLinksSlot(self):
|
|
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when a all the links must be deleted.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
for link in self._links.copy():
|
|
|
|
|
link.delete()
|
|
|
|
|
|
2014-03-20 20:03:42 -06:00
|
|
|
def deletedSlot(self):
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when the node has been deleted.
|
|
|
|
|
"""
|
|
|
|
|
|
2015-10-04 14:56:34 -06:00
|
|
|
if self is None:
|
|
|
|
|
return
|
2014-05-27 11:20:16 -06:00
|
|
|
self._node.removeAllocatedName()
|
2014-04-25 18:27:32 -06:00
|
|
|
if self in self.scene().items():
|
|
|
|
|
self.scene().removeItem(self)
|
2014-02-27 21:45:56 -07:00
|
|
|
self.setUnsavedState()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2015-01-30 19:37:17 -07:00
|
|
|
def serverErrorSlot(self, node_id, message):
|
2014-03-29 21:39:15 -06:00
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when the node has received an error from the server.
|
|
|
|
|
|
2014-04-21 12:52:57 -06:00
|
|
|
:param node_id: node identifier
|
2014-03-29 21:39:15 -06:00
|
|
|
:param message: error message
|
|
|
|
|
"""
|
|
|
|
|
|
2015-12-02 16:13:59 +01:00
|
|
|
if self:
|
|
|
|
|
self._last_error = "{message}".format(message=message)
|
2014-03-29 21:39:15 -06:00
|
|
|
|
2014-04-29 18:21:33 -06:00
|
|
|
def errorSlot(self, node_id, message):
|
|
|
|
|
"""
|
|
|
|
|
Slot to receive events from the attached Node instance
|
|
|
|
|
when the node wants to report an error.
|
|
|
|
|
|
|
|
|
|
:param node_id: node identifier
|
|
|
|
|
:param message: error message
|
|
|
|
|
"""
|
|
|
|
|
|
2015-12-02 16:13:59 +01:00
|
|
|
if self:
|
|
|
|
|
self._last_error = "{message}".format(message=message)
|
2014-04-29 18:21:33 -06:00
|
|
|
|
2014-01-31 16:22:31 -07:00
|
|
|
def setCustomToolTip(self):
|
|
|
|
|
"""
|
|
|
|
|
Sets a new ToolTip.
|
|
|
|
|
"""
|
|
|
|
|
|
2014-03-29 21:39:15 -06:00
|
|
|
if not self._initialized:
|
|
|
|
|
if not self._last_error:
|
|
|
|
|
error = "unknown error"
|
|
|
|
|
else:
|
|
|
|
|
error = self._last_error
|
|
|
|
|
self.setToolTip("This node isn't initialized\n{}".format(error))
|
|
|
|
|
else:
|
|
|
|
|
self.setToolTip(self._node.info())
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2014-06-20 09:52:21 -06:00
|
|
|
def label(self):
|
|
|
|
|
"""
|
|
|
|
|
Returns the node label.
|
|
|
|
|
|
|
|
|
|
:return: NoteItem instance.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
return self._node_label
|
|
|
|
|
|
|
|
|
|
def setLabel(self, label):
|
|
|
|
|
"""
|
|
|
|
|
Sets the node label.
|
|
|
|
|
|
|
|
|
|
:param label: NoteItem instance.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self._node_label = label
|
|
|
|
|
|
2015-01-11 18:25:36 -07:00
|
|
|
def _centerLabel(self):
|
|
|
|
|
"""
|
|
|
|
|
Centers the node label.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
text_rect = self._node_label.boundingRect()
|
|
|
|
|
text_middle = text_rect.topRight() / 2
|
|
|
|
|
node_rect = self.boundingRect()
|
|
|
|
|
node_middle = node_rect.topRight() / 2
|
|
|
|
|
label_x_pos = node_middle.x() - text_middle.x()
|
|
|
|
|
label_y_pos = -25
|
|
|
|
|
self._node_label.setPos(label_x_pos, label_y_pos)
|
|
|
|
|
|
2014-06-20 09:52:21 -06:00
|
|
|
def _showLabel(self):
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
2014-06-20 09:52:21 -06:00
|
|
|
Shows the node label on the scene.
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
2014-06-20 09:52:21 -06:00
|
|
|
if not self._node_label:
|
|
|
|
|
self._node_label = NoteItem(self)
|
|
|
|
|
self._node_label.setEditable(False)
|
|
|
|
|
self._node_label.setPlainText(self._node.name())
|
2015-01-11 18:25:36 -07:00
|
|
|
self._centerLabel()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def connectToPort(self, unavailable_ports=[]):
|
|
|
|
|
"""
|
|
|
|
|
Shows a contextual menu for the user to choose port or auto-select one.
|
|
|
|
|
|
|
|
|
|
:param unavailable_ports: list of port names that the user cannot choose
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:returns: Port instance corresponding to the selected port
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self._selected_port = None
|
2015-04-17 12:14:21 +02:00
|
|
|
menu = QtWidgets.QMenu()
|
2014-01-31 16:22:31 -07:00
|
|
|
ports = self._node.ports()
|
|
|
|
|
if not ports:
|
2015-04-17 12:14:21 +02:00
|
|
|
QtWidgets.QMessageBox.critical(self.scene().parent(), "Link", "No port available, please configure this device")
|
2014-01-31 16:22:31 -07:00
|
|
|
return None
|
|
|
|
|
|
2014-11-27 11:34:01 -07:00
|
|
|
# sort the ports
|
|
|
|
|
ports_dict = {}
|
2014-01-31 16:22:31 -07:00
|
|
|
for port in ports:
|
2015-02-13 19:46:08 +01:00
|
|
|
if port.adapterNumber() is not None:
|
2015-01-16 15:17:03 -07:00
|
|
|
# make the port number unique (special case with WICs).
|
|
|
|
|
port_number = port.portNumber()
|
|
|
|
|
if port_number >= 16:
|
2015-06-17 14:23:55 -06:00
|
|
|
port_number *= 8
|
2015-02-13 19:46:08 +01:00
|
|
|
ports_dict[(port.adapterNumber() * 16) + port_number] = port
|
2014-11-27 11:34:01 -07:00
|
|
|
elif port.portNumber()is not None:
|
|
|
|
|
ports_dict[port.portNumber()] = port
|
2014-11-23 19:26:37 -07:00
|
|
|
else:
|
2014-11-27 11:34:01 -07:00
|
|
|
ports_dict[port.name()] = port
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
ports = sorted(ports_dict.keys(), key=int)
|
|
|
|
|
except ValueError:
|
|
|
|
|
ports = sorted(ports_dict.keys())
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
# show a contextual menu for the user to choose a port
|
|
|
|
|
for port in ports:
|
2014-11-27 11:34:01 -07:00
|
|
|
port_object = ports_dict[port]
|
2015-06-07 11:01:38 -06:00
|
|
|
log.debug("Node '{}' Port {} Type {}".format(self.node(), port_object.name(), type(port_object.name())))
|
2014-01-31 16:22:31 -07:00
|
|
|
if port in unavailable_ports:
|
|
|
|
|
# this port cannot be chosen by the user (grayed out)
|
2014-11-23 19:26:37 -07:00
|
|
|
action = menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port_object.name())
|
2014-01-31 16:22:31 -07:00
|
|
|
action.setDisabled(True)
|
|
|
|
|
elif port_object.isFree():
|
2014-11-23 19:26:37 -07:00
|
|
|
menu.addAction(QtGui.QIcon(':/icons/led_red.svg'), port_object.name())
|
2014-01-31 16:22:31 -07:00
|
|
|
else:
|
2014-11-23 19:26:37 -07:00
|
|
|
menu.addAction(QtGui.QIcon(':/icons/led_green.svg'), port_object.name())
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
menu.triggered.connect(self.selectedPortSlot)
|
|
|
|
|
menu.exec_(QtGui.QCursor.pos())
|
|
|
|
|
return self._selected_port
|
|
|
|
|
|
|
|
|
|
def selectedPortSlot(self, action):
|
|
|
|
|
"""
|
|
|
|
|
Slot to receive events when a port has been selected in the
|
|
|
|
|
contextual menu.
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:param action: QAction instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
ports = self._node.ports()
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
# get the Port instance based on the selected port name.
|
2014-01-31 16:22:31 -07:00
|
|
|
for port in ports:
|
2014-02-27 21:45:56 -07:00
|
|
|
if port.name() == str(action.text()):
|
2014-01-31 16:22:31 -07:00
|
|
|
self._selected_port = port
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
def itemChange(self, change, value):
|
|
|
|
|
"""
|
|
|
|
|
Notifies this node item that some part of the item's state changes.
|
|
|
|
|
|
|
|
|
|
:param change: GraphicsItemChange type
|
|
|
|
|
:param value: value of the change
|
|
|
|
|
"""
|
|
|
|
|
|
2016-06-20 10:27:45 +01:00
|
|
|
# was causing infinite recursion loops when placed within the below if statements
|
|
|
|
|
if change == QtWidgets.QGraphicsItem.ItemPositionHasChanged and self._main_window.uiSnapToGridAction.isChecked():
|
2016-06-20 09:50:24 +01:00
|
|
|
GRID_SIZE = 75
|
|
|
|
|
self.setPos(float(GRID_SIZE * round(self.x() / GRID_SIZE)), float(GRID_SIZE * round(self.y() / GRID_SIZE)))
|
|
|
|
|
|
2014-01-31 16:22:31 -07:00
|
|
|
# dynamically change the renderer when this node item is selected/unselected.
|
2015-06-22 15:56:29 -06:00
|
|
|
if change == QtWidgets.QGraphicsItem.ItemSelectedChange:
|
2014-01-31 16:22:31 -07:00
|
|
|
if value:
|
2015-06-22 15:56:29 -06:00
|
|
|
self.graphicsEffect().setEnabled(True)
|
2014-01-31 16:22:31 -07:00
|
|
|
else:
|
2015-06-22 15:56:29 -06:00
|
|
|
self.graphicsEffect().setEnabled(False)
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
# adjust link item positions when this node is moving or has changed.
|
2015-06-22 15:56:29 -06:00
|
|
|
if change == QtWidgets.QGraphicsItem.ItemPositionChange or change == QtWidgets.QGraphicsItem.ItemPositionHasChanged:
|
2014-02-27 21:45:56 -07:00
|
|
|
self.setUnsavedState()
|
2014-01-31 16:22:31 -07:00
|
|
|
for link in self._links:
|
|
|
|
|
link.adjust()
|
|
|
|
|
|
2015-04-17 12:14:21 +02:00
|
|
|
return QtWidgets.QGraphicsItem.itemChange(self, change, value)
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def paint(self, painter, option, widget=None):
|
|
|
|
|
"""
|
|
|
|
|
Paints the contents of an item in local coordinates.
|
|
|
|
|
|
2014-08-30 18:41:06 -06:00
|
|
|
:param painter: QPainter instance
|
|
|
|
|
:param option: QStyleOptionGraphicsItem instance
|
|
|
|
|
:param widget: QWidget instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# don't show the selection rectangle
|
2015-03-06 17:36:19 -07:00
|
|
|
if not self._settings["draw_rectangle_selected_item"]:
|
2015-04-17 12:14:21 +02:00
|
|
|
option.state = QtWidgets.QStyle.State_None
|
|
|
|
|
super().paint(painter, option, widget)
|
2014-01-31 16:22:31 -07:00
|
|
|
|
2014-08-30 18:41:06 -06:00
|
|
|
if not self._initialized or self.show_layer:
|
2014-02-27 21:45:56 -07:00
|
|
|
brect = self.boundingRect()
|
2014-08-30 18:41:06 -06:00
|
|
|
center = self.mapFromItem(self, brect.width() / 2.0, brect.height() / 2.0)
|
2014-02-27 21:45:56 -07:00
|
|
|
painter.setBrush(QtCore.Qt.red)
|
|
|
|
|
painter.setPen(QtCore.Qt.red)
|
|
|
|
|
painter.drawRect((brect.width() / 2.0) - 10, (brect.height() / 2.0) - 10, 20, 20)
|
2014-08-30 18:41:06 -06:00
|
|
|
painter.setPen(QtCore.Qt.black)
|
|
|
|
|
if self.show_layer:
|
|
|
|
|
text = str(int(self.zValue())) # Z value
|
|
|
|
|
elif self._last_error:
|
|
|
|
|
text = "E" # error
|
|
|
|
|
else:
|
|
|
|
|
text = "S" # initialization
|
|
|
|
|
painter.drawText(QtCore.QPointF(center.x() - 4, center.y() + 4), text)
|
|
|
|
|
|
|
|
|
|
def setZValue(self, value):
|
|
|
|
|
"""
|
|
|
|
|
Sets a new Z value.
|
2014-02-27 21:45:56 -07:00
|
|
|
|
2014-08-30 18:41:06 -06:00
|
|
|
:param value: Z value
|
|
|
|
|
"""
|
|
|
|
|
|
2015-04-17 12:14:21 +02:00
|
|
|
super().setZValue(value)
|
2014-08-30 18:41:06 -06:00
|
|
|
if self.zValue() < 0:
|
|
|
|
|
self.setFlag(self.ItemIsSelectable, False)
|
|
|
|
|
self.setFlag(self.ItemIsMovable, False)
|
|
|
|
|
if self._node_label:
|
|
|
|
|
self._node_label.setFlag(self.ItemIsSelectable, False)
|
|
|
|
|
self._node_label.setFlag(self.ItemIsMovable, False)
|
|
|
|
|
else:
|
|
|
|
|
self.setFlag(self.ItemIsSelectable, True)
|
|
|
|
|
self.setFlag(self.ItemIsMovable, True)
|
|
|
|
|
if self._node_label:
|
|
|
|
|
self._node_label.setFlag(self.ItemIsSelectable, True)
|
|
|
|
|
self._node_label.setFlag(self.ItemIsMovable, True)
|
|
|
|
|
for link in self._links:
|
|
|
|
|
link.adjust()
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def hoverEnterEvent(self, event):
|
|
|
|
|
"""
|
|
|
|
|
Handles all hover enter events for this item.
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:param event: QGraphicsSceneHoverEvent instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
self.setCustomToolTip()
|
|
|
|
|
if not self.isSelected():
|
2015-06-22 15:56:29 -06:00
|
|
|
self.graphicsEffect().setEnabled(True)
|
2014-01-31 16:22:31 -07:00
|
|
|
|
|
|
|
|
def hoverLeaveEvent(self, event):
|
|
|
|
|
"""
|
|
|
|
|
Handles all hover leave events for this item.
|
|
|
|
|
|
2014-02-27 21:45:56 -07:00
|
|
|
:param event: QGraphicsSceneHoverEvent instance
|
2014-01-31 16:22:31 -07:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if not self.isSelected():
|
2015-06-22 15:56:29 -06:00
|
|
|
self.graphicsEffect().setEnabled(False)
|