Coverage for pyPhotoAlbum/mixins/operations/zorder_ops.py: 92%
107 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-20 12:55 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-20 12:55 +0000
1"""
2Z-order operations mixin for pyPhotoAlbum
3"""
5from pyPhotoAlbum.decorators import ribbon_action
6from pyPhotoAlbum.commands import ChangeZOrderCommand
9class ZOrderOperationsMixin:
10 """Mixin providing z-order/layer control operations"""
12 @ribbon_action(
13 label="Bring to Front",
14 tooltip="Bring selected element to front",
15 tab="Arrange",
16 group="Order",
17 shortcut="Ctrl+Shift+]",
18 requires_selection=True,
19 )
20 def bring_to_front(self):
21 """Bring selected element to front (end of list)"""
22 if not self.gl_widget.selected_element:
23 return
25 current_page = self.get_current_page()
26 if not current_page:
27 return
29 element = self.gl_widget.selected_element
30 elements = current_page.layout.elements
32 if element not in elements:
33 return
35 old_index = elements.index(element)
36 new_index = len(elements) - 1
38 if old_index == new_index:
39 self.show_status("Element is already at front", 2000)
40 return
42 # Create and execute command
43 cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
44 self.project.history.execute(cmd)
46 self.update_view()
47 self.show_status("Brought element to front (Ctrl+Z to undo)", 2000)
48 print(f"Brought element to front: {old_index} → {new_index}")
50 @ribbon_action(
51 label="Send to Back",
52 tooltip="Send selected element to back",
53 tab="Arrange",
54 group="Order",
55 shortcut="Ctrl+Shift+[",
56 requires_selection=True,
57 )
58 def send_to_back(self):
59 """Send selected element to back (start of list)"""
60 if not self.gl_widget.selected_element:
61 return
63 current_page = self.get_current_page()
64 if not current_page:
65 return
67 element = self.gl_widget.selected_element
68 elements = current_page.layout.elements
70 if element not in elements:
71 return
73 old_index = elements.index(element)
74 new_index = 0
76 if old_index == new_index:
77 self.show_status("Element is already at back", 2000)
78 return
80 # Create and execute command
81 cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
82 self.project.history.execute(cmd)
84 self.update_view()
85 self.show_status("Sent element to back (Ctrl+Z to undo)", 2000)
86 print(f"Sent element to back: {old_index} → {new_index}")
88 @ribbon_action(
89 label="Bring Forward",
90 tooltip="Bring selected element forward one layer",
91 tab="Arrange",
92 group="Order",
93 shortcut="Ctrl+]",
94 requires_selection=True,
95 )
96 def bring_forward(self):
97 """Move selected element forward one position in list"""
98 if not self.gl_widget.selected_element:
99 return
101 current_page = self.get_current_page()
102 if not current_page:
103 return
105 element = self.gl_widget.selected_element
106 elements = current_page.layout.elements
108 if element not in elements:
109 return
111 old_index = elements.index(element)
112 new_index = old_index + 1
114 if new_index >= len(elements):
115 self.show_status("Element is already at front", 2000)
116 return
118 # Create and execute command
119 cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
120 self.project.history.execute(cmd)
122 self.update_view()
123 self.show_status("Brought element forward (Ctrl+Z to undo)", 2000)
124 print(f"Brought element forward: {old_index} → {new_index}")
126 @ribbon_action(
127 label="Send Backward",
128 tooltip="Send selected element backward one layer",
129 tab="Arrange",
130 group="Order",
131 shortcut="Ctrl+[",
132 requires_selection=True,
133 )
134 def send_backward(self):
135 """Move selected element backward one position in list"""
136 if not self.gl_widget.selected_element:
137 return
139 current_page = self.get_current_page()
140 if not current_page:
141 return
143 element = self.gl_widget.selected_element
144 elements = current_page.layout.elements
146 if element not in elements:
147 return
149 old_index = elements.index(element)
150 new_index = old_index - 1
152 if new_index < 0:
153 self.show_status("Element is already at back", 2000)
154 return
156 # Create and execute command
157 cmd = ChangeZOrderCommand(current_page.layout, element, old_index, new_index)
158 self.project.history.execute(cmd)
160 self.update_view()
161 self.show_status("Sent element backward (Ctrl+Z to undo)", 2000)
162 print(f"Sent element backward: {old_index} → {new_index}")
164 @ribbon_action(
165 label="Swap Order",
166 tooltip="Swap z-order of two selected elements",
167 tab="Arrange",
168 group="Order",
169 shortcut="Ctrl+Shift+X",
170 requires_selection=True,
171 min_selection=2,
172 )
173 def swap_order(self):
174 """Swap the z-order of two selected elements"""
175 if len(self.gl_widget.selected_elements) != 2:
176 self.show_status("Please select exactly 2 elements to swap", 2000)
177 return
179 current_page = self.get_current_page()
180 if not current_page:
181 return
183 elements = current_page.layout.elements
184 selected = list(self.gl_widget.selected_elements)
186 # Get indices of both elements
187 try:
188 index1 = elements.index(selected[0])
189 index2 = elements.index(selected[1])
190 except ValueError:
191 self.show_status("Selected elements not found on current page", 2000)
192 return
194 # Swap them in the list
195 elements[index1], elements[index2] = elements[index2], elements[index1]
197 self.update_view()
198 self.show_status(f"Swapped z-order of elements", 2000)
199 print(f"Swapped elements at indices {index1} and {index2}")