From 8ab0fba67c3ba05400d12fc61deb2b0d7bd337f9 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 15 Jan 2026 22:53:47 -0400 Subject: [PATCH] Change Fit All to Fit Selection with Select All shortcut - F key now fits to selected nodes (or all if none selected) - A key selects all nodes - Workflow: drag-select nodes then F to zoom, or A then F for all - Updated help banner and context menu - Context menu now has Select All (A) and Fit Selection (F) Co-Authored-By: Claude Opus 4.5 --- src/cmdforge/gui/widgets/flow_graph.py | 57 ++++++++++++++++++-------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/cmdforge/gui/widgets/flow_graph.py b/src/cmdforge/gui/widgets/flow_graph.py index 4a767d5..f0ef37b 100644 --- a/src/cmdforge/gui/widgets/flow_graph.py +++ b/src/cmdforge/gui/widgets/flow_graph.py @@ -163,7 +163,8 @@ class FlowGraphWidget(QWidget): "Zoom: Scroll wheel | " "Select: Click or drag box | " "Edit: Double-click | " - "Fit All: F" + "Select All: A | " + "Fit Selection: F" ) self._help_banner.setStyleSheet(""" QLabel { @@ -294,25 +295,41 @@ class FlowGraphWidget(QWidget): # Clear selection self._graph.clear_selection() - def fit_all_nodes(self): - """Fit view to show all nodes.""" + def select_all_nodes(self): + """Select all nodes in the graph.""" if not self._graph: return all_nodes = self._graph.all_nodes() - if not all_nodes: - return - - # Select all, fit, then clear selection for node in all_nodes: node.set_selected(True) - self._graph.fit_to_selection() - self._graph.clear_selection() + + def fit_selection(self): + """Fit view to show selected nodes (or all if none selected).""" + if not self._graph: + return + + selected = self._graph.selected_nodes() + if not selected: + # No selection - fit all nodes + all_nodes = self._graph.all_nodes() + if not all_nodes: + return + for node in all_nodes: + node.set_selected(True) + self._graph.fit_to_selection() + self._graph.clear_selection() + else: + # Fit to current selection (don't clear it) + self._graph.fit_to_selection() def keyPressEvent(self, event: QKeyEvent): """Handle keyboard shortcuts.""" if event.key() == Qt.Key_F: - self.fit_all_nodes() + self.fit_selection() + event.accept() + elif event.key() == Qt.Key_A: + self.select_all_nodes() event.accept() else: super().keyPressEvent(event) @@ -324,10 +341,14 @@ class FlowGraphWidget(QWidget): QTimer.singleShot(100, self._show_help_banner) def eventFilter(self, obj, event): - """Filter events from the graph widget to catch F key and focus.""" - if event.type() == QEvent.KeyPress and event.key() == Qt.Key_F: - self.fit_all_nodes() - return True # Event handled + """Filter events from the graph widget to catch keyboard shortcuts.""" + if event.type() == QEvent.KeyPress: + if event.key() == Qt.Key_F: + self.fit_selection() + return True # Event handled + elif event.key() == Qt.Key_A: + self.select_all_nodes() + return True # Event handled elif event.type() == QEvent.Enter: # Show banner when mouse enters the graph area self._show_help_banner() @@ -372,8 +393,12 @@ class FlowGraphWidget(QWidget): """Show context menu.""" menu = QMenu(self._graph.widget) - fit_action = QAction("Fit All (F)", menu) - fit_action.triggered.connect(self.fit_all_nodes) + select_all_action = QAction("Select All (A)", menu) + select_all_action.triggered.connect(self.select_all_nodes) + menu.addAction(select_all_action) + + fit_action = QAction("Fit Selection (F)", menu) + fit_action.triggered.connect(self.fit_selection) menu.addAction(fit_action) menu.exec_(self._graph.widget.mapToGlobal(pos))