Exemple #1
0
    def connect(cls, controller_widget, control_name, control_instance):
        """ Connect an 'Enum' controller trait and an 'EnumControlWidget'
        controller widget control.

        Parameters
        ----------
        cls: EnumControlWidget (mandatory)
            an EnumControlWidget control
        controller_widget: ControllerWidget (mandatory)
            a controller widget that contains the controller we want to update
        control_name: str (mandatory)
            the name of the controller widget control we want to synchronize
            with the controller
        control_instance: QComboBox (mandatory)
            the instance of the controller widget control we want to
            synchronize with the controller
        """
        # Update one element of the controller widget.
        # Hook: function that will be called to update the specific widget
        # when a trait event is detected.
        controller_hook = SomaPartial(cls.update_controller_widget,
                                      weak_proxy(controller_widget),
                                      control_name,
                                      weak_proxy(control_instance))

        # When the 'control_name' controller trait value is modified, update
        # the corresponding control
        controller_widget.controller.on_trait_change(controller_hook,
                                                     name=control_name,
                                                     dispatch='ui')

        # Store the trait - control connection we just build
        control_instance._controller_connections = (controller_hook, )
        logger.debug("Add 'Compound' connection: {0} / {1}".format(
            control_name, control_instance))
Exemple #2
0
 def __setstate__(self, state):
     """ Restore the callbacks that have been removed by __getstate__.
     """
     state['_callbacks'] = dict((i, SomaPartial(self._value_callback, *i))
                                for i in state['_callbacks'])
     if state['pipeline'] is state['process']:
         state['pipeline'] = state['process'] = weak_proxy(
             state['pipeline'])
     else:
         state['pipeline'] = weak_proxy(state['pipeline'])
     super(Node, self).__setstate__(state)
     for callback_key, value_callback in six.iteritems(self._callbacks):
         self.set_callback_on_plug(callback_key[0], value_callback)
Exemple #3
0
    def __init__(self, pipeline, name, process, **kwargs):
        """ Generate a ProcessNode

        Parameters
        ----------
        pipeline: Pipeline (mandatory)
            the pipeline object where the node is added.
        name: str (mandatory)
            the node name.
        process: instance
            a process/interface instance.
        kwargs: dict
            process default values.
        """
        if process is pipeline:
            self.process = weak_proxy(process)
        else:
            self.process = process
        self.kwargs = kwargs
        inputs = []
        outputs = []
        for parameter, trait in six.iteritems(self.process.user_traits()):
            if parameter in ('nodes_activation', 'selection_changed'):
                continue
            if trait.output:
                outputs.append(
                    dict(name=parameter,
                         optional=bool(trait.optional),
                         output=True))
            else:
                inputs.append(
                    dict(name=parameter,
                         optional=bool(trait.optional or parameter in kwargs)))
        super(ProcessNode, self).__init__(pipeline, name, inputs, outputs)
Exemple #4
0
 def __init__(self, process, name=None):
     super(ProcessCompletionEngine, self).__init__(
         process=process, name=name)
     self.process = weak_proxy(process)
     self.name = name
     self.completion_ongoing = False
     self.add_trait('completion_progress', traits.Float(0.))
     self.add_trait('completion_progress_total', traits.Float(1.))
Exemple #5
0
    def connect(self, source_plug_name, dest_node, dest_plug_name):
        """ Connect linked plugs of two nodes

        Parameters
        ----------
        source_plug_name: str (mandatory)
            the source plug name
        dest_node: Node (mandatory)
            the destination node
        dest_plug_name: str (mandatory)
            the destination plug name
        """
        # add a callback to spread the source plug value
        value_callback = SomaPartial(self.__class__._value_callback,
                                     weak_proxy(self), source_plug_name,
                                     weak_proxy(dest_node), dest_plug_name)
        self._callbacks[(source_plug_name, dest_node,
                         dest_plug_name)] = value_callback
        self.set_callback_on_plug(source_plug_name, value_callback)
Exemple #6
0
    def connect(cls, controller_widget, control_name, control_instance):
        """ Connect a 'Str' or 'String' controller trait and a
        'StrControlWidget' controller widget control.

        Parameters
        ----------
        cls: StrControlWidget (mandatory)
            a StrControlWidget control
        controller_widget: ControllerWidget (mandatory)
            a controller widget that contains the controller we want to update
        control_name: str (mandatory)
            the name of the controller widget control we want to synchronize
            with the controller
        control_instance: QLineEdit (mandatory)
            the instance of the controller widget control we want to
            synchronize with the controller
        """
        # Check if the control is connected
        if not control_instance.connected:

            # Update one element of the controller.
            # Hook: function that will be called to update a specific
            # controller trait when a 'userModification' qt signal is emited
            widget_hook = partial(cls.update_controller,
                                  weak_proxy(controller_widget), control_name,
                                  weak_proxy(control_instance), False)

            # When a qt 'userModification' signal is emited, update the
            # 'control_name' controller trait value
            control_instance.userModification.connect(widget_hook)

            widget_hook2 = partial(cls.update_controller,
                                   weak_proxy(controller_widget), control_name,
                                   weak_proxy(control_instance), True)

            control_instance.editingFinished.connect(widget_hook2)

            # Update the control.
            # Hook: function that will be called to update the control value
            # when the 'control_name' controller trait is modified.
            controller_hook = SomaPartial(cls.update_controller_widget,
                                          weak_proxy(controller_widget),
                                          control_name,
                                          weak_proxy(control_instance))

            # When the 'control_name' controller trait value is modified,
            # update the corresponding control
            controller_widget.controller.on_trait_change(controller_hook,
                                                         name=control_name,
                                                         dispatch='ui')

            # Store the trait - control connection we just build
            control_instance._controller_connections = (widget_hook,
                                                        widget_hook2,
                                                        controller_hook)
            logger.debug("Add 'String' connection: {0} / {1}.".format(
                control_name, control_instance))

            # Update the control connection status
            control_instance.connected = True
Exemple #7
0
    def _create_group_widget(self, group):
        group_widget = QtGui.QGroupBox()
        last_row = self._grid_layout.rowCount()
        self._grid_layout.addWidget(group_widget, last_row, 0, 1, 2)
        lay1 = QtGui.QVBoxLayout()
        lay1.setContentsMargins(0, 0, 0, 0)
        lay2 = QtGui.QHBoxLayout()
        lay1.addLayout(lay2)
        lay2.setContentsMargins(10, 0, 0, 0)
        lay2.addWidget(QtGui.QLabel('<html><em>%s</em></html>' % group))
        lay2.addStretch(1)
        icon = QtGui.QIcon()
        icon.addPixmap(
            QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/nav_down")),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        group_widget.fold_button = QtGui.QPushButton(icon, '')
        group_widget.fold_button.setFixedSize(30, 20)
        lay2.addWidget(group_widget.fold_button)
        widget = QtGui.QWidget()
        group_widget.setLayout(lay1)
        lay1.addWidget(widget)
        group_widget.hideable_widget = widget
        layout = QtGui.QGridLayout()
        widget.setLayout(layout)
        layout.setAlignment(QtCore.Qt.AlignTop)
        layout.setSpacing(3)
        layout.setContentsMargins(5, 5, 5, 5)
        group_widget.setAlignment(QtCore.Qt.AlignLeft)

        visible_groups = getattr(self.controller, 'visible_groups', set())
        if group in visible_groups:
            show = True
        else:
            show = False
        group_widget.hideable_widget.setVisible(show)

        if not show:
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap(_fromUtf8(":/soma_widgets_icons/nav_right")),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            group_widget.fold_button.setIcon(icon)

        #group_widget.fold_button.clicked.connect(SomaPartial(
        #self._toggle_group_visibility, group))
        # FIXME: if we use this, self gets deleted somewhere. This is not
        # normal.
        group_widget.fold_button.clicked.connect(
            partial(self.__class__._toggle_group_visibility, weak_proxy(self),
                    group))

        return group_widget
Exemple #8
0
 def _install_subprogress_moniotoring(self, subprocess_compl):
     monitor_subprocess_progress = getattr(
         self, 'monitor_subprocess_progress', True)
     if monitor_subprocess_progress:
         self._old_monitor_sub = getattr(
             subprocess_compl, 'monitor_subprocess_progress', True)
         subprocess_compl.monitor_subprocess_progress = False
         self._current_progress = self.completion_progress
         self._monitoring_callback = SomaPartial(
             self.__class__._substep_completion_progress, weak_proxy(self),
             subprocess_compl)
         subprocess_compl.on_trait_change(
             self._monitoring_callback, 'completion_progress')
Exemple #9
0
    def check(cls, control_instance):
        """ Check if a controller widget control is filled correctly.

        Parameters
        ----------
        cls: EnumControlWidget (mandatory)
            an EnumControlWidget control
        control_instance: QComboBox (mandatory)
            the control widget we want to validate
        """
        # Hook: function that will be called to check for typo
        # when a 'textEdited' qt signal is emited
        widget_callback = partial(cls.is_valid, weak_proxy(control_instance))

        # Execute manually the first time the control check method
        widget_callback()
Exemple #10
0
    def check(cls, control_instance):
        """ Check if a controller widget control is filled correctly.

        Parameters
        ----------
        cls: StrControlWidget (mandatory)
            a StrControlWidget control
        control_instance: QLineEdit (mandatory)
            the control widget we want to validate
        """
        # Hook: function that will be called to check for typo
        # when a 'userModification' qt signal is emited
        widget_callback = partial(cls.is_valid, weak_proxy(control_instance))

        # The first time execute manually the control check method
        widget_callback()

        # When a qt 'userModification' signal is emited, check if the new
        # user value is correct
        control_instance.userModification.connect(widget_callback)
Exemple #11
0
    def __init__(self, pipeline, name, inputs, outputs):
        """ Generate a Node

        Parameters
        ----------
        pipeline: Pipeline (mandatory)
            the pipeline object where the node is added
        name: str (mandatory)
            the node name
        inputs: list of dict (mandatory)
            a list of input parameters containing a dictionary with default
            values (mandatory key: name)
        outputs: dict (mandatory)
            a list of output parameters containing a dictionary with default
            values (mandatory key: name)
        """
        super(Node, self).__init__()
        self.pipeline = weak_proxy(pipeline)
        self.name = name
        self.plugs = SortedDictionary()
        # _callbacks -> (src_plug_name, dest_node, dest_plug_name)
        self._callbacks = {}

        # generate a list with all the inputs and outputs
        # the second parameter (parameter_type) is False for an input,
        # True for an output
        parameters = list(zip(inputs, [
            False,
        ] * len(inputs)))
        parameters.extend(list(zip(outputs, [
            True,
        ] * len(outputs))))
        for parameter, parameter_type in parameters:
            # check if parameter is a dictionary as specified in the
            # docstring
            if isinstance(parameter, dict):
                # check if parameter contains a name item
                # as specified in the docstring
                if "name" not in parameter:
                    raise Exception(
                        "Can't create parameter with unknown"
                        "identifier and parameter {0}".format(parameter))
                parameter = parameter.copy()
                plug_name = parameter.pop("name")
                # force the parameter type
                parameter["output"] = parameter_type
                # generate plug with input parameter and identifier name
                plug = Plug(**parameter)
            else:
                raise Exception("Can't create Node. Expect a dict structure "
                                "to initialize the Node, "
                                "got {0}: {1}".format(type(parameter),
                                                      parameter))
            # update plugs list
            self.plugs[plug_name] = plug
            # add an event on plug to validate the pipeline
            plug.on_trait_change(pipeline.update_nodes_and_plugs_activation,
                                 "enabled")

        # add an event on the Node instance traits to validate the pipeline
        self.on_trait_change(pipeline.update_nodes_and_plugs_activation,
                             "enabled")
Exemple #12
0
    def create_widget(parent,
                      control_name,
                      control_value,
                      trait,
                      label_class=None,
                      user_data=None):
        """ Method to create the list widget.

        Parameters
        ----------
        parent: QWidget (mandatory)
            the parent widget
        control_name: str (mandatory)
            the name of the control we want to create
        control_value: list of items (mandatory)
            the default control value
        trait: Tait (mandatory)
            the trait associated to the control
        label_class: Qt widget class (optional, default: None)
            the label widget will be an instance of this class. Its constructor
            will be called using 2 arguments: the label string and the parent
            widget.

        Returns
        -------
        out: 2-uplet
            a two element tuple of the form (control widget: ,
            associated labels: (a label QLabel, the tools QWidget))
        """
        widget, label = OffscreenListFileControlWidget.create_widget(
            parent,
            control_name,
            control_value,
            trait,
            label_class=label_class,
            user_data=user_data)

        layout = widget.layout()

        project = user_data.get('project')
        scan_list = user_data.get('scan_list')
        main_window = user_data.get('main_window')
        if project and scan_list:
            # Create a browse button
            button = Qt.QPushButton("Filter", widget)
            button.setObjectName('filter_button')
            button.setStyleSheet('QPushButton#filter_button '
                                 '{padding: 2px 10px 2px 10px; margin: 0px;}')
            layout.addWidget(button)
            widget.filter_b = button

            # Set a callback on the browse button
            control_class = parent.get_control_class(trait)
            node_name = getattr(parent.controller, 'name', None)
            if node_name is None:
                node_name = parent.controller.__class__.__name__
            browse_hook = partial(control_class.filter_clicked,
                                  weak_proxy(widget), node_name, control_name)
            #parameters, process)
            widget.filter_b.clicked.connect(browse_hook)

        return (widget, label)
Exemple #13
0
    def create_widget(parent,
                      control_name,
                      control_value,
                      trait,
                      label_class=None,
                      user_data=None):
        """ Method to create the file widget.

        Parameters
        ----------
        parent: QWidget (mandatory)
            the parent widget
        control_name: str (mandatory)
            the name of the control we want to create
        control_value: str (mandatory)
            the default control value
        trait: Tait (mandatory)
            the trait associated to the control
        label_class: Qt widget class (optional, default: None)
            the label widget will be an instance of this class. Its constructor
            will be called using 2 arguments: the label string and the parent
            widget.

        Returns
        -------
        out: 2-uplet
            a two element tuple of the form (control widget: QWidget with two
            elements, a QLineEdit in the 'path' parameter and a browse button
            in the 'browse' parameter, associated label: QLabel)
        """
        # Create the widget that will be used to select a file
        widget, label = FileControlWidget.create_widget(
            parent,
            control_name,
            control_value,
            trait,
            label_class=label_class,
            user_data=user_data)
        if user_data is None:
            user_data = {}
        widget.user_data = user_data  # regular File does not store data

        layout = widget.layout()

        project = user_data.get('project')
        scan_list = user_data.get('scan_list')
        connected_inputs = user_data.get('connected_inputs', set())

        def is_number(x):
            try:
                int(x)
                return True
            except ValueError:
                return False

        main_window = user_data.get('main_window')
        # files in a list don't get a Filter button.
        if project and scan_list and not trait.output \
                and control_name not in connected_inputs \
                and not is_number(control_name):
            # Create a browse button
            button = Qt.QPushButton("Filter", widget)
            button.setObjectName('filter_button')
            button.setStyleSheet('QPushButton#filter_button '
                                 '{padding: 2px 10px 2px 10px; margin: 0px;}')
            layout.addWidget(button)
            widget.filter_b = button

            # Set a callback on the browse button
            control_class = parent.get_control_class(trait)
            node_name = getattr(parent.controller, 'name', None)
            if node_name is None:
                node_name = parent.controller.__class__.__name__
            browse_hook = partial(control_class.filter_clicked,
                                  weak_proxy(widget), node_name, control_name)
            widget.filter_b.clicked.connect(browse_hook)

        return (widget, label)