Duncan Tourolle 80d7d291f3
All checks were successful
Python CI / test (push) Successful in 1m31s
Lint / lint (push) Successful in 1m7s
Tests / test (3.11) (push) Successful in 1m43s
Tests / test (3.12) (push) Successful in 1m44s
Tests / test (3.13) (push) Successful in 1m38s
Tests / test (3.14) (push) Successful in 1m17s
Re-organised ribbons. Fixed bug in rendering.
2025-12-01 20:19:43 +01:00

145 lines
4.8 KiB
Python

"""
Edit operations mixin for pyPhotoAlbum
"""
from pyPhotoAlbum.decorators import ribbon_action
from pyPhotoAlbum.commands import DeleteElementCommand, RotateElementCommand
class EditOperationsMixin:
"""Mixin providing edit-related operations"""
@ribbon_action(label="Undo", tooltip="Undo last action (Ctrl+Z)", tab="Home", group="Edit", shortcut="Ctrl+Z")
def undo(self):
"""Undo last action"""
if self.project.history.undo():
self.update_view()
self.show_status("Undo successful", 2000)
print("Undo successful")
else:
self.show_status("Nothing to undo", 2000)
print("Nothing to undo")
@ribbon_action(
label="Redo", tooltip="Redo last action (Ctrl+Y or Ctrl+Shift+Z)", tab="Home", group="Edit", shortcut="Ctrl+Y"
)
def redo(self):
"""Redo last action"""
if self.project.history.redo():
self.update_view()
self.show_status("Redo successful", 2000)
print("Redo successful")
else:
self.show_status("Nothing to redo", 2000)
print("Nothing to redo")
@ribbon_action(
label="Delete",
tooltip="Delete selected element (Delete key)",
tab="Home",
group="Edit",
shortcut="Delete",
requires_selection=True,
)
def delete_selected_element(self):
"""Delete the currently selected element"""
if not self.require_selection(min_count=1):
return
current_page = self.get_current_page()
if not current_page:
return
# Delete the first selected element (for backward compatibility)
# In the future, we could delete all selected elements
selected_element = next(iter(self.gl_widget.selected_elements))
try:
cmd = DeleteElementCommand(current_page.layout, selected_element, asset_manager=self.project.asset_manager)
self.project.history.execute(cmd)
# Clear selection
self.gl_widget.selected_elements.clear()
# Update display
self.update_view()
self.show_status("Element deleted (Ctrl+Z to undo)", 2000)
print("Deleted selected element")
except Exception as e:
self.show_error("Error", f"Failed to delete element: {str(e)}")
print(f"Error deleting element: {e}")
@ribbon_action(
label="Rotate Left",
tooltip="Rotate selected element 90° counter-clockwise",
tab="Arrange",
group="Transform",
requires_selection=True,
)
def rotate_left(self):
"""Rotate selected element 90 degrees counter-clockwise"""
if not self.require_selection(min_count=1):
return
selected_element = next(iter(self.gl_widget.selected_elements))
old_rotation = selected_element.rotation
new_rotation = (old_rotation - 90) % 360
cmd = RotateElementCommand(selected_element, old_rotation, new_rotation)
self.project.history.execute(cmd)
self.update_view()
self.show_status(f"Rotated left (Ctrl+Z to undo)", 2000)
print(f"Rotated element left: {old_rotation}° → {new_rotation}°")
@ribbon_action(
label="Rotate Right",
tooltip="Rotate selected element 90° clockwise",
tab="Arrange",
group="Transform",
requires_selection=True,
)
def rotate_right(self):
"""Rotate selected element 90 degrees clockwise"""
if not self.require_selection(min_count=1):
return
selected_element = next(iter(self.gl_widget.selected_elements))
old_rotation = selected_element.rotation
new_rotation = (old_rotation + 90) % 360
cmd = RotateElementCommand(selected_element, old_rotation, new_rotation)
self.project.history.execute(cmd)
self.update_view()
self.show_status(f"Rotated right (Ctrl+Z to undo)", 2000)
print(f"Rotated element right: {old_rotation}° → {new_rotation}°")
@ribbon_action(
label="Reset Rotation",
tooltip="Reset selected element rotation to 0°",
tab="Arrange",
group="Transform",
requires_selection=True,
)
def reset_rotation(self):
"""Reset selected element rotation to 0 degrees"""
if not self.require_selection(min_count=1):
return
selected_element = next(iter(self.gl_widget.selected_elements))
old_rotation = selected_element.rotation
if old_rotation == 0:
self.show_status("Element already at 0°", 2000)
return
cmd = RotateElementCommand(selected_element, old_rotation, 0)
self.project.history.execute(cmd)
self.update_view()
self.show_status("Reset rotation to 0° (Ctrl+Z to undo)", 2000)
print(f"Reset element rotation: {old_rotation}° → 0°")