1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
from qtpy.QtCore import QObject, Signal
from .base import ConnectionBase
from .enums import ConnectionPolicy, PortType
def opposite_port(port: PortType):
return {PortType.input: PortType.output,
PortType.output: PortType.input}.get(port, PortType.none)
class Port(QObject):
connection_created = Signal(ConnectionBase)
connection_deleted = Signal(ConnectionBase)
data_updated = Signal(QObject)
data_invalidated = Signal(QObject)
def __init__(self, node, *, port_type: PortType, index: int):
super().__init__(parent=node)
self.node = node
self.port_type = port_type
self.index = index
self._connections = []
self.opposite_port = {PortType.input: PortType.output,
PortType.output: PortType.input}[self.port_type]
@property
def connections(self):
return list(self._connections)
@property
def model(self):
'The data model associated with the Port'
return self.node.model
@property
def data(self):
'The NodeData associated with the Port, if an output port'
if self.port_type == PortType.input:
# return self.model.in_data(self.index)
# TODO
return
else:
return self.model.out_data(self.index)
@property
def can_connect(self):
'Can this port be connected to?'
return (not self._connections or
self.connection_policy == ConnectionPolicy.many)
@property
def caption(self):
'Data model-specified caption for the port'
return self.model.port_caption[self.port_type][self.index]
@property
def caption_visible(self):
'Show the data model-specified caption?'
return self.model.port_caption_visible[self.port_type][self.index]
@property
def data_type(self):
'The NodeData type associated with the Port'
return self.model.data_type[self.port_type][self.index]
@property
def display_text(self):
'The text to show on the label caption'
return (self.caption
if self.caption_visible
else self.data_type.name)
@property
def connection_policy(self):
'The connection policy (one/many) for the port'
if self.port_type == PortType.input:
return ConnectionPolicy.one
else:
return self.model.port_out_connection_policy(self.index)
def add_connection(self, connection: ConnectionBase):
'Add a Connection to the Port'
if connection in self._connections:
raise ValueError('Connection already in list')
self._connections.append(connection)
self.connection_created.emit(connection)
def remove_connection(self, connection: ConnectionBase):
'Remove a Connection from the Port'
try:
self._connections.remove(connection)
except ValueError:
# TODO: should not be reaching this
...
else:
self.connection_deleted.emit(connection)
@property
def scene_position(self):
'''
The position in the scene of the Port
Returns
-------
value : QPointF
See also
--------
get_mapped_scene_position
'''
return self.node.geometry.port_scene_position(self.port_type,
self.index)
def get_mapped_scene_position(self, transform):
"""
Node port scene position after a transform
Parameters
----------
port_type : PortType
port_index : int
Returns
-------
value : QPointF
"""
ngo = self.node.graphics_object
return ngo.sceneTransform().map(self.scene_position)
def __repr__(self):
return (f'<{self.__class__.__name__} port_type={self.port_type} '
f'index={self.index} connections={len(self._connections)}>')
|