mirror of
https://github.com/gnuradio/gnuradio-companion.git
synced 2025-12-10 15:57:35 -06:00
189 lines
6.4 KiB
Python
189 lines
6.4 KiB
Python
from __future__ import absolute_import, print_function
|
|
|
|
# Standard modules
|
|
import logging
|
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from ast import literal_eval
|
|
from qtpy import QtGui, QtCore, QtWidgets
|
|
from qtpy.QtCore import Qt
|
|
|
|
# Custom modules
|
|
from .canvas.block import Block
|
|
from .. import base
|
|
from .canvas.flowgraph import FlowgraphScene, Flowgraph
|
|
from .canvas.colors import LIGHT_FLOWGRAPH_BACKGROUND_COLOR, DARK_FLOWGRAPH_BACKGROUND_COLOR
|
|
|
|
from ...core.generator import Generator
|
|
|
|
# Logging
|
|
log = logging.getLogger(f"grc.application.{__name__}")
|
|
|
|
DEFAULT_MAX_X = 400
|
|
DEFAULT_MAX_Y = 300
|
|
|
|
|
|
class FlowgraphView(
|
|
QtWidgets.QGraphicsView, base.Component
|
|
): # added base.Component so it can see platform
|
|
def __init__(self, parent, platform, filename=None):
|
|
super(FlowgraphView, self).__init__()
|
|
self.setParent(parent)
|
|
self.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
|
|
|
self.setScene(FlowgraphScene(self, platform))
|
|
|
|
self.scalefactor = 0.8
|
|
self.scale(self.scalefactor, self.scalefactor)
|
|
|
|
self.setSceneRect(0, 0, DEFAULT_MAX_X, DEFAULT_MAX_Y)
|
|
if filename is not None:
|
|
self.readFile(filename)
|
|
else:
|
|
self.initEmpty()
|
|
|
|
self.fitInView(self.scene().sceneRect(), QtCore.Qt.KeepAspectRatio)
|
|
if self.app.theme == "dark":
|
|
self.setBackgroundBrush(QtGui.QBrush(DARK_FLOWGRAPH_BACKGROUND_COLOR))
|
|
else:
|
|
self.setBackgroundBrush(QtGui.QBrush(LIGHT_FLOWGRAPH_BACKGROUND_COLOR))
|
|
|
|
self.isPanning = False
|
|
self.mousePressed = False
|
|
|
|
self.setDragMode(self.RubberBandDrag)
|
|
|
|
self.generator = None
|
|
self.process = None
|
|
|
|
def createActions(self, actions):
|
|
log.debug("Creating actions")
|
|
|
|
def contextMenuEvent(self, event):
|
|
super(FlowgraphView, self).contextMenuEvent(event)
|
|
|
|
def createMenus(self, actions, menus):
|
|
log.debug("Creating menus")
|
|
|
|
def createToolbars(self, actions, toolbars):
|
|
log.debug("Creating toolbars")
|
|
|
|
def get_generator(self) -> Generator:
|
|
return self.generator
|
|
|
|
def process_is_done(self) -> bool:
|
|
if self.process is None:
|
|
return True
|
|
else:
|
|
return (False if self.process.returncode is None else True)
|
|
|
|
def readFile(self, filename):
|
|
tree = ET.parse(filename)
|
|
|
|
for xml_block in tree.findall("block"):
|
|
attrib = {}
|
|
params = []
|
|
block_key = xml_block.find("key").text
|
|
|
|
for param in xml_block.findall("param"):
|
|
key = param.find("key").text
|
|
value = param.find("value").text
|
|
if key.startswith("_"):
|
|
attrib[key] = literal_eval(value)
|
|
else:
|
|
params.append((key, value))
|
|
|
|
# Find block in tree so that we can pull out label
|
|
try:
|
|
block = self.platform.blocks[block_key]
|
|
|
|
new_block = Block(block_key, block.label, attrib, params)
|
|
self.scene.addItem(new_block)
|
|
self.newElement.emit(new_block)
|
|
except:
|
|
log.warning("Block '{}' was not found".format(block_key))
|
|
|
|
# This part no longer works now that we are using a Scene with GraphicsItems, but I'm sure there's still some way to do it
|
|
# bounds = self.scene.itemsBoundingRect()
|
|
# self.setSceneRect(bounds)
|
|
# self.fitInView(bounds)
|
|
|
|
def initEmpty(self):
|
|
self.setSceneRect(0, 0, DEFAULT_MAX_X, DEFAULT_MAX_Y)
|
|
|
|
def zoom(self, factor: float, anchor=QtWidgets.QGraphicsView.AnchorViewCenter):
|
|
new_scalefactor = self.scalefactor * factor
|
|
|
|
if new_scalefactor > 0.25 and new_scalefactor < 2.5:
|
|
self.scalefactor = new_scalefactor
|
|
self.setTransformationAnchor(anchor)
|
|
self.setResizeAnchor(anchor)
|
|
self.scale(factor, factor)
|
|
|
|
def zoomOriginal(self):
|
|
# TODO: Original scale factor as a constant?
|
|
self.zoom(0.8 / self.scalefactor)
|
|
|
|
def wheelEvent(self, event):
|
|
# TODO: Support multi touch drag and drop for scrolling through the view
|
|
if event.modifiers() == Qt.ControlModifier:
|
|
factor = 1.1 if event.angleDelta().y() > 0 else (1.0 / 1.1)
|
|
self.zoom(factor, anchor=QtWidgets.QGraphicsView.AnchorUnderMouse)
|
|
|
|
# if new_scalefactor > 0.25 and new_scalefactor < 2.5:
|
|
# self.scalefactor = new_scalefactor
|
|
# self.setTransformationAnchor(QtWidgets.QGraphicsView.NoAnchor)
|
|
# self.setResizeAnchor(QtWidgets.QGraphicsView.NoAnchor)
|
|
|
|
# old_pos = self.mapToScene(event.pos())
|
|
|
|
# self.scale(factor, factor)
|
|
# new_pos = self.mapToScene(event.pos())
|
|
|
|
# delta = new_pos - old_pos
|
|
# self.translate(delta.x(), delta.y())
|
|
|
|
elif event.modifiers() == Qt.ShiftModifier:
|
|
self.horizontalScrollBar().setValue(
|
|
self.horizontalScrollBar().value() - event.angleDelta().y())
|
|
else:
|
|
QtWidgets.QGraphicsView.wheelEvent(self, event)
|
|
|
|
def mousePressEvent(self, event):
|
|
if event.button() == Qt.LeftButton:
|
|
self.mousePressed = True
|
|
# This will pass the mouse move event to the scene
|
|
super(FlowgraphView, self).mousePressEvent(event)
|
|
|
|
def mouseMoveEvent(self, event):
|
|
if self.mousePressed and self.isPanning:
|
|
new_pos = event.pos()
|
|
diff = new_pos - self.dragPos
|
|
self.dragPos = new_pos
|
|
self.horizontalScrollBar().setValue(
|
|
self.horizontalScrollBar().value() - diff.x()
|
|
)
|
|
self.verticalScrollBar().setValue(
|
|
self.verticalScrollBar().value() - diff.y()
|
|
)
|
|
event.accept()
|
|
else:
|
|
# This will pass the mouse move event to the scene
|
|
super(FlowgraphView, self).mouseMoveEvent(event)
|
|
|
|
def mouseReleaseEvent(self, event):
|
|
if event.button() == Qt.LeftButton:
|
|
self.mousePressed = False
|
|
super(FlowgraphView, self).mouseReleaseEvent(event)
|
|
|
|
def keyPressEvent(self, event):
|
|
super(FlowgraphView, self).keyPressEvent(event)
|
|
|
|
def keyReleaseEvent(self, event):
|
|
super(FlowgraphView, self).keyPressEvent(event)
|
|
|
|
def mouseDoubleClickEvent(self, event):
|
|
# This will pass the double click event to the scene
|
|
super(FlowgraphView, self).mouseDoubleClickEvent(event)
|