diff --git a/typetapper/hierarchy_graph_view.py b/typetapper/hierarchy_graph_view.py index 5494f9c..2b3abcf 100644 --- a/typetapper/hierarchy_graph_view.py +++ b/typetapper/hierarchy_graph_view.py @@ -10,7 +10,7 @@ import logging from PySide6.QtCore import QRectF, QPointF, QTimeLine, QEasingCurve, QMarginsF, QTimer, Qt, QEvent from PySide6.QtGui import QColor, QFont, QBrush, QPainterPath, QPen, QAction, QShortcut from PySide6.QtWidgets import QGraphicsItem, QGraphicsRectItem, QGraphicsSimpleTextItem, QHBoxLayout, QGraphicsScene, \ - QGraphicsEllipseItem, QGraphicsSceneMouseEvent, QMenu, QDialog, QVBoxLayout, QLineEdit, QInputDialog + QGraphicsEllipseItem, QGraphicsSceneMouseEvent, QMenu, QDialog, QVBoxLayout, QLineEdit, QInputDialog, QMessageBox import networkx import pygraphviz @@ -115,10 +115,30 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView): self._action_rename.setShortcut("N") self._action_rename.triggered.connect(self.rename_selected_node) self.viewport().addAction(self._action_rename) - self._action_create = QAction("Create Group") + self._action_create = QAction("Create group") self._action_create.setShortcut("C") self._action_create.triggered.connect(self.new_group) self.viewport().addAction(self._action_create) + self._action_move_out = QAction("Move to parent group") + self._action_move_out.setShortcut("O") + self._action_move_out.triggered.connect(self.move_out) + self.viewport().addAction(self._action_move_out) + self._action_break = QAction("Break group") + self._action_break.setShortcut("B") + self._action_break.triggered.connect(self.break_group) + self.viewport().addAction(self._action_break) + self._action_nav_in = QAction("Navigate to selected") + self._action_nav_in.setShortcut("D") + self._action_nav_in.triggered.connect(self.navigate_in) + self.viewport().addAction(self._action_nav_in) + self._action_nav_out = QAction("Navigate to parent") + self._action_nav_out.setShortcut("U") + self._action_nav_out.triggered.connect(self.navigate_out) + self.viewport().addAction(self._action_nav_out) + self._action_delete = QAction("Remove") + self._action_delete.setShortcut("Delete") + self._action_delete.triggered.connect(self.delete_selected) + self.viewport().addAction(self._action_delete) self.setScene(QGraphicsScene()) self.scene().selectionChanged.connect(self._on_selection_changed_internal) @@ -378,6 +398,45 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView): self._layout(0) self.qnodes[self.ug_reverse[grp]].setSelected(True) + def move_out(self): + if self.current_group.parent is None: + QMessageBox.information(self, "Can't move to parent", "You are in the root group.") + return + + for model in self.selected_nodes: + if not isinstance(model, (RelativeAtom, RelativeAtomGroup)): + continue + self.hg.move_node_out(model) + + self._layout(0) + + def break_group(self): + for model in self.selected_nodes: + if not isinstance(model, RelativeAtomGroup): + continue + qnode = self.qnodes[self.ug_reverse[model]] + rect = qnode.boundingRect().translated(qnode.x(), qnode.y()) + for i, child in enumerate(model.children): + self._layouts[self.current_group.am_obj][child] = rand_point(rect, i) + self.hg.destroy_group(model) + + self._layout(0) + + def navigate_in(self): + if self.selected_node is None: + return + + self.navigate(self.selected_node) + + def navigate_out(self): + if self.current_group.am_obj is not self.hg.root_group: + self.current_group.am_obj = self.current_group.parent + self.current_group.am_event() + + def delete_selected(self): + self.faux_frontier.update(model for model in self.selected_nodes if isinstance(model, (RelativeAtom, RelativeAtomGroup))) + self._layout(0) + # private interfaces def _rekey_externs(self, old_qnode: 'PropChartHG', new_qnode: 'PropChartHG'): @@ -680,7 +739,13 @@ class HierarchicalGraphWidget(QZoomableDraggableGraphicsView): qedge.update() single = len(self.selected_nodes) == 1 + some = len(self.selected_nodes) >= 1 + hasgroup = any(isinstance(model, RelativeAtomGroup) for model in self.selected_nodes) self._action_rename.setVisible(single) + self._action_move_out.setVisible(some) + self._action_break.setVisible(hasgroup) + self._action_nav_in.setVisible(single) + self._action_delete.setVisible(some) class AnimatableItem(QGraphicsItem):