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 ...@@ -45,6 +45,7 @@ from PyQt5.QtGui import QTransform
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QHBoxLayout from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QFormLayout from PyQt5.QtWidgets import QFormLayout
from PyQt5.QtWidgets import QWidget from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QGraphicsView from PyQt5.QtWidgets import QGraphicsView
...@@ -61,6 +62,7 @@ from PyQt5.QtWidgets import QMenu ...@@ -61,6 +62,7 @@ from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QLineEdit from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtWidgets import QColorDialog from PyQt5.QtWidgets import QColorDialog
from PyQt5.QtWidgets import QListWidget
from beat.backend.python.algorithm import Algorithm from beat.backend.python.algorithm import Algorithm
...@@ -211,14 +213,17 @@ class InputPin(BasePin): ...@@ -211,14 +213,17 @@ class InputPin(BasePin):
x = -(width / 2.0) x = -(width / 2.0)
if self.block_object.type == BlockType.LOOPS.name: if self.block_object.type == BlockType.LOOPS.name:
_idx = None
if self.pin in self.block_object.processor_inputs: if self.pin in self.block_object.processor_inputs:
_idx = self.block_object.processor_inputs.index(self.pin) _idx = self.block_object.processor_inputs.index(self.pin)
elif self.pin in self.block_object.evaluator_inputs: elif self.pin in self.block_object.evaluator_inputs:
_idx = self.block_object.evaluator_inputs.index(self.pin) + len( _idx = self.block_object.evaluator_inputs.index(self.pin) + len(
self.block_object.processor_inputs self.block_object.processor_inputs
) )
if _idx is not None:
y = self.block_object.height + _idx * self.block_object.pin_height y = self.block_object.height + _idx * self.block_object.pin_height
else:
y = self.block_object.height
else: else:
y = ( y = (
self.block_object.height self.block_object.height
...@@ -244,6 +249,7 @@ class OutputPin(BasePin): ...@@ -244,6 +249,7 @@ class OutputPin(BasePin):
x = self.block_object.custom_width - (width / 2.0) x = self.block_object.custom_width - (width / 2.0)
if self.block_object.type == BlockType.LOOPS.name: if self.block_object.type == BlockType.LOOPS.name:
_idx = None
if self.pin in self.block_object.processor_outputs: if self.pin in self.block_object.processor_outputs:
_idx = self.block_object.processor_outputs.index(self.pin) _idx = self.block_object.processor_outputs.index(self.pin)
elif self.pin in self.block_object.evaluator_outputs: elif self.pin in self.block_object.evaluator_outputs:
...@@ -251,7 +257,10 @@ class OutputPin(BasePin): ...@@ -251,7 +257,10 @@ class OutputPin(BasePin):
self.block_object.processor_outputs 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: else:
y = ( y = (
self.block_object.height self.block_object.height
...@@ -427,6 +436,208 @@ class Connection(QGraphicsPathItem): ...@@ -427,6 +436,208 @@ class Connection(QGraphicsPathItem):
self.end_block.blockMoved.connect(self.set_moved_block_pins_coordinates) 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): class BlockEditionDialog(QDialog):
"""Dialog to edit a block""" """Dialog to edit a block"""
...@@ -894,10 +1105,16 @@ class Block(QGraphicsObject): ...@@ -894,10 +1105,16 @@ class Block(QGraphicsObject):
block_updated = True block_updated = True
if block_updated: if block_updated:
# Update blocks
block_item = {} block_item = {}
block_item["inputs"] = self.inputs if self.type == BlockType.LOOPS.name:
block_item["outputs"] = self.outputs 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["name"] = self.name
block_item["synchronized_channel"] = self.synchronized_channel block_item["synchronized_channel"] = self.synchronized_channel
...@@ -1166,6 +1383,11 @@ class Toolchain(QWidget): ...@@ -1166,6 +1383,11 @@ class Toolchain(QWidget):
self.json_object = {} 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: with open("beat/editor/widgets/toolchain_style_config.json") as json_file:
config_data = json.load(json_file) config_data = json.load(json_file)
...@@ -1180,10 +1402,10 @@ class Toolchain(QWidget): ...@@ -1180,10 +1402,10 @@ class Toolchain(QWidget):
self.toolbar = QToolBar() self.toolbar = QToolBar()
# loop_action = QAction( self.loop_button = QPushButton()
# QIcon("beat/editor/widgets/dataset_icon.png"), "&Loop", self self.loop_button.setToolTip("Loop")
# ) self.loop_button.setIcon(QIcon("beat/editor/widgets/dataset_icon.png"))
# loop_action.triggered.connect(lambda: self.add_block(BlockType.LOOP)) self.loop_button.clicked.connect(self.add_loop_block)
self.dataset_button = QPushButton() self.dataset_button = QPushButton()
self.dataset_button.setToolTip("Dataset") self.dataset_button.setToolTip("Dataset")
...@@ -1203,6 +1425,7 @@ class Toolchain(QWidget): ...@@ -1203,6 +1425,7 @@ class Toolchain(QWidget):
self.toolbar.addWidget(self.dataset_button) self.toolbar.addWidget(self.dataset_button)
self.toolbar.addWidget(self.block_button) self.toolbar.addWidget(self.block_button)
self.toolbar.addWidget(self.analyzer_button) self.toolbar.addWidget(self.analyzer_button)
self.toolbar.addWidget(self.loop_button)
self.toolbar.setOrientation(Qt.Vertical) self.toolbar.setOrientation(Qt.Vertical)
...@@ -1210,6 +1433,105 @@ class Toolchain(QWidget): ...@@ -1210,6 +1433,105 @@ class Toolchain(QWidget):
layout.addWidget(self.toolbar) layout.addWidget(self.toolbar)
layout.addWidget(self.view) 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): def update_channel_path(self, block, old_channel, new_channel):
# check if current block is synchronized on old_channel # check if current block is synchronized on old_channel
for connection in self.connections: for connection in self.connections:
...@@ -1329,6 +1651,11 @@ class Toolchain(QWidget): ...@@ -1329,6 +1651,11 @@ class Toolchain(QWidget):
self.block_button.setMenu(self.block_edit_menu) self.block_button.setMenu(self.block_edit_menu)
self.analyzer_button.setMenu(self.analyzer_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): def clear_space(self):
self.scene.clear() self.scene.clear()
self.scene.items().clear() self.scene.items().clear()
...@@ -1345,7 +1672,7 @@ class Toolchain(QWidget): ...@@ -1345,7 +1672,7 @@ class Toolchain(QWidget):
self.clear_space() self.clear_space()
# Get datasets, blocks, analyzers # Get datasets, blocks, analyzers, loops
for block_type in BlockType: for block_type in BlockType:
for block_item in self.json_object.get(block_type.value, {}): for block_item in self.json_object.get(block_type.value, {}):
block = Block( 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