From 27fd28ded246fca41bbcf776be11cd600103a280 Mon Sep 17 00:00:00 2001 From: Flavio Tarsetti Date: Sun, 24 Nov 2019 04:15:28 +0100 Subject: [PATCH] [widgets][toolchaineditor] loops loading --- .../widgets/toolchain_style_config.json | 1 + beat/editor/widgets/toolchaineditor.py | 348 ++++++++++++++---- 2 files changed, 287 insertions(+), 62 deletions(-) diff --git a/beat/editor/widgets/toolchain_style_config.json b/beat/editor/widgets/toolchain_style_config.json index 7f0aafb..c766631 100644 --- a/beat/editor/widgets/toolchain_style_config.json +++ b/beat/editor/widgets/toolchain_style_config.json @@ -20,6 +20,7 @@ "background_color_datasets": [255, 254, 200, 255], "background_color_blocks": [204, 204, 204, 255], "background_color_analyzers": [136, 150, 216, 255], + "background_color_loops": [182, 216, 136, 255], "border_color": [50, 50, 50, 255], "selection_border_color": [170, 80, 80, 255], "text_color": [0, 0, 0, 255] diff --git a/beat/editor/widgets/toolchaineditor.py b/beat/editor/widgets/toolchaineditor.py index 7604426..eb8f82f 100644 --- a/beat/editor/widgets/toolchaineditor.py +++ b/beat/editor/widgets/toolchaineditor.py @@ -209,10 +209,22 @@ class InputPin(BasePin): width = height x = -(width / 2.0) - y = ( - self.block_object.height - + self.block_object.inputs.index(self.pin) * self.block_object.pin_height - ) + + if self.block_object.type == BlockType.LOOPS.name: + if self.pin in self.block_object.processor_inputs: + _idx = self.block_object.processor_inputs.index(self.pin) + elif self.pin in self.block_object.evaluator_inputs: + _idx = self.block_object.evaluator_inputs.index(self.pin) + len( + self.block_object.processor_inputs + ) + + y = self.block_object.height + _idx * self.block_object.pin_height + else: + y = ( + self.block_object.height + + self.block_object.inputs.index(self.pin) + * self.block_object.pin_height + ) rect = QRectF(QRect(x, y, width, height)) return rect @@ -231,10 +243,21 @@ class OutputPin(BasePin): width = height x = self.block_object.custom_width - (width / 2.0) - y = ( - self.block_object.height - + self.block_object.outputs.index(self.pin) * self.block_object.pin_height - ) + if self.block_object.type == BlockType.LOOPS.name: + if self.pin in self.block_object.processor_outputs: + _idx = self.block_object.processor_outputs.index(self.pin) + elif self.pin in self.block_object.evaluator_outputs: + _idx = self.block_object.evaluator_outputs.index(self.pin) + len( + self.block_object.processor_outputs + ) + + y = self.block_object.height + _idx * self.block_object.pin_height + else: + y = ( + self.block_object.height + + self.block_object.outputs.index(self.pin) + * self.block_object.pin_height + ) rect = QRectF(QRect(x, y, width, height)) return rect @@ -371,8 +394,29 @@ class Connection(QGraphicsPathItem): elif block.name == self.end_block_name: self.end_block = block - self.start_pin = self.start_block.pins["outputs"][self.start_pin_name] - self.end_pin = self.end_block.pins["inputs"][self.end_pin_name] + if self.start_block.type == BlockType.LOOPS.name: + if self.start_pin_name in self.start_block.pins["outputs"]["processor"]: + self.start_pin = self.start_block.pins["outputs"]["processor"][ + self.start_pin_name + ] + else: + self.start_pin = self.start_block.pins["outputs"]["evaluator"][ + self.start_pin_name + ] + else: + self.start_pin = self.start_block.pins["outputs"][self.start_pin_name] + + if self.end_block.type == BlockType.LOOPS.name: + if self.end_pin_name in self.end_block.pins["inputs"]["processor"]: + self.end_pin = self.end_block.pins["inputs"]["processor"][ + self.end_pin_name + ] + else: + self.end_pin = self.end_block.pins["inputs"]["evaluator"][ + self.end_pin_name + ] + else: + self.end_pin = self.end_block.pins["inputs"][self.end_pin_name] self.start_pin_center_point = self.start_pin.get_center_point() self.end_pin_center_point = self.end_pin.get_center_point() @@ -484,6 +528,7 @@ class BlockType(Enum): BLOCKS = "blocks" ANALYZERS = "analyzers" DATASETS = "datasets" + LOOPS = "loops" @classmethod def from_name(cls, name): @@ -506,15 +551,21 @@ class Block(QGraphicsObject): self.type = block_type self.name = "" - if self.type == BlockType.DATASETS.name: - self.inputs = None + if self.type == BlockType.LOOPS.name: + self.processor_inputs = [] + self.processor_outputs = [] + self.evaluator_inputs = [] + self.evaluator_outputs = [] else: - self.inputs = [] + if self.type == BlockType.DATASETS.name: + self.inputs = None + else: + self.inputs = [] - if self.type == BlockType.ANALYZERS.name: - self.outputs = None - else: - self.outputs = [] + if self.type == BlockType.ANALYZERS.name: + self.outputs = None + else: + self.outputs = [] self.synchronized_channel = None @@ -526,6 +577,12 @@ class Block(QGraphicsObject): self.pins["inputs"] = dict() self.pins["outputs"] = dict() + if self.type == BlockType.LOOPS.name: + self.pins["inputs"]["processor"] = dict() + self.pins["outputs"]["processor"] = dict() + self.pins["inputs"]["evaluator"] = dict() + self.pins["outputs"]["evaluator"] = dict() + self.set_style(style) def load(self, toolchain, block_details): @@ -534,11 +591,23 @@ class Block(QGraphicsObject): if "name" in block_details: self.name = block_details["name"] - if self.type != BlockType.DATASETS.name: - self.inputs = block_details["inputs"] + if self.type == BlockType.LOOPS.name: + self.processor_inputs = block_details["processor_inputs"] + self.processor_outputs = block_details["processor_outputs"] + self.evaluator_inputs = block_details["evaluator_inputs"] + self.evaluator_outputs = block_details["evaluator_outputs"] + else: + if ( + self.type != BlockType.DATASETS.name + and self.type != BlockType.LOOPS.name + ): + self.inputs = block_details["inputs"] - if self.type != BlockType.ANALYZERS.name: - self.outputs = block_details["outputs"] + if ( + self.type != BlockType.ANALYZERS.name + and self.type != BlockType.LOOPS.name + ): + self.outputs = block_details["outputs"] if "synchronized_channel" in block_details: self.synchronized_channel = block_details["synchronized_channel"] @@ -548,24 +617,57 @@ class Block(QGraphicsObject): def create_pins(self): - if self.inputs is not None: - for pin_name in self.inputs: + if self.type == BlockType.LOOPS.name: + for pin_name in self.processor_inputs: input_pin = InputPin( self, pin_name, self.name, self.pin_brush, self.pin_pen ) - self.pins["inputs"][pin_name] = input_pin + self.pins["inputs"]["processor"][pin_name] = input_pin input_pin.dataChanged.connect(self.dataChanged) - if self.outputs is not None: - for pin_name in self.outputs: + for pin_name in self.processor_outputs: output_pin = OutputPin( self, pin_name, self.name, self.pin_brush, self.pin_pen ) - self.pins["outputs"][pin_name] = output_pin + self.pins["outputs"]["processor"][pin_name] = output_pin output_pin.dataChanged.connect(self.dataChanged) + for pin_name in self.evaluator_inputs: + input_pin = InputPin( + self, pin_name, self.name, self.pin_brush, self.pin_pen + ) + self.pins["inputs"]["evaluator"][pin_name] = input_pin + + input_pin.dataChanged.connect(self.dataChanged) + + for pin_name in self.evaluator_outputs: + output_pin = OutputPin( + self, pin_name, self.name, self.pin_brush, self.pin_pen + ) + self.pins["outputs"]["evaluator"][pin_name] = output_pin + + output_pin.dataChanged.connect(self.dataChanged) + else: + if self.inputs is not None: + for pin_name in self.inputs: + input_pin = InputPin( + self, pin_name, self.name, self.pin_brush, self.pin_pen + ) + self.pins["inputs"][pin_name] = input_pin + + input_pin.dataChanged.connect(self.dataChanged) + + if self.outputs is not None: + for pin_name in self.outputs: + output_pin = OutputPin( + self, pin_name, self.name, self.pin_brush, self.pin_pen + ) + self.pins["outputs"][pin_name] = output_pin + + output_pin.dataChanged.connect(self.dataChanged) + def set_style(self, config): self.setAcceptHoverEvents(True) @@ -585,19 +687,60 @@ class Block(QGraphicsObject): metrics = QFontMetrics(self.text_font) text_width = metrics.boundingRect(self.name).width() + 24 - if self.inputs is not None and len(self.inputs) > 0: - self.max_inputs_width = ( - metrics.boundingRect(max(self.inputs, key=len)).width() + 24 + if self.type == BlockType.LOOPS.name: + if len(self.processor_inputs) > 0: + self.max_processor_inputs_width = ( + metrics.boundingRect(max(self.processor_inputs, key=len)).width() + + 24 + ) + else: + self.max_processor_inputs_width = 24 + + if len(self.evaluator_inputs) > 0: + self.max_evaluator_inputs_width = ( + metrics.boundingRect(max(self.evaluator_inputs, key=len)).width() + + 24 + ) + else: + self.max_evaluator_inputs_width = 24 + + self.max_inputs_width = max( + self.max_processor_inputs_width, self.max_evaluator_inputs_width ) - else: - self.max_inputs_width = 24 - if self.outputs is not None and len(self.outputs) > 0: - self.max_outputs_width = ( - metrics.boundingRect(max(self.outputs, key=len)).width() + 24 + if len(self.processor_outputs) > 0: + self.max_processor_outputs_width = ( + metrics.boundingRect(max(self.processor_outputs, key=len)).width() + + 24 + ) + else: + self.max_processor_outputs_width = 24 + + if len(self.evaluator_outputs) > 0: + self.max_evaluator_outputs_width = ( + metrics.boundingRect(max(self.evaluator_outputs, key=len)).width() + + 24 + ) + else: + self.max_evaluator_outputs_width = 24 + + self.max_outputs_width = max( + self.max_processor_outputs_width, self.max_evaluator_outputs_width ) else: - self.max_outputs_width = 24 + if self.inputs is not None and len(self.inputs) > 0: + self.max_inputs_width = ( + metrics.boundingRect(max(self.inputs, key=len)).width() + 24 + ) + else: + self.max_inputs_width = 24 + + if self.outputs is not None and len(self.outputs) > 0: + self.max_outputs_width = ( + metrics.boundingRect(max(self.outputs, key=len)).width() + 24 + ) + else: + self.max_outputs_width = 24 self.custom_width = max( self.max_outputs_width + self.max_inputs_width, text_width @@ -615,6 +758,7 @@ class Block(QGraphicsObject): self.background_color_datasets = QColor(*config["background_color_datasets"]) self.background_color_analyzers = QColor(*config["background_color_analyzers"]) self.background_color_blocks = QColor(*config["background_color_blocks"]) + self.background_color_loops = QColor(*config["background_color_loops"]) self.background_brush.setColor(self.background_color_blocks) @@ -652,14 +796,20 @@ class Block(QGraphicsObject): metrics = QFontMetrics(self.text_font) text_height = metrics.boundingRect(self.name).height() + 24 - if self.inputs is not None and self.outputs is not None: - max_pin_height = max(len(self.inputs), len(self.outputs)) - elif self.inputs is not None and self.outputs is None: - max_pin_height = len(self.inputs) - elif self.inputs is None and self.outputs is not None: - max_pin_height = len(self.outputs) + if self.type == BlockType.LOOPS.name: + max_pin_height = max( + len(self.processor_inputs) + len(self.evaluator_inputs), + len(self.processor_outputs) + len(self.evaluator_outputs), + ) else: - max_pin_height = 0 + if self.inputs is not None and self.outputs is not None: + max_pin_height = max(len(self.inputs), len(self.outputs)) + elif self.inputs is not None and self.outputs is None: + max_pin_height = len(self.inputs) + elif self.inputs is None and self.outputs is not None: + max_pin_height = len(self.outputs) + else: + max_pin_height = 0 if max_pin_height == 0: self.custom_width = 55 @@ -672,9 +822,9 @@ class Block(QGraphicsObject): rect = QRectF(rect) return rect - def draw_pins_name(self, painter, _type, data): + def draw_pins_name(self, painter, _type, data, offset): """Paint pin with name""" - offset = 0 + offset = offset * self.pin_height for pin_name in data: # Pin rect painter.setBrush(self.background_brush) @@ -852,18 +1002,26 @@ class Block(QGraphicsObject): self.background_brush.setColor(self.background_color_datasets) elif self.type == BlockType.ANALYZERS.name: self.background_brush.setColor(self.background_color_analyzers) + elif self.type == BlockType.LOOPS.name: + self.background_brush.setColor(self.background_color_loops) painter.setBrush(self.background_brush) painter.setPen(self.border_pen) - if self.inputs is not None and self.outputs is not None: - max_pin_height = max(len(self.inputs), len(self.outputs)) - elif self.inputs is not None and self.outputs is None: - max_pin_height = len(self.inputs) - elif self.inputs is None and self.outputs is not None: - max_pin_height = len(self.outputs) + if self.type == BlockType.LOOPS.name: + max_pin_height = max( + len(self.processor_inputs) + len(self.evaluator_inputs), + len(self.processor_outputs) + len(self.evaluator_outputs), + ) else: - max_pin_height = 0 + if self.inputs is not None and self.outputs is not None: + max_pin_height = max(len(self.inputs), len(self.outputs)) + elif self.inputs is not None and self.outputs is None: + max_pin_height = len(self.inputs) + elif self.inputs is None and self.outputs is not None: + max_pin_height = len(self.outputs) + else: + max_pin_height = 0 if self.isSelected(): self.selection_border_pen.setWidth(3) @@ -898,10 +1056,20 @@ class Block(QGraphicsObject): painter.drawText(text_rect, Qt.AlignCenter, self.name) # Pin - if self.inputs is not None: - self.draw_pins_name(painter, "input", self.inputs) - if self.outputs is not None: - self.draw_pins_name(painter, "output", self.outputs) + if self.type == BlockType.LOOPS.name: + self.draw_pins_name(painter, "input", self.processor_inputs, 0) + self.draw_pins_name( + painter, "input", self.evaluator_inputs, len(self.processor_inputs) + ) + self.draw_pins_name(painter, "output", self.processor_outputs, 0) + self.draw_pins_name( + painter, "output", self.evaluator_outputs, len(self.processor_outputs) + ) + else: + if self.inputs is not None: + self.draw_pins_name(painter, "input", self.inputs, 0) + if self.outputs is not None: + self.draw_pins_name(painter, "output", self.outputs, 0) class ToolchainView(QGraphicsView): @@ -1012,6 +1180,11 @@ class Toolchain(QWidget): self.toolbar = QToolBar() + # loop_action = QAction( + # QIcon("beat/editor/widgets/dataset_icon.png"), "&Loop", self + # ) + # loop_action.triggered.connect(lambda: self.add_block(BlockType.LOOP)) + self.dataset_button = QPushButton() self.dataset_button.setToolTip("Dataset") self.dataset_button.setIcon(QIcon("beat/editor/widgets/dataset_icon.png")) @@ -1116,7 +1289,15 @@ class Toolchain(QWidget): self.scene.addItem(block) def set_prefix_databases_algorithms_lists( - self, prefix_path, dataset_list, algorithm_list, analyzer_list + self, + prefix_path, + dataset_list, + algorithm_list, + sequential_loop_processor_list, + autonomous_loop_processor_list, + sequential_loop_evaluator_list, + autonomous_loop_evaluator_list, + analyzer_list, ): self.prefix_path = prefix_path @@ -1212,10 +1393,16 @@ class Toolchain(QWidget): block_data["name"] = block.name if block.synchronized_channel is not None: block_data["synchronized_channel"] = block.synchronized_channel - if block.inputs is not None: - block_data["inputs"] = block.inputs - if block.outputs is not None: - block_data["outputs"] = block.outputs + if block.type == BlockType.LOOPS.name: + block_data["processor_inputs"] = block.processor_inputs + block_data["evaluator_inputs"] = block.evaluator_inputs + block_data["processor_outputs"] = block.processor_outputs + block_data["evaluator_outputs"] = block.evaluator_outputs + else: + if block.inputs is not None: + block_data["inputs"] = block.inputs + if block.outputs is not None: + block_data["outputs"] = block.outputs block_type_list.append(block_data) data["representation"]["blocks"][block.name] = { @@ -1260,6 +1447,10 @@ class ToolchainEditor(AbstractAssetEditor): self.algorithm_list = [] self.analyzer_list = [] self.dataset_list = [] + self.sequential_loop_processor_list = [] + self.autonomous_loop_processor_list = [] + self.sequential_loop_evaluator_list = [] + self.autonomous_loop_evaluator_list = [] self.toolchain.dataChanged.connect(self.dataChanged) self.contextChanged.connect(self.__onContextChanged) @@ -1278,14 +1469,47 @@ class ToolchainEditor(AbstractAssetEditor): algorithm_model.index(i, 0).data() for i in range(algorithm_model.rowCount()) ] + algorithm_model.setAnalyzerEnabled(True) self.analyzer_list = [ algorithm_model.index(i, 0).data() for i in range(algorithm_model.rowCount()) ] + algorithm_model.setAnalyzerEnabled(False) + algorithm_model.setTypes([Algorithm.SEQUENTIAL_LOOP_PROCESSOR]) + self.sequential_loop_processor_list = [ + algorithm_model.index(i, 0).data() + for i in range(algorithm_model.rowCount()) + ] + + algorithm_model.setTypes([Algorithm.AUTONOMOUS_LOOP_PROCESSOR]) + self.autonomous_loop_processor_list = [ + algorithm_model.index(i, 0).data() + for i in range(algorithm_model.rowCount()) + ] + + algorithm_model.setTypes([Algorithm.SEQUENTIAL_LOOP_EVALUATOR]) + self.sequential_loop_evaluator_list = [ + algorithm_model.index(i, 0).data() + for i in range(algorithm_model.rowCount()) + ] + + algorithm_model.setTypes([Algorithm.AUTONOMOUS_LOOP_EVALUATOR]) + self.autonomous_loop_evaluator_list = [ + algorithm_model.index(i, 0).data() + for i in range(algorithm_model.rowCount()) + ] + self.toolchain.set_prefix_databases_algorithms_lists( - self.prefix_path, self.dataset_list, self.algorithm_list, self.analyzer_list + self.prefix_path, + self.dataset_list, + self.algorithm_list, + self.sequential_loop_processor_list, + self.autonomous_loop_processor_list, + self.sequential_loop_evaluator_list, + self.autonomous_loop_evaluator_list, + self.analyzer_list, ) def _load_json(self, json_object): -- 2.21.0