Duncan Tourolle 5257c6654a
All checks were successful
Python CI / test (push) Successful in 55s
Lint / lint (push) Successful in 1m4s
Tests / test (3.10) (push) Successful in 42s
Tests / test (3.11) (push) Successful in 45s
Tests / test (3.9) (push) Successful in 41s
Improved undo-redo system
2025-10-28 21:03:30 +01:00

200 lines
6.3 KiB
Python

"""
Z-order operations mixin for pyPhotoAlbum
"""
from pyPhotoAlbum.decorators import ribbon_action
from pyPhotoAlbum.commands import ChangeZOrderCommand
class ZOrderOperationsMixin:
"""Mixin providing z-order/layer control operations"""
@ribbon_action(
label="Bring to Front",
tooltip="Bring selected element to front",
tab="Arrange",
group="Order",
shortcut="Ctrl+Shift+]",
requires_selection=True
)
def bring_to_front(self):
"""Bring selected element to front (end of list)"""
if not self.gl_widget.selected_element:
return
current_page = self.get_current_page()
if not current_page:
return
element = self.gl_widget.selected_element
elements = current_page.layout.elements
if element not in elements:
return
old_index = elements.index(element)
new_index = len(elements) - 1
if old_index == new_index:
self.show_status("Element is already at front", 2000)
return
# Create and execute command
cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
self.project.history.execute(cmd)
self.update_view()
self.show_status("Brought element to front (Ctrl+Z to undo)", 2000)
print(f"Brought element to front: {old_index}{new_index}")
@ribbon_action(
label="Send to Back",
tooltip="Send selected element to back",
tab="Arrange",
group="Order",
shortcut="Ctrl+Shift+[",
requires_selection=True
)
def send_to_back(self):
"""Send selected element to back (start of list)"""
if not self.gl_widget.selected_element:
return
current_page = self.get_current_page()
if not current_page:
return
element = self.gl_widget.selected_element
elements = current_page.layout.elements
if element not in elements:
return
old_index = elements.index(element)
new_index = 0
if old_index == new_index:
self.show_status("Element is already at back", 2000)
return
# Create and execute command
cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
self.project.history.execute(cmd)
self.update_view()
self.show_status("Sent element to back (Ctrl+Z to undo)", 2000)
print(f"Sent element to back: {old_index}{new_index}")
@ribbon_action(
label="Bring Forward",
tooltip="Bring selected element forward one layer",
tab="Arrange",
group="Order",
shortcut="Ctrl+]",
requires_selection=True
)
def bring_forward(self):
"""Move selected element forward one position in list"""
if not self.gl_widget.selected_element:
return
current_page = self.get_current_page()
if not current_page:
return
element = self.gl_widget.selected_element
elements = current_page.layout.elements
if element not in elements:
return
old_index = elements.index(element)
new_index = old_index + 1
if new_index >= len(elements):
self.show_status("Element is already at front", 2000)
return
# Create and execute command
cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
self.project.history.execute(cmd)
self.update_view()
self.show_status("Brought element forward (Ctrl+Z to undo)", 2000)
print(f"Brought element forward: {old_index}{new_index}")
@ribbon_action(
label="Send Backward",
tooltip="Send selected element backward one layer",
tab="Arrange",
group="Order",
shortcut="Ctrl+[",
requires_selection=True
)
def send_backward(self):
"""Move selected element backward one position in list"""
if not self.gl_widget.selected_element:
return
current_page = self.get_current_page()
if not current_page:
return
element = self.gl_widget.selected_element
elements = current_page.layout.elements
if element not in elements:
return
old_index = elements.index(element)
new_index = old_index - 1
if new_index < 0:
self.show_status("Element is already at back", 2000)
return
# Create and execute command
cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
self.project.history.execute(cmd)
self.update_view()
self.show_status("Sent element backward (Ctrl+Z to undo)", 2000)
print(f"Sent element backward: {old_index}{new_index}")
@ribbon_action(
label="Swap Order",
tooltip="Swap z-order of two selected elements",
tab="Arrange",
group="Order",
shortcut="Ctrl+Shift+X",
requires_selection=True,
min_selection=2
)
def swap_order(self):
"""Swap the z-order of two selected elements"""
if len(self.gl_widget.selected_elements) != 2:
self.show_status("Please select exactly 2 elements to swap", 2000)
return
current_page = self.get_current_page()
if not current_page:
return
elements = current_page.layout.elements
selected = list(self.gl_widget.selected_elements)
# Get indices of both elements
try:
index1 = elements.index(selected[0])
index2 = elements.index(selected[1])
except ValueError:
self.show_status("Selected elements not found on current page", 2000)
return
# Swap them in the list
elements[index1], elements[index2] = elements[index2], elements[index1]
self.update_view()
self.show_status(f"Swapped z-order of elements", 2000)
print(f"Swapped elements at indices {index1} and {index2}")