Exemple #1
0
    def create_time_labels(self):
        """Create the time labels, but don't plot them yet.

        Notes
        -----
        It's necessary to have the height of the time labels, so that we can
        adjust the main scene.

        Not very robust, because it uses seconds as integers.
        """
        min_time = int(floor(min(self.data.axis['time'][0])))
        max_time = int(ceil(max(self.data.axis['time'][0])))
        n_time_labels = self.parent.value('n_time_labels')

        self.idx_time = []
        self.time_pos = []
        for one_time in linspace(min_time, max_time, n_time_labels):
            x_label = (self.data.start_time +
                       timedelta(seconds=one_time)).strftime('%H:%M:%S')
            item = QGraphicsSimpleTextItem(x_label)
            item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
            self.idx_time.append(item)
            self.time_pos.append(QPointF(one_time,
                                         len(self.idx_label) *
                                         self.parent.value('y_distance')))
Exemple #2
0
    def create_time_labels(self):
        """Create the time labels, but don't plot them yet.

        Notes
        -----
        It's necessary to have the height of the time labels, so that we can
        adjust the main scene.

        Not very robust, because it uses seconds as integers.
        """
        min_time = int(floor(min(self.data.axis['time'][0])))
        max_time = int(ceil(max(self.data.axis['time'][0])))
        n_time_labels = self.parent.value('n_time_labels')

        self.idx_time = []
        self.time_pos = []
        for one_time in linspace(min_time, max_time, n_time_labels):
            x_label = (self.data.start_time +
                       timedelta(seconds=one_time)).strftime('%H:%M:%S')
            item = QGraphicsSimpleTextItem(x_label)
            item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
            self.idx_time.append(item)
            self.time_pos.append(
                QPointF(one_time,
                        len(self.idx_label) * self.parent.value('y_distance')))
Exemple #3
0
    def create_chan_labels(self):
        """Create the channel labels, but don't plot them yet.

        Notes
        -----
        It's necessary to have the width of the labels, so that we can adjust
        the main scene.
        """
        self.idx_label = []
        for one_grp in self.parent.channels.groups:
            for one_label in one_grp['chan_to_plot']:
                item = QGraphicsSimpleTextItem(one_label)
                item.setBrush(QBrush(QColor(one_grp['color'])))
                item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
                self.idx_label.append(item)
Exemple #4
0
    def create_chan_labels(self):
        """Create the channel labels, but don't plot them yet.

        Notes
        -----
        It's necessary to have the width of the labels, so that we can adjust
        the main scene.
        """
        self.idx_label = []
        for one_grp in self.parent.channels.groups:
            for one_label in one_grp['chan_to_plot']:
                item = QGraphicsSimpleTextItem(one_label)
                item.setBrush(QBrush(QColor(one_grp['color'])))
                item.setFlag(QGraphicsItem.ItemIgnoresTransformations)
                self.idx_label.append(item)
Exemple #5
0
class Scene(GBaseModelScene):
    def __init__(self, main_widget, workflow, available_actions, parent=None):
        super(Scene, self).__init__(workflow, parent)
        self.detached_port = None
        self.available_actions = available_actions

        self.main_widget = main_widget
        self.workflow_name = QGraphicsSimpleTextItem(workflow.name)
        self.workflow_name.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)
        self.selectionChanged.connect(self.on_selection_changed)

        self.new_action_pos = QtCore.QPoint()

        self.initialize_workspace_from_workflow()

    def on_selection_changed(self):
        if len(self.selectedItems()) == 1:
            self.main_widget.property_editor.set_action( self.workflow, self.selectedItems()[0])
            pass
        else:
            self.main_widget.property_editor.clear()

    def initialize_workspace_from_workflow(self):
        for action_name, action in {**self.workflow.action_call_dict, "__result__": self.workflow._result_call}.items():
            if not isinstance(action.action, _Value):
                self._add_action(QPoint(0.0, 0.0), action_name)

        self.update_scene()
        self.order_diagram()
        self.update_scene()
        self.parent().center_on_content = True

    def draw_action(self, item):
        action = {**self.workflow.action_call_dict, "__result__":self.workflow._result_call}.get(item.data(GActionData.NAME))

        if action is None:
            action = self.unconnected_actions.get(item.data(GActionData.NAME))

        if not isinstance(action.action, _Value):
            if isinstance(action, _SlotCall):
                self.actions.append(GInputAction(item, action, self.root_item))
                self.workflow.is_analysis = False
            elif isinstance(action, _ResultCall):
                self.actions.append(GOutputAction(item, action, self.root_item))
            elif isinstance(action, ActionCall):
                self.actions.append(GAction(item, action, self.root_item))

            for child in item.children():
                self.draw_action(child)

            self.update()

    def drawForeground(self, painter, rectf):
        super(Scene, self).drawForeground(painter, rectf)
        painter.resetTransform()
        painter.scale(1.5, 1.5)
        text = QStaticText("Workflow: " + self.workflow.name)
        painter.drawStaticText(QPoint(5,5), text)

    def find_top_afs(self, pos):
        for item in self.items(pos):
            if issubclass(type(item), GActionForSubactions):
                return [item, item.mapFromScene(pos)]
        return [self.root_item, pos]

    def add_random_items(self):
        if not self.actions:
            self.new_action_pos = QtCore.QPoint(0, 0)
            self.add_action()
        for i in range(200):
            if i > 100:
                action = self.actions[random.randint(0,len(self.actions) - 1)]
                self.add_connection(action.in_ports[random.randint(0, len(action.in_ports) - 1)])
                action = self.actions[random.randint(0, len(self.actions) - 1)]
                self.add_connection(action.out_ports[random.randint(0, len(action.out_ports) - 1)])
            else:
                self.new_action_pos = QtCore.QPoint(random.randint(-800, 800), random.randint(-800, 800))
                self.add_action(QtCore.QPoint(random.randint(-800, 800), random.randint(-800, 800)))
                self.update_scene()

    def mouseReleaseEvent(self, release_event):
        super(Scene, self).mouseReleaseEvent(release_event)

    def action_name_changed(self, action_data, new_name):
        if self.action_model.exists(new_name):
            return False
        self.action_model.name_changed(action_data,new_name)
        return True

    def is_graph_acyclic(self):
        leaf_nodes = []
        processed_nodes = []
        acyclic_nodes = []
        for node in self.actions:
            if node.next_actions():
                pass
            else:
                leaf_nodes.append(node)

        while leaf_nodes:
            node = leaf_nodes.pop()
            processed_nodes.append(node)
            acyclic_nodes.append(node)

            prev_actions = node.previous_actions()
            i = 0
            while len(prev_actions) > i:
                curr = prev_actions[i]
                if curr in processed_nodes:
                    return False
                else:
                    processed_nodes.append(curr)
                    for act in curr.previous_actions():
                        if act not in prev_actions:
                            prev_actions.append(act)
                i += 1

        if len(processed_nodes) == len(self.actions):
            return True
        else:
            return False

    # Modifying functions
    def add_action(self, new_action_pos, action_type="wf.List"):
        index = action_type.rfind(".")
        module = action_type[:index]
        action_name = action_type[index + 1:]

        if action_type == "wf._Slot":
            action = _SlotCall("slot")
            name = self.action_model.add_item(new_action_pos.x(), new_action_pos.y(), 50, 50, action.name)
            action.name = name
            self.workflow.insert_slot(len(self.workflow.slots), action)
            self.main_widget.tab_widget.current_module_view().workspace_changed()

        elif action_name in self.available_actions[module]:
            action = ActionCall.create(self.available_actions[module][action_name])
            name = self.action_model.add_item(new_action_pos.x(), new_action_pos.y(), 50, 50, action.name)
            action.name = name

        else:
            assert False, "Action isn't supported by scene!"
            return



        self.unconnected_actions[name] = action
    '''
    def add_while_loop(self):
        [parent, pos] = self.find_top_afs(self.new_action_pos)
        self.actions.append(ActionForSubactions(parent, pos))
    '''

    def detach_connection(self, in_port, alt):
        action_name1 = in_port.parentItem().name
        port_index1 = in_port.parentItem().in_ports.index(in_port)
        action_name2 = in_port.connections[0].port1.parentItem().name
        self._delete_connection(in_port.connections[0])
        self.update_model = True
        self.update_scene()
        port1 = self.get_action(action_name1).in_ports[port_index1]
        port2 = self.get_action(action_name2).out_ports[0]
        if alt:
            connected_port = port2
            self.detached_port = port1
        else:
            connected_port = port1
            self.detached_port = port2

        self.add_connection(connected_port)

    def add_connection(self, port):
        """Create new connection from/to specified port and add it to workspace."""
        if self.new_connection is None:
            self.clearSelection()
            if isinstance(port, GOutputPort):
                self.enable_ports(False, False)
            else:
                self.enable_ports(True, False)
            self.new_connection = GConnection(port)
            self.new_connection.unsetCursor()
            self.addItem(self.new_connection)
            self.new_connection.setFlag(QtWidgets.QGraphicsPathItem.ItemIsSelectable, False)
        else:
            if isinstance(port, GOutputPort):
                self.enable_ports(True, True)
            else:
                self.enable_ports(False, True)

            self.new_connection.set_port2(port)

            port1 = self.new_connection.port1
            port2 = self.new_connection.port2
            port1.connections.append(self.new_connection)
            port2.connections.append(self.new_connection)
            action1 = port1.parentItem().w_data_item
            action2 = port2.parentItem().w_data_item
            self.workflow.set_action_input(action2, port2.index, action1)
            if True: #self.is_graph_acyclic():
                self.new_connection.setFlag(QtWidgets.QGraphicsPathItem.ItemIsSelectable, True)
                self.new_connection.setCursor(Qt.ArrowCursor)
                self.new_connection = None
                self.detached_port = None
                self.update_model = True

                if port1.appending_port:
                    port1.appending_port = False

                def update_unconected(action):
                    self.unconnected_actions.pop(action.name, None)
                    for argument in action.arguments:
                        update_unconected(argument.value)

                if action1 in self.workflow.action_call_dict.values():
                    update_unconected(action1)

                if action2 in self.workflow.action_call_dict.values():
                    update_unconected(action2)

                if port2.appending_port:
                    port2.appending_port = False


            else:
                msg = "Pipeline cannot be cyclic!"
                msg = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning,
                                            "Cyclic diagram", msg,
                                            QtWidgets.QMessageBox.Ok)
                msg.exec_()
                self._delete_connection(self.new_connection)
                self.new_connection = None

    def enable_ports(self, in_ports, enable):
        for action in self.actions:
            for port in action.in_ports if in_ports else action.out_ports:
                port.setEnabled(enable)

            for port in action.in_ports:
                if port.connections:
                    port.setEnabled(enable)

    def keyPressEvent(self, key_event):
        if key_event.key() == Qt.Key_Escape:
            if self.detached_port:
                self.add_connection(self.detached_port)
            else:
                self.removeItem(self.new_connection)
                self.new_connection = None
                self.enable_ports(True, True)
                self.enable_ports(False, True)


    def delete_items(self):
        """Delete all selected items from workspace."""
        if self.new_connection is None:
            while self.selectedItems():

                item = self.selectedItems()[0]
                if self.is_action(item):
                    for port in item.ports():
                        while port.connections:
                            self._delete_connection(port.connections[0])

                    self._delete_action(item)
                else:
                    self._delete_connection(item)

            self.update_model = True
            self.update()

    def _delete_action(self, action):
        """Delete specified action from workspace."""
        if not isinstance(action.w_data_item, _ResultCall):
            self.action_model.removeRow(action.g_data_item.child_number())
            self.actions.remove(action)
            self.removeItem(action)
            self.unconnected_actions.pop(action.name)

            if isinstance(action, GInputAction):
                self.workflow.remove_slot(self.workflow.slots.index(action.w_data_item))
            action = action.w_data_item
            for i in range(len(action.arguments)):
                if action.arguments[i].value is not None:
                    if isinstance(action.arguments[i].value.action, Value):
                        self.unconnected_actions.pop(action.arguments[i].value.name, None)
        else:
            action.setSelected(False)

    def _delete_connection(self, conn):
        action1 = conn.port1.parentItem().w_data_item
        action2 = conn.port2.parentItem().w_data_item
        for i in range(len(action2.arguments)):

            if action1 == action2.arguments[i].value:
                self.workflow.set_action_input(action2, i, None)
        if isinstance(action1, Value):
            self._delete_action(conn.port1.parentItem())

        def put_all_actions_to_unconnected(action):
            if action is None:
                print('Processing None')
                return
            self.unconnected_actions[action.name] = action
            for argument in action.arguments:
                put_all_actions_to_unconnected(argument.value)

        if action1 not in self.workflow.action_call_dict:
            put_all_actions_to_unconnected(action1)
        conn.port1.connections.remove(conn)
        conn.port2.connections.remove(conn)
        self.removeItem(conn)

    def save_item(self, save_file, item, level=0):
        for child in item.children():
            save_file.write("\t"*level)
            for col in range(child.column_count()):
                save_file.write(str(child.data(col)) + ",")
            save_file.write("\n")
            self.save_item(save_file, child, level+1)

    def save_connection(self, index=QtCore.QModelIndex()):
        for child in self.connection_model.get_item().children():
            self.draw_connection(child)

    def load_item(self):
        pass