Add rename node and shortcut skeletons
This commit is contained in:
parent
63b1abb130
commit
ea3f528dda
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue