Commit b889cd60 authored by Flavio TARSETTI's avatar Flavio TARSETTI

[widgets][toolchaineditor] loop creation/editing

parent 27fd28de
......@@ -45,6 +45,7 @@ from PyQt5.QtGui import QTransform
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QFormLayout
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QGraphicsView
......@@ -61,6 +62,7 @@ from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtWidgets import QColorDialog
from PyQt5.QtWidgets import QListWidget
from beat.backend.python.algorithm import Algorithm
......@@ -211,14 +213,17 @@ class InputPin(BasePin):
x = -(width / 2.0)
if self.block_object.type == BlockType.LOOPS.name:
_idx = None
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
if _idx is not None:
y = self.block_object.height + _idx * self.block_object.pin_height
else:
y = self.block_object.height
else:
y = (
self.block_object.height
......@@ -244,6 +249,7 @@ class OutputPin(BasePin):
x = self.block_object.custom_width - (width / 2.0)
if self.block_object.type == BlockType.LOOPS.name:
_idx = None
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:
......@@ -251,7 +257,10 @@ class OutputPin(BasePin):
self.block_object.processor_outputs
)
y = self.block_object.height + _idx * self.block_object.pin_height
if _idx is not None:
y = self.block_object.height + _idx * self.block_object.pin_height
else:
y = self.block_object.height
else:
y = (
self.block_object.height
......@@ -427,6 +436,208 @@ class Connection(QGraphicsPathItem):
self.end_block.blockMoved.connect(self.set_moved_block_pins_coordinates)
class LoopWidget(QDialog):
"""Class holder for the various libraries"""
dataChanged = pyqtSignal()
def __init__(self, parent=None):
"""Constructor"""
super().__init__(parent)
self.setMinimumHeight(200)
# Layouts
layout = QHBoxLayout(self)
self.sequential_loop_processor_listwidget = QListWidget()
self.autonomous_loop_processor_listwidget = QListWidget()
self.sequential_loop_evaluator_listwidget = QListWidget()
self.autonomous_loop_evaluator_listwidget = QListWidget()
# QVBoxLayout for available lists
sequential_loop_processor_listwidget_layout = QVBoxLayout()
sequential_loop_processor_listwidget_layout.addWidget(
QLabel(self.tr("Sequential Loop Processor"))
)
sequential_loop_processor_listwidget_layout.addWidget(
self.sequential_loop_processor_listwidget
)
autonomous_loop_processor_listwidget_layout = QVBoxLayout()
autonomous_loop_processor_listwidget_layout.addWidget(
QLabel(self.tr("Autonomous Loop Processor"))
)
autonomous_loop_processor_listwidget_layout.addWidget(
self.autonomous_loop_processor_listwidget
)
sequential_loop_evaluator_listwidget_layout = QVBoxLayout()
sequential_loop_evaluator_listwidget_layout.addWidget(
QLabel(self.tr("Sequential Loop Evaluator"))
)
sequential_loop_evaluator_listwidget_layout.addWidget(
self.sequential_loop_evaluator_listwidget
)
autonomous_loop_evaluator_listwidget_layout = QVBoxLayout()
autonomous_loop_evaluator_listwidget_layout.addWidget(
QLabel(self.tr("Autonomous Loop Evaluator"))
)
autonomous_loop_evaluator_listwidget_layout.addWidget(
self.autonomous_loop_evaluator_listwidget
)
# Layouts Design
layout.addLayout(sequential_loop_processor_listwidget_layout)
layout.addLayout(autonomous_loop_processor_listwidget_layout)
layout.addLayout(sequential_loop_evaluator_listwidget_layout)
layout.addLayout(autonomous_loop_evaluator_listwidget_layout)
def set_sequential_loop_processor_list(self, _list):
self.sequential_loop_processor_list = _list
self.sequential_loop_processor_listwidget.addItems(_list)
def set_autonomous_loop_processor_list(self, _list):
self.autonomous_loop_processor_list = _list
self.autonomous_loop_processor_listwidget.addItems(_list)
def set_sequential_loop_evaluator_list(self, _list):
self.sequential_loop_evaluator_list = _list
self.sequential_loop_evaluator_listwidget.addItems(_list)
def set_autonomous_loop_evaluator_list(self, _list):
self.autonomous_loop_evaluator_list = _list
self.autonomous_loop_evaluator_listwidget.addItems(_list)
def get_processor_evaluator_loops(self):
selected_loops = {}
selected_sequential_loop_processor = (
self.sequential_loop_processor_listwidget.selectedItems()
)
selected_autonomous_loop_processor = (
self.autonomous_loop_processor_listwidget.selectedItems()
)
selected_sequential_loop_evaluator = (
self.sequential_loop_evaluator_listwidget.selectedItems()
)
selected_autonomous_loop_evaluator = (
self.autonomous_loop_evaluator_listwidget.selectedItems()
)
sequential_loop_processor = None
if selected_sequential_loop_processor:
sequential_loop_processor = selected_sequential_loop_processor[0].text()
autonomous_loop_processor = None
if selected_autonomous_loop_processor:
autonomous_loop_processor = selected_autonomous_loop_processor[0].text()
sequential_loop_evaluator = None
if selected_sequential_loop_evaluator:
sequential_loop_evaluator = selected_sequential_loop_evaluator[0].text()
autonomous_loop_evaluator = None
if selected_autonomous_loop_evaluator:
autonomous_loop_evaluator = selected_autonomous_loop_evaluator[0].text()
selected_loops["sequential_loop_processor"] = sequential_loop_processor
selected_loops["autonomous_loop_processor"] = autonomous_loop_processor
selected_loops["sequential_loop_evaluator"] = sequential_loop_evaluator
selected_loops["autonomous_loop_evaluator"] = autonomous_loop_evaluator
return selected_loops
class LoopDialog(QDialog):
"""Dialog to edit a block"""
def __init__(self, toolchain, parent=None):
"""Constructor
:param block: current block
:param parent QWidget: parent widget
"""
super().__init__(parent)
self.setWindowTitle(self.tr("Add Loop"))
layout = QVBoxLayout(self)
# Layouts Widget
self.loop_widget = LoopWidget()
layout.addWidget(self.loop_widget)
# OK and Cancel buttons
self.buttons = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self
)
layout.addWidget(self.buttons)
# Signals/Slots connection
self.buttons.accepted.connect(self.accept)
self.buttons.rejected.connect(self.reject)
def value(self):
"""Returns the value selected"""
return self.loop_widget.get_processor_evaluator_loops()
def set_lists(
self,
sequential_loop_processor_list,
autonomous_loop_processor_list,
sequential_loop_evaluator_list,
autonomous_loop_evaluator_list,
):
self.loop_widget.set_sequential_loop_processor_list(
sequential_loop_processor_list
)
self.loop_widget.set_autonomous_loop_processor_list(
autonomous_loop_processor_list
)
self.loop_widget.set_sequential_loop_evaluator_list(
sequential_loop_evaluator_list
)
self.loop_widget.set_autonomous_loop_evaluator_list(
autonomous_loop_evaluator_list
)
@staticmethod
def getLoops(
toolchain,
sequential_loop_processor_list,
autonomous_loop_processor_list,
sequential_loop_evaluator_list,
autonomous_loop_evaluator_list,
parent=None,
):
"""Static method to create the dialog and return qdialog accepted/spinbox value
:param block: current block
:param parent QWidget: parent widget
"""
dialog = LoopDialog(toolchain, parent)
dialog.set_lists(
sequential_loop_processor_list,
autonomous_loop_processor_list,
sequential_loop_evaluator_list,
autonomous_loop_evaluator_list,
)
result = dialog.exec_()
value = None
if result == QDialog.Accepted:
value = dialog.value()
return (value, result)
class BlockEditionDialog(QDialog):
"""Dialog to edit a block"""
......@@ -894,10 +1105,16 @@ class Block(QGraphicsObject):
block_updated = True
if block_updated:
# Update blocks
block_item = {}
block_item["inputs"] = self.inputs
block_item["outputs"] = self.outputs
if self.type == BlockType.LOOPS.name:
block_item["processor_inputs"] = self.processor_inputs
block_item["processor_outputs"] = self.processor_outputs
block_item["evaluator_inputs"] = self.processor_inputs
block_item["evaluator_outputs"] = self.evaluator_outputs
# Update blocks
else:
block_item["inputs"] = self.inputs
block_item["outputs"] = self.outputs
block_item["name"] = self.name
block_item["synchronized_channel"] = self.synchronized_channel
......@@ -1166,6 +1383,11 @@ class Toolchain(QWidget):
self.json_object = {}
self.sequential_loop_processor_list = []
self.autonomous_loop_processor_list = []
self.sequential_loop_evaluator_list = []
self.autonomous_loop_evaluator_list = []
with open("beat/editor/widgets/toolchain_style_config.json") as json_file:
config_data = json.load(json_file)
......@@ -1180,10 +1402,10 @@ 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.loop_button = QPushButton()
self.loop_button.setToolTip("Loop")
self.loop_button.setIcon(QIcon("beat/editor/widgets/dataset_icon.png"))
self.loop_button.clicked.connect(self.add_loop_block)
self.dataset_button = QPushButton()
self.dataset_button.setToolTip("Dataset")
......@@ -1203,6 +1425,7 @@ class Toolchain(QWidget):
self.toolbar.addWidget(self.dataset_button)
self.toolbar.addWidget(self.block_button)
self.toolbar.addWidget(self.analyzer_button)
self.toolbar.addWidget(self.loop_button)
self.toolbar.setOrientation(Qt.Vertical)
......@@ -1210,6 +1433,105 @@ class Toolchain(QWidget):
layout.addWidget(self.toolbar)
layout.addWidget(self.view)
def add_loop_block(self):
loops, ok = LoopDialog.getLoops(
self,
self.sequential_loop_processor_list,
self.autonomous_loop_processor_list,
self.sequential_loop_evaluator_list,
self.autonomous_loop_evaluator_list,
)
sequential_loop_processor = loops["sequential_loop_processor"]
autonomous_loop_processor = loops["autonomous_loop_processor"]
sequential_loop_evaluator = loops["sequential_loop_evaluator"]
autonomous_loop_evaluator = loops["autonomous_loop_evaluator"]
if sequential_loop_processor is None and autonomous_loop_processor is None:
raise ValueError("No processor selected!")
elif sequential_loop_evaluator is None and autonomous_loop_evaluator is None:
raise ValueError("No evaluator selected!")
elif (
sequential_loop_processor is not None
and autonomous_loop_processor is not None
):
raise ValueError("Two processors selected!")
elif (
sequential_loop_evaluator is not None
and autonomous_loop_evaluator is not None
):
raise ValueError("Two evaluators selected!")
else:
processor_asset = None
evaluator_asset = None
processor_inputs = []
processor_outputs = []
evaluator_inputs = []
evaluator_outputs = []
if sequential_loop_processor is not None:
processor_asset = Asset(
self.prefix_path, AssetType.ALGORITHM, sequential_loop_processor
)
else:
processor_asset = Asset(
self.prefix_path, AssetType.ALGORITHM, autonomous_loop_processor
)
if sequential_loop_evaluator is not None:
evaluator_asset = Asset(
self.prefix_path, AssetType.ALGORITHM, sequential_loop_evaluator
)
else:
evaluator_asset = Asset(
self.prefix_path, AssetType.ALGORITHM, autonomous_loop_evaluator
)
processor_declaration = processor_asset.declaration
evaluator_declaration = evaluator_asset.declaration
block_item = {}
for group in processor_declaration["groups"]:
if "inputs" in group:
for key in group["inputs"].keys():
processor_inputs.append(key)
block_item["processor_inputs"] = processor_inputs
if "outputs" in group:
for key in group["outputs"].keys():
processor_outputs.append(key)
block_item["processor_outputs"] = processor_outputs
for group in evaluator_declaration["groups"]:
if "inputs" in group:
for key in group["inputs"].keys():
evaluator_inputs.append(key)
block_item["evaluator_inputs"] = evaluator_inputs
if "outputs" in group:
for key in group["outputs"].keys():
evaluator_outputs.append(key)
block_item["evaluator_outputs"] = evaluator_outputs
init_name_count = 0
init_name = self.tr("CHANGE_ME")
for block in self.blocks:
if block.name.find(init_name) > -1:
init_name_count += 1
new_block_name = init_name + "_" + str(init_name_count)
block_item["name"] = new_block_name
self.web_representation["channel_colors"][new_block_name] = "#000000"
block = Block(
BlockType.LOOPS.name, self.block_config, self.connection_config
)
block.load(self, block_item)
block.dataChanged.connect(self.dataChanged)
block.dataChanged.emit()
self.blocks.append(block)
self.scene.addItem(block)
def update_channel_path(self, block, old_channel, new_channel):
# check if current block is synchronized on old_channel
for connection in self.connections:
......@@ -1329,6 +1651,11 @@ class Toolchain(QWidget):
self.block_button.setMenu(self.block_edit_menu)
self.analyzer_button.setMenu(self.analyzer_edit_menu)
self.sequential_loop_processor_list = sequential_loop_processor_list
self.autonomous_loop_processor_list = autonomous_loop_processor_list
self.sequential_loop_evaluator_list = sequential_loop_evaluator_list
self.autonomous_loop_evaluator_list = autonomous_loop_evaluator_list
def clear_space(self):
self.scene.clear()
self.scene.items().clear()
......@@ -1345,7 +1672,7 @@ class Toolchain(QWidget):
self.clear_space()
# Get datasets, blocks, analyzers
# Get datasets, blocks, analyzers, loops
for block_type in BlockType:
for block_item in self.json_object.get(block_type.value, {}):
block = Block(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment