feat: Add Delete key and undo/redo for preview changes
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
a8cc90c128
commit
d7c64c1621
|
|
@ -18,7 +18,7 @@ from typing import Optional
|
||||||
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QThread, QRectF, QPointF, QSizeF
|
from PyQt6.QtCore import Qt, QTimer, pyqtSignal, QThread, QRectF, QPointF, QSizeF
|
||||||
from PyQt6.QtGui import (
|
from PyQt6.QtGui import (
|
||||||
QFont, QColor, QAction, QKeySequence, QSyntaxHighlighter,
|
QFont, QColor, QAction, QKeySequence, QSyntaxHighlighter,
|
||||||
QTextCharFormat, QPainter, QPen, QBrush
|
QTextCharFormat, QPainter, QPen, QBrush, QTextCursor
|
||||||
)
|
)
|
||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||||
|
|
@ -1511,6 +1511,13 @@ class ArtifactEditorWindow(QMainWindow):
|
||||||
redo_action.triggered.connect(self.code_editor.redo)
|
redo_action.triggered.connect(self.code_editor.redo)
|
||||||
edit_menu.addAction(redo_action)
|
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)
|
# Templates menu (rebuilt when format changes)
|
||||||
self.templates_menu = menubar.addMenu("&Templates")
|
self.templates_menu = menubar.addMenu("&Templates")
|
||||||
self._rebuild_templates_menu()
|
self._rebuild_templates_menu()
|
||||||
|
|
@ -2578,12 +2585,28 @@ class ArtifactEditorWindow(QMainWindow):
|
||||||
def _on_svg_scene_changed(self):
|
def _on_svg_scene_changed(self):
|
||||||
"""Handle scene changes from the SVG manager (element moved, deleted, etc.)."""
|
"""Handle scene changes from the SVG manager (element moved, deleted, etc.)."""
|
||||||
# Regenerate SVG from the scene and update code editor
|
# 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()
|
new_svg = self.svg_selection.generate_svg()
|
||||||
|
|
||||||
|
# Block signals to prevent triggering a re-render loop
|
||||||
self.code_editor.blockSignals(True)
|
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)
|
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):
|
def _on_svg_overlay_element_selected(self, element):
|
||||||
"""Handle element selection from overlay."""
|
"""Handle element selection from overlay."""
|
||||||
if element is None:
|
if element is None:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue