From d7c64c162119e0ca9c4e6dd0833550cccf4a9430 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 23 Dec 2025 14:55:03 -0400 Subject: [PATCH] feat: Add Delete key and undo/redo for preview changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Delete key shortcut to remove selected elements from preview - Make preview changes (move, resize, delete) undoable with Ctrl+Z - Use QTextCursor with beginEditBlock/endEditBlock for undoable updates - Add Delete Selected action to Edit menu 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/artifact_editor/gui.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/artifact_editor/gui.py b/src/artifact_editor/gui.py index ae4cfdd..927f716 100644 --- a/src/artifact_editor/gui.py +++ b/src/artifact_editor/gui.py @@ -18,7 +18,7 @@ from typing import Optional from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QThread, QRectF, QPointF, QSizeF from PyQt6.QtGui import ( QFont, QColor, QAction, QKeySequence, QSyntaxHighlighter, - QTextCharFormat, QPainter, QPen, QBrush + QTextCharFormat, QPainter, QPen, QBrush, QTextCursor ) from PyQt6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, @@ -1511,6 +1511,13 @@ class ArtifactEditorWindow(QMainWindow): redo_action.triggered.connect(self.code_editor.redo) edit_menu.addAction(redo_action) + edit_menu.addSeparator() + + delete_action = QAction("&Delete Selected", self) + delete_action.setShortcut(QKeySequence.StandardKey.Delete) + delete_action.triggered.connect(self._delete_selected_element) + edit_menu.addAction(delete_action) + # Templates menu (rebuilt when format changes) self.templates_menu = menubar.addMenu("&Templates") self._rebuild_templates_menu() @@ -2578,12 +2585,28 @@ class ArtifactEditorWindow(QMainWindow): def _on_svg_scene_changed(self): """Handle scene changes from the SVG manager (element moved, deleted, etc.).""" # Regenerate SVG from the scene and update code editor - # Block signals to prevent triggering a re-render + # Use undoable text replacement so Ctrl+Z works for preview changes new_svg = self.svg_selection.generate_svg() + + # Block signals to prevent triggering a re-render loop self.code_editor.blockSignals(True) - self.code_editor.setPlainText(new_svg) + + # Use QTextCursor to replace all text - this is undoable unlike setPlainText + cursor = self.code_editor.textCursor() + cursor.beginEditBlock() # Group as single undo operation + cursor.select(cursor.SelectionType.Document) + cursor.insertText(new_svg) + cursor.endEditBlock() + self.code_editor.blockSignals(False) + def _delete_selected_element(self): + """Delete the currently selected element in the SVG preview.""" + if hasattr(self, 'svg_selection') and self.svg_selection: + self.svg_selection.delete_selected() + # Update the elements list + self._update_elements_list() + def _on_svg_overlay_element_selected(self, element): """Handle element selection from overlay.""" if element is None: