source: orange/Orange/OrangeCanvas/scheme/link.py @ 11367:9630e1bb6112

Revision 11367:9630e1bb6112, 5.3 KB checked in by Ales Erjavec <ales.erjavec@…>, 14 months ago (diff)

Added rst documentation for scheme package.

Fixing docstrings in the process.

RevLine 
[11101]1"""
2===========
3Scheme Link
4===========
5
6"""
7
8from PyQt4.QtCore import QObject
9from PyQt4.QtCore import pyqtSignal as Signal
10from PyQt4.QtCore import pyqtProperty as Property
11
12from .utils import name_lookup
13from .errors import IncompatibleChannelTypeError
14
15
16def compatible_channels(source_channel, sink_channel):
[11367]17    """
18    Do the channels in link have compatible types, i.e. can they be
[11101]19    connected based on their type.
20
21    """
22    source_type = name_lookup(source_channel.type)
23    sink_type = name_lookup(sink_channel.type)
24    ret = issubclass(source_type, sink_type)
25    if source_channel.dynamic:
26        ret = ret or issubclass(sink_type, source_type)
27    return ret
28
29
30def can_connect(source_node, sink_node):
[11367]31    """
32    Return True if any output from `source_node` can be connected to
[11101]33    any input of `sink_node`.
34
35    """
36    return bool(possible_links(source_node, sink_node))
37
38
39def possible_links(source_node, sink_node):
[11367]40    """
41    Return a list of (OutputSignal, InputSignal) tuples, that
[11101]42    can connect the two nodes.
43
44    """
45    possible = []
46    for source in source_node.output_channels():
47        for sink in sink_node.input_channels():
48            if compatible_channels(source, sink):
49                possible.append((source, sink))
50    return possible
51
52
53class SchemeLink(QObject):
[11367]54    """
55    A instantiation of a link between two :class:`.SchemeNode` instances
56    in a :class:`.Scheme`.
[11101]57
58    Parameters
59    ----------
[11367]60    source_node : :class:`.SchemeNode`
[11101]61        Source node.
[11367]62    source_channel : :class:`OutputSignal`
[11101]63        The source widget's signal.
[11367]64    sink_node : :class:`.SchemeNode`
[11101]65        The sink node.
[11367]66    sink_channel : :class:`InputSignal`
[11101]67        The sink widget's input signal.
68    properties : `dict`
69        Additional link properties.
70
71    """
72
73    enabled_changed = Signal(bool)
74    dynamic_enabled_changed = Signal(bool)
75
76    def __init__(self, source_node, source_channel,
77                 sink_node, sink_channel, enabled=True, properties=None,
78                 parent=None):
79        QObject.__init__(self, parent)
80        self.source_node = source_node
81
82        if isinstance(source_channel, basestring):
83            source_channel = source_node.output_channel(source_channel)
84        elif source_channel not in source_node.output_channels():
85            raise ValueError("%r not in in nodes output channels." \
86                             % source_channel)
87
88        self.source_channel = source_channel
89
90        self.sink_node = sink_node
91
92        if isinstance(sink_channel, basestring):
93            sink_channel = sink_node.input_channel(sink_channel)
94        elif sink_channel not in sink_node.input_channels():
95            raise ValueError("%r not in in nodes input channels." \
96                             % source_channel)
97
98        self.sink_channel = sink_channel
99
100        if not compatible_channels(source_channel, sink_channel):
101            raise IncompatibleChannelTypeError(
102                    "Cannot connect %r to %r" \
[11302]103                    % (source_channel.type, sink_channel.type)
[11101]104                )
105
106        self.__enabled = enabled
107        self.__dynamic_enabled = False
108        self.__tool_tip = ""
109        self.properties = properties or {}
110
111    def source_type(self):
[11367]112        """
113        Return the type of the source channel.
[11101]114        """
115        return name_lookup(self.source_channel.type)
116
117    def sink_type(self):
[11367]118        """
119        Return the type of the sink channel.
[11101]120        """
121        return name_lookup(self.sink_channel.type)
122
123    def is_dynamic(self):
[11367]124        """
125        Is this link dynamic.
[11101]126        """
127        return self.source_channel.dynamic and \
[11182]128            issubclass(self.sink_type(), self.source_type()) and \
129            not (self.sink_type() is self.source_type())
[11101]130
[11367]131    def set_enabled(self, enabled):
[11101]132        """
[11367]133        Enable/disable the link.
[11101]134        """
135        if self.__enabled != enabled:
136            self.__enabled = enabled
137            self.enabled_changed.emit(enabled)
138
[11367]139    def enabled(self):
140        """
141        Is this link enabled.
142        """
143        return self.__enabled
144
[11101]145    enabled = Property(bool, fget=enabled, fset=set_enabled)
146
147    def set_dynamic_enabled(self, enabled):
[11367]148        """
149        Enable/disable the dynamic link. Has no effect if the link
150        is not dynamic.
[11101]151
152        """
153        if self.is_dynamic() and self.__dynamic_enabled != enabled:
154            self.__dynamic_enabled = enabled
155            self.dynamic_enabled_changed.emit(enabled)
156
157    def dynamic_enabled(self):
[11367]158        """
159        Is this a dynamic link and is `dynamic_enabled` set to `True`
[11101]160        """
161        return self.is_dynamic() and self.__dynamic_enabled
162
163    dynamic_enabled = Property(bool, fget=dynamic_enabled,
[11367]164                               fset=set_dynamic_enabled)
[11101]165
166    def set_tool_tip(self, tool_tip):
[11367]167        """
168        Set the link tool tip.
[11101]169        """
170        if self.__tool_tip != tool_tip:
171            self.__tool_tip = tool_tip
172
173    def tool_tip(self):
[11367]174        """
175        Link tool tip.
[11101]176        """
177        return self.__tool_tip
178
179    tool_tip = Property(str, fget=tool_tip,
[11367]180                        fset=set_tool_tip)
[11267]181
182    def __str__(self):
183        return u"{0}(({1}, {2}) -> ({3}, {4}))".format(
184                    type(self).__name__,
185                    self.source_node.title,
186                    self.source_channel.name,
187                    self.sink_node.title,
188                    self.sink_channel.name
189                )
Note: See TracBrowser for help on using the repository browser.