source: orange/Orange/OrangeCanvas/scheme/widgetsscheme.py @ 11101:e5aa7c1c5b23

Revision 11101:e5aa7c1c5b23, 4.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 19 months ago (diff)

Added scheme package, containing the scheme graph workflow data structure/model.

Line 
1
2import logging
3
4from .. import orngSignalManager
5from .scheme import Scheme
6from .utils import name_lookup
7from ..config import rc
8
9log = logging.getLogger(__name__)
10
11
12class WidgetsScheme(Scheme):
13    """A Scheme containing Orange Widgets managed with a SignalManager
14    instance.
15
16    """
17    def __init__(self, parent=None, title=None, description=None):
18        Scheme.__init__(self, parent, title, description)
19
20        self.widgets = []
21        self.widget_for_node = {}
22        self.signal_manager = orngSignalManager.SignalManager()
23
24        self.__loaded_from = None
25
26    def add_node(self, node):
27        widget = self.create_widget_instance(node)
28        Scheme.add_node(self, node)
29        self.widgets.append(widget)
30
31        self.widget_for_node[node] = widget
32
33        self.signal_manager.addWidget(widget)
34
35    def remove_node(self, node):
36        Scheme.remove_node(self, node)
37        widget = self.widget_for_node[node]
38        self.signal_manager.removeWidget(widget)
39        del self.widget_for_node[node]
40
41        # Save settings to user global settings.
42        if not self.__loaded_from:
43            widget.saveSettings()
44
45        # Notify the widget it will be deleted.
46        widget.onDeleteWidget()
47        # And schedule it for deletion.
48        widget.deleteLater()
49
50    def add_link(self, link):
51        Scheme.add_link(self, link)
52        source_widget = self.widget_for_node[link.source_node]
53        sink_widget = self.widget_for_node[link.sink_node]
54        source_channel = link.source_channel.name
55        sink_channel = link.sink_channel.name
56        self.signal_manager.addLink(source_widget, sink_widget, source_channel,
57                                    sink_channel, enabled=link.enabled)
58        from functools import partial
59        self.signal_manager.processNewSignals()
60        link.enabled_changed.connect(
61            partial(self.signal_manager.setLinkEnabled,
62                    source_widget, sink_widget)
63        )
64
65    def remove_link(self, link):
66        Scheme.remove_link(self, link)
67
68        source_widget = self.widget_for_node[link.source_node]
69        sink_widget = self.widget_for_node[link.sink_node]
70        source_channel = link.source_channel.name
71        sink_channel = link.sink_channel.name
72
73        self.signal_manager.removeLink(source_widget, sink_widget,
74                                       source_channel, sink_channel)
75
76    def create_widget_instance(self, node):
77        desc = node.description
78        klass = name_lookup(desc.qualified_name)
79
80        log.info("Creating %r instance.", klass)
81        widget = klass.__new__(
82            klass,
83            _owInfo=rc.get("canvas.show-state-info", True),
84            _owWarning=rc.get("canvas.show-state-warning", True),
85            _owError=rc.get("canvas.show-state-error", True),
86            _owShowStatus=rc.get("OWWidget.show-status", True),
87            _useContexts=rc.get("OWWidget.use-contexts", True),
88            _category=desc.category,
89            _settingsFromSchema=node.properties
90        )
91        import pprint
92        log.debug("New %r instance properties:\n%s", node.title,
93                  pprint.pformat(node.properties))
94
95        widget.__init__(None, self.signal_manager)
96        widget.setCaption(node.title)
97        widget.widgetInfo = desc
98
99        widget.setVisible(node.properties.get("visible", False))
100
101        node.title_changed.connect(widget.setCaption)
102        # Bind widgets progress/processing state back to the node's properties
103        widget.progressBarValueChanged.connect(node.set_progress)
104        widget.processingStateChanged.connect(node.set_processing_state)
105
106        return widget
107
108    def close_all_open_widgets(self):
109        for widget in self.widget_for_node.values():
110            widget.close()
111
112    def sync_node_properties(self):
113        """Sync the widget settings/properties with the SchemeNode.properties.
114        Return True if there were any changes in the properties (i.e. if the
115        new node.properties differ from the old value) and False otherwise.
116
117        .. note:: this should hopefully be removed in the feature, when the
118            widget can notify a changed setting property.
119
120        """
121        changed = False
122        for node in self.nodes:
123            widget = self.widget_for_node[node]
124            settings = widget.getSettings()
125            if settings != node.properties:
126                node.properties = settings
127                changed = True
128        log.debug("Scheme node properties sync (changed: %s)", changed)
129        return changed
130
131    def save_to(self, stream):
132        self.sync_node_properties()
133        Scheme.save_to(self, stream)
134
135    def load_from(self, stream):
136        """Load the scheme from xml formated stream.
137        """
138        if isinstance(stream, basestring):
139            self.__loaded_from = stream
140            stream = open(stream, "rb")
141        elif isinstance(stream, file):
142            self.__loaded_from = stream.name
143
144        Scheme.load_from(self, stream)
Note: See TracBrowser for help on using the repository browser.