Skip to content

Commit

Permalink
Extract edge dragging from graphics view
Browse files Browse the repository at this point in the history
  • Loading branch information
don4get committed Jun 15, 2020
1 parent c0497ed commit 802ac8b
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 179 deletions.
115 changes: 115 additions & 0 deletions nodedge/edge_dragging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# -*- coding: utf-8 -*-
"""
Edge dragging module containing :class:`~nodedge.edge_dragging.EdgeDragging` class.
"""

import logging
from enum import IntEnum
from typing import Optional

from nodedge.edge import Edge, EdgeType
from nodedge.graphics_socket import GraphicsSocket
from nodedge.socket import Socket
from nodedge.utils import dumpException


class EdgeDraggingMode(IntEnum):
"""
:class:`~nodedge.graphics_view.DragMode` class.
"""

NOOP = 1 #: Mode representing ready state
EDGE_DRAG = 2 #: Mode representing when we drag edge state
EDGE_CUT = 3 #: Mode representing when we draw a cutting edge


class EdgeDragging:
""":class:`~nodedge.edge_dragging.EdgeDragging` class ."""

def __init__(self, graphicsView: "GraphicsView"): # type: ignore
self.graphicsView = graphicsView
self.dragEdge: Optional[Edge] = None
self.dragStartSocket: Optional[Socket] = None
self.mode: EdgeDraggingMode = EdgeDraggingMode.NOOP

self.__logger = logging.getLogger(__name__)
self.__logger.setLevel(logging.INFO)

def startEdgeDragging(self, graphicsSocket: GraphicsSocket):
"""
Handle the start of dragging an :class:`~nodedge.edge.Edge` operation.
:param graphicsSocket: The socket being connected to another one.
:type graphicsSocket: :class:`~nodedge.graphics_socket.GraphicsSocket`
"""
try:
self.__logger.debug("Assign socket.")
self.dragStartSocket = graphicsSocket.socket
self.dragEdge = Edge(
self.graphicsView.graphicsScene.scene,
graphicsSocket.socket,
edgeType=EdgeType.BEZIER,
)
except Exception as e:
dumpException(e)

def endEdgeDragging(self, graphicsSocket: GraphicsSocket):
"""
Handle the end of dragging an :class:`~nodedge.edge.Edge` operation.
:param graphicsSocket: socket being connected
:type graphicsSocket: :class:`~nodedge.graphics_socket.GraphicsSocket`
:return: True is the operation is a success, false otherwise.
:rtype: ``bool``
"""
self.mode = EdgeDraggingMode.NOOP
self.__logger.debug(f"Drag mode: {self.mode}")

# noinspection PyBroadException
try:
if self.dragEdge is not None:
# Don't notify sockets about removing drag_edge
self.dragEdge.remove(silent=True)
except Exception:
self.__logger.warning("Impossible to remove dragEdge")
self.dragEdge = None

try:
if self.dragStartSocket is not None:
if not self.dragStartSocket.allowMultiEdges:
self.dragStartSocket.removeAllEdges()

if not graphicsSocket.socket.allowMultiEdges:
graphicsSocket.socket.removeAllEdges()

newEdge = Edge(
self.graphicsView.graphicsScene.scene,
self.dragStartSocket,
graphicsSocket.socket,
edgeType=EdgeType.CIRCUIT,
)
graphicsSocket.socket.addEdge(newEdge)
self.__logger.debug(
f"New edge created: {newEdge} connecting"
f"\n|||| {newEdge.sourceSocket} to"
f"\n |||| {newEdge.targetSocket}"
)

socket: Optional[Socket]
for socket in [self.dragStartSocket, graphicsSocket.socket]:
if socket is not None:
socket.node.onEdgeConnectionChanged(newEdge)

if socket.isInput:
socket.node.onInputChanged(socket)

self.graphicsView.graphicsScene.scene.history.store(
"Create a new edge by dragging"
)
self.__logger.debug("Socket assigned.")
return True
except Exception as e:
dumpException(e)

self.__logger.debug("Drag edge successful.")
return False
51 changes: 49 additions & 2 deletions nodedge/graphics_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import logging
import math
from typing import Optional
from typing import Optional, Union

from PyQt5.QtCore import QPointF, Qt
from PyQt5.QtGui import QColor, QPainterPath, QPen
Expand All @@ -18,6 +18,9 @@
QGraphicsSceneMouseEvent,
)

from nodedge.graphics_socket import getSocketColor
from nodedge.utils import dumpException


class GraphicsEdge(QGraphicsPathItem):
""":class:`~nodedge.graphics_edge.GraphicsEdge` class
Expand Down Expand Up @@ -105,7 +108,8 @@ def initStyle(self):
"""
Initialize ``QObject`` like ``QColor``, ``QPen`` and ``QBrush``
"""
self._color: QColor = QColor("#001000")
self._defaultColor: QColor = QColor("#001000")
self._color: QColor = self._defaultColor
self._colorSelected: QColor = QColor("#00ff00")
self._colorHovered: QColor = QColor("#FF37A6FF")

Expand Down Expand Up @@ -234,6 +238,49 @@ def intersectsWith(self, p1: QPointF, p2: QPointF) -> bool:
path = self.calcPath()
return cutpath.intersects(path)

# noinspection PyAttributeOutsideInit
def changeColor(self, color: Union[str, QColor]):
"""Change color of the edge from string hex value '#00ff00'"""

newColor = color if isinstance(color, QColor) else QColor(color)

self.__logger.debug(
"Change color to:",
newColor.red(),
newColor.green(),
newColor.blue(),
"on edge:",
self.edge,
)

self._color = newColor
self._pen = QPen(self._color)
self._pen.setWidthF(3.0)

def setColorFromSockets(self) -> bool:
"""
Change color according to connected sockets.
Returns ``True`` if color can be determined.
"""
try:
if self.edge is None:
return False

if self.edge.sourceSocket is None:
return False

if self.edge.targetSocket is None:
return False

sourceSocketType = self.edge.sourceSocket.socketType
targetSocketType = self.edge.targetSocket.socketType
if sourceSocketType != targetSocketType:
return False
self.changeColor(getSocketColor(sourceSocketType))
except Exception as e:
dumpException(e)
return True


class GraphicsEdgeDirect(GraphicsEdge):
"""
Expand Down
29 changes: 17 additions & 12 deletions nodedge/graphics_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def __init__(self, socket: "Socket") -> None: # type: ignore

self.initUI()

self.isHighlighted = False

def initUI(self) -> None:
"""
Setup this ``QGraphicsItem``.
Expand All @@ -51,12 +53,15 @@ def initStyle(self) -> None:
"""
Initialize ``QObjects`` like ``QColor``, ``QPen`` and ``QBrush``.
"""
self._colorBackground: QColor = GraphicsSocket.getSocketColor(self.socketType)
self._colorBackground: QColor = getSocketColor(self.socketType)
self._colorOutline: QColor = QColor("#FF000000")
self._colorHighlight: QColor = QColor("#FF37A6FF")

self._pen: QPen = QPen(self._colorOutline)
self._pen.setWidthF(self.outlineWidth)
self._brush: QBrush = QBrush(self._colorBackground)
self._penHighlight: QPen = QPen(self._colorHighlight)
self._penHighlight.setWidthF(2.0)

# noinspection PyAttributeOutsideInit
def initSizes(self) -> None:
Expand All @@ -70,19 +75,10 @@ def initSizes(self) -> None:
def socketType(self):
return self.socket.socketType

@staticmethod
def getSocketColor(key):
"""Returns the ``QColor`` for this ``key``."""
if type(key) == int:
return SOCKET_COLORS[key]
elif type(key) == str:
return QColor(key)
return Qt.transparent

# noinspection PyAttributeOutsideInit
def updateSocketType(self):
"""Change the Socket Type."""
self._colorBackground = self.getSocketColor(self.socketType)
self._colorBackground = getSocketColor(self.socketType)
self._brush = QBrush(self._colorBackground)
self.update()

Expand All @@ -91,7 +87,7 @@ def paint(self, painter, QStyleOptionGraphicsItem, widget=None):
Paint a circle.
"""
painter.setBrush(self._brush)
painter.setPen(self._pen)
painter.setPen(self._pen if not self.isHighlighted else self._penHighlight)

painter.drawEllipse(
-self.radius, -self.radius, 2 * self.radius, 2 * self.radius
Expand All @@ -107,3 +103,12 @@ def boundingRect(self):
2 * (self.radius + self.outlineWidth),
2 * (self.radius + self.outlineWidth),
)


def getSocketColor(key):
"""Returns the ``QColor`` for this ``key``."""
if type(key) == int:
return SOCKET_COLORS[key]
elif type(key) == str:
return QColor(key)
return Qt.transparent

0 comments on commit 802ac8b

Please sign in to comment.