236 lines
7.4 KiB
Python
236 lines
7.4 KiB
Python
from qtpy.QtWidgets import QUndoCommand
|
|
|
|
import logging
|
|
from copy import copy
|
|
from qtpy.QtCore import QPointF
|
|
|
|
from .canvas.flowgraph import FlowgraphScene
|
|
from .canvas.block import Block
|
|
from ...core.base import Element
|
|
|
|
log = logging.getLogger(f"grc.application.{__name__}")
|
|
|
|
|
|
# Movement, rotation, enable/disable/bypass, bus ports,
|
|
# change params, toggle type.
|
|
# Basically anything that's not cut/paste or new/delete
|
|
class ChangeStateAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene):
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init ChangeState")
|
|
self.old_states = []
|
|
self.old_params = []
|
|
self.new_states = []
|
|
self.new_params = []
|
|
self.scene = scene
|
|
self.g_blocks = scene.selected_blocks()
|
|
for g_block in self.g_blocks:
|
|
self.old_states.append(copy(g_block.core.states))
|
|
self.new_states.append(copy(g_block.core.states))
|
|
self.old_params.append(copy(g_block.core.params))
|
|
self.new_params.append(copy(g_block.core.params))
|
|
|
|
def redo(self):
|
|
for i in range(len(self.g_blocks)):
|
|
self.g_blocks[i].set_states(self.new_states[i])
|
|
self.g_blocks[i].core.params = (self.new_params[i])
|
|
self.scene.update()
|
|
|
|
def undo(self):
|
|
for i in range(len(self.g_blocks)):
|
|
self.g_blocks[i].set_states(self.old_states[i])
|
|
self.g_blocks[i].params = (self.old_params[i])
|
|
self.scene.update()
|
|
|
|
|
|
class RotateAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene, delta_angle: int):
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init RotateAction")
|
|
self.setText('Rotate')
|
|
self.g_blocks = scene.selected_blocks()
|
|
self.scene = scene
|
|
self.delta_angle = delta_angle
|
|
|
|
def redo(self):
|
|
self.scene.rotate_selected(self.delta_angle)
|
|
|
|
def undo(self):
|
|
self.scene.rotate_selected(-self.delta_angle)
|
|
|
|
|
|
class MoveAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene, diff: QPointF):
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init MoveAction")
|
|
self.setText('Move')
|
|
self.g_blocks = scene.selected_blocks()
|
|
self.scene = scene
|
|
self.x = diff.x()
|
|
self.y = diff.y()
|
|
for block in self.g_blocks:
|
|
block.core.states["coordinate"] = (block.x(), block.y())
|
|
self.first = True
|
|
|
|
# redo() is called when the MoveAction is first created.
|
|
# At this point, the item is already at the correct position.
|
|
# Therefore, do nothing.
|
|
def redo(self):
|
|
if self.first:
|
|
self.first = False
|
|
return
|
|
for g_block in self.g_blocks:
|
|
g_block.move(self.x, self.y)
|
|
self.scene.update()
|
|
|
|
def undo(self):
|
|
for g_block in self.g_blocks:
|
|
g_block.move(-self.x, -self.y)
|
|
self.scene.update()
|
|
|
|
|
|
class EnableAction(ChangeStateAction):
|
|
def __init__(self, scene: FlowgraphScene):
|
|
ChangeStateAction.__init__(self, scene)
|
|
log.debug("init EnableAction")
|
|
self.setText('Enable')
|
|
for i in range(len(self.g_blocks)):
|
|
self.new_states[i]['state'] = 'enabled'
|
|
|
|
|
|
class DisableAction(ChangeStateAction):
|
|
def __init__(self, scene: FlowgraphScene):
|
|
ChangeStateAction.__init__(self, scene)
|
|
log.debug("init DisableAction")
|
|
self.setText('Disable')
|
|
for i in range(len(self.g_blocks)):
|
|
self.new_states[i]['state'] = 'disabled'
|
|
|
|
|
|
class BypassAction(ChangeStateAction):
|
|
def __init__(self, scene: FlowgraphScene):
|
|
ChangeStateAction.__init__(self, scene)
|
|
log.debug("init BypassAction")
|
|
self.setText('Bypass')
|
|
for i in range(len(self.g_blocks)):
|
|
self.new_states[i]['state'] = 'bypassed'
|
|
|
|
|
|
# Change properties
|
|
# This can only be performed on one block at a time
|
|
class BlockPropsChangeAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene, c_block: Block):
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init BlockPropsChangeAction")
|
|
self.setText(f'{c_block.name} block: Change properties')
|
|
self.scene = scene
|
|
self.c_block = c_block
|
|
self.old_data = copy(c_block.old_data)
|
|
self.new_data = copy(c_block.export_data())
|
|
self.first = True
|
|
|
|
def redo(self):
|
|
if self.first:
|
|
self.first = False
|
|
return
|
|
try:
|
|
name = self.new_data['name']
|
|
except KeyError:
|
|
name = self.new_data['parameters']['id']
|
|
|
|
self.c_block.import_data(name, self.new_data['states'], self.new_data['parameters'])
|
|
self.c_block.rewrite()
|
|
self.c_block.validate()
|
|
self.c_block.gui.create_shapes_and_labels()
|
|
self.scene.update()
|
|
|
|
def undo(self):
|
|
try:
|
|
name = self.old_data['name']
|
|
except KeyError:
|
|
name = self.old_data['parameters']['id']
|
|
|
|
self.c_block.import_data(name, self.old_data['states'], self.old_data['parameters'])
|
|
self.c_block.rewrite()
|
|
self.c_block.validate()
|
|
self.c_block.gui.create_shapes_and_labels()
|
|
self.scene.update()
|
|
|
|
|
|
class BussifyAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene, direction: str): # direction is either "sink" or "source"
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init BussifyAction")
|
|
self.setText(f'Toggle bus {direction}')
|
|
self.scene = scene
|
|
self.direction = direction
|
|
self.g_blocks = scene.selected_blocks()
|
|
|
|
def bussify(self):
|
|
for g_block in self.g_blocks:
|
|
g_block.core.bussify(self.direction)
|
|
self.scene.update()
|
|
|
|
def redo(self):
|
|
self.bussify()
|
|
|
|
def undo(self):
|
|
self.bussify()
|
|
|
|
|
|
# Blocks and connections
|
|
class NewElementAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene, element: Element):
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init NewElementAction")
|
|
self.setText('New')
|
|
self.scene = scene
|
|
self.element = element
|
|
self.first = True
|
|
|
|
def redo(self):
|
|
if self.first:
|
|
self.first = False
|
|
return
|
|
|
|
if self.element.is_block:
|
|
self.scene.core.blocks.append(self.element)
|
|
elif self.element.is_connection:
|
|
self.scene.core.connections.add(self.element)
|
|
|
|
self.scene.addItem(self.element.gui)
|
|
self.scene.update()
|
|
|
|
def undo(self):
|
|
self.scene.remove_element(self.element.gui)
|
|
self.scene.update()
|
|
|
|
|
|
class DeleteElementAction(QUndoCommand):
|
|
def __init__(self, scene: FlowgraphScene):
|
|
QUndoCommand.__init__(self)
|
|
log.debug("init DeleteElementAction")
|
|
self.setText('Delete')
|
|
self.scene = scene
|
|
self.g_connections = scene.selected_connections()
|
|
self.g_blocks = scene.selected_blocks()
|
|
for block in self.g_blocks:
|
|
for conn in block.core.connections():
|
|
self.g_connections = self.g_connections + [conn.gui]
|
|
|
|
def redo(self):
|
|
for con in self.g_connections:
|
|
self.scene.remove_element(con)
|
|
for block in self.g_blocks:
|
|
self.scene.remove_element(block)
|
|
self.scene.update()
|
|
|
|
def undo(self):
|
|
for block in self.g_blocks:
|
|
self.scene.core.blocks.append(block.core)
|
|
self.scene.addItem(block)
|
|
for con in self.g_connections:
|
|
self.scene.core.connections.add(con.core)
|
|
self.scene.addItem(con)
|
|
self.scene.update()
|