File: port.py

package info (click to toggle)
python-qtpynodeeditor 0.2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 604 kB
  • sloc: python: 5,038; makefile: 14; sh: 1
file content (134 lines) | stat: -rw-r--r-- 4,031 bytes parent folder | download
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)}>')