Add rename node and shortcut skeletons

This commit is contained in:
Audrey 2022-11-17 13:50:24 -07:00
parent 63b1abb130
commit ea3f528dda
1 changed files with 51 additions and 20 deletions

View File

@ -8,9 +8,9 @@ from threading import Lock
import logging
from PySide6.QtCore import QRectF, QPointF, QTimeLine, QEasingCurve, QMarginsF, QTimer, Qt, QEvent
from PySide6.QtGui import QColor, QFont, QBrush, QPainterPath, QPen
from PySide6.QtGui import QColor, QFont, QBrush, QPainterPath, QPen, QAction, QShortcut
from PySide6.QtWidgets import QGraphicsItem, QGraphicsRectItem, QGraphicsSimpleTextItem, QHBoxLayout, QGraphicsScene, \
QGraphicsEllipseItem, QGraphicsSceneMouseEvent
QGraphicsEllipseItem, QGraphicsSceneMouseEvent, QMenu, QDialog, QVBoxLayout, QLineEdit, QInputDialog
import networkx
import pygraphviz
@ -111,6 +111,11 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
super().__init__(parent)
self._action_rename = QAction("Rename...")
self._action_rename.setShortcut("N")
self._action_rename.triggered.connect(self.rename_selected_node)
self.viewport().addAction(self._action_rename)
self.setScene(QGraphicsScene())
self.scene().selectionChanged.connect(self._on_selection_changed_internal)
self.current_group.am_subscribe(self._on_change_group)
@ -122,6 +127,7 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
self._layout_animation_controller.timeout.connect(self._layout_animation.stop)
self.setDragMode(QZoomableDraggableGraphicsView.ScrollHandDrag)
self.viewport().setCursor(Qt.CursorShape.ArrowCursor)
self.viewport().setContextMenuPolicy(Qt.ActionsContextMenu)
self._on_change_group(src='__init__')
@ -157,11 +163,14 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
self.current_group.am_event(focus=target)
def label(self, node: RelativeAtomOrGroup) -> str:
def label(self, node: RelativeAtomOrGroupOrExtern) -> str:
if node not in self._labels:
if isinstance(node, RelativeAtom):
self._labels[node] = str(node.atom)
elif isinstance(node, ExternNode):
self._labels[node] = "Out"
else:
assert isinstance(node, RelativeAtomGroup)
self._labels[node] = 'Unknown group'
funcs = {self.hg.kp.atom_to_function(atom) for atom in self.hg.atoms(node) if atom not in self.hg.frontier}
if len(funcs) == 1:
@ -333,7 +342,6 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
if edge_replacement is not None:
self.drop_target.edges[edge_replacement[1]] = self.drop_target.edges.pop(edge_replacement[0])
assert isinstance(model, RelativeAtomGroup)
for item in self.scene().selectedItems():
if isinstance(item, PropChartHG):
@ -341,10 +349,18 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
self._rekey_externs(item, self.drop_target)
self.drop_target.deemphasize()
self.drop_target._layout_marks()
self.drop_target.layout()
self.drop_target = None
self._layout(0)
def rename_selected_node(self):
if self.selected_node is None:
return
current_name = self._labels[self.selected_node]
text, confirmed = QInputDialog.getText(self, "Rename", "Rename node to:", QLineEdit.EchoMode.Normal, current_name)
if confirmed:
self._labels[self.selected_node] = text
self.qnodes[self.ug_reverse[self.selected_node]].layout()
# private interfaces
@ -552,11 +568,17 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
# qt overrides
def viewportEvent(self, event):
if event.type() == QEvent.Type.ContextMenu:
return False
return super().viewportEvent(event)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Z and not self.is_expanding:
self._layout_animation.start()
event.accept()
super().keyPressEvent(event)
else:
super().keyPressEvent(event)
def keyReleaseEvent(self, event):
if event.key() == Qt.Key_Z:
@ -615,14 +637,13 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
self.centerOn(qnode.center)
def _on_selection_changed(self, src=None, **kwargs):
if src == 'qt':
return
self._selection_event_occurring = True
self.scene().clearSelection()
for node in self.selected_nodes:
qnode = self.qnodes[self.ug_reverse[node]]
qnode.setSelected(True)
self._selection_event_occurring = False
if src != 'qt':
self._selection_event_occurring = True
self.scene().clearSelection()
for node in self.selected_nodes:
qnode = self.qnodes[self.ug_reverse[node]]
qnode.setSelected(True)
self._selection_event_occurring = False
def _on_selection_changed_internal(self):
if self.is_expanding:
@ -642,6 +663,9 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView):
for qedge in self.qedges:
qedge.update()
single = len(self.selected_nodes) == 1
self._action_rename.setVisible(single)
class AnimatableItem(QGraphicsItem):
def __init__(self, *args, **kwargs):
@ -708,6 +732,9 @@ class HGNode(AnimatableItem):
def set_agraph_node_properties(self, node: pygraphviz.Node):
raise NotImplementedError
def layout(self):
raise NotImplementedError
# private interfaces
def _animate_enter(self, value):
@ -756,7 +783,7 @@ class PropChart(QGraphicsItem):
super().__init__(parent)
self._layout_marks()
self.layout()
@property
def prop(self) -> Prop:
@ -864,9 +891,9 @@ class PropChartHG(HGNode, PropChart):
self.setX(v.x() - self.width / 2)
self.setY(v.y() - self.height / 2)
def _layout_marks(self):
def layout(self):
lbl_height = 20
super()._layout_marks()
self._layout_marks()
self.height += lbl_height
for obj in self.objects:
if obj is self.object_bg:
@ -967,15 +994,19 @@ class HGExtern(HGNode):
self.object_text = None
super().__init__(*args, **kwargs)
self._layout()
self.layout()
def layout(self):
self.objects.clear()
for item in list(self.childItems()):
self.scene().removeItem(item)
def _layout(self):
self.object_bg = QGraphicsEllipseItem(QRectF(-self.radius, -self.radius, self.radius*2, self.radius*2), self)
self.object_bg.setBrush(BOX_COLOR)
self.object_bg.setPen(QPen(BOX_BORDER_COLOR, BOX_BORDER_WIDTH))
self.objects.append(self.object_bg)
self.object_text = QGraphicsSimpleTextItem("Out", self)
self.object_text = QGraphicsSimpleTextItem(self.hgw.label(self.model), self)
self.object_text.setPos(-self.object_text.boundingRect().center())
self.object_text.setFont(TEXT_FONT)
self.objects.append(self.object_text)