From ddcfada636e4797f36551ab35b5a92e30b60224d Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Tue, 28 Oct 2025 18:41:24 +0100 Subject: [PATCH] fix lack of snapping toggle --- pyPhotoAlbum/gl_widget.py | 57 +++++++++++++++++++--- pyPhotoAlbum/mixins/operations/view_ops.py | 55 +++++++++++++++++++++ 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/pyPhotoAlbum/gl_widget.py b/pyPhotoAlbum/gl_widget.py index bdbfc60..0cbbb2d 100644 --- a/pyPhotoAlbum/gl_widget.py +++ b/pyPhotoAlbum/gl_widget.py @@ -543,16 +543,29 @@ class GLWidget(QOpenGLWidget): # Transfer element to the new page self._transfer_element_to_page(self.selected_element, source_page, current_page, x, y, current_renderer) else: - # Same page - just update position normally + # Same page - update position with snapping total_dx = (x - self.drag_start_pos[0]) / self.zoom_level total_dy = (y - self.drag_start_pos[1]) / self.zoom_level new_x = self.drag_start_element_pos[0] + total_dx new_y = self.drag_start_element_pos[1] + total_dy - self.selected_element.position = (new_x, new_y) + # Apply snapping + main_window = self.window() + snap_sys = source_page.layout.snapping_system + page_size = source_page.layout.size + dpi = main_window.project.working_dpi + + snapped_pos = snap_sys.snap_position( + position=(new_x, new_y), + size=self.selected_element.size, + page_size=page_size, + dpi=dpi + ) + + self.selected_element.position = snapped_pos else: - # No page detected or no parent page - update normally + # No page detected or no parent page - update normally without snapping total_dx = (x - self.drag_start_pos[0]) / self.zoom_level total_dy = (y - self.drag_start_pos[1]) / self.zoom_level @@ -776,9 +789,41 @@ class GLWidget(QOpenGLWidget): if not self.resize_start_pos or not self.resize_start_size: return - # Use non-snap resize for now - # TODO: Implement page-aware snapping - self._resize_element_no_snap(dx, dy) + # Get the snapping system from the element's parent page + main_window = self.window() + if not hasattr(self.selected_element, '_parent_page'): + self._resize_element_no_snap(dx, dy) + return + + parent_page = self.selected_element._parent_page + snap_sys = parent_page.layout.snapping_system + + # Get page size + page_size = parent_page.layout.size + dpi = main_window.project.working_dpi + + # Apply snapping to resize + new_pos, new_size = snap_sys.snap_resize( + position=self.resize_start_pos, + size=self.resize_start_size, + dx=dx, + dy=dy, + resize_handle=self.resize_handle, + page_size=page_size, + dpi=dpi + ) + + # Apply the snapped values + self.selected_element.position = new_pos + self.selected_element.size = new_size + + # Ensure minimum size + min_size = 20 + w, h = self.selected_element.size + if w < min_size or h < min_size: + w = max(w, min_size) + h = max(h, min_size) + self.selected_element.size = (w, h) def _resize_element_no_snap(self, dx, dy): """Resize element without snapping""" diff --git a/pyPhotoAlbum/mixins/operations/view_ops.py b/pyPhotoAlbum/mixins/operations/view_ops.py index 8aa6b0e..7f0ebb2 100644 --- a/pyPhotoAlbum/mixins/operations/view_ops.py +++ b/pyPhotoAlbum/mixins/operations/view_ops.py @@ -287,3 +287,58 @@ class ViewOperationsMixin: self.update_view() self.show_status(f"Grid size: {new_grid_size:.1f}mm, Threshold: {new_threshold:.1f}mm", 2000) print(f"Updated grid settings - Size: {new_grid_size:.1f}mm, Threshold: {new_threshold:.1f}mm") + + # ===== Layout Tab Snapping Controls ===== + # These provide easy access to snapping features during layout work + + @ribbon_action( + label="Grid Snap", + tooltip="Enable/disable snapping to grid (Ctrl+G)", + tab="Layout", + group="Snapping", + shortcut="Ctrl+G" + ) + def layout_toggle_grid_snap(self): + """Toggle grid snapping (Layout tab)""" + self.toggle_grid_snap() + + @ribbon_action( + label="Edge Snap", + tooltip="Enable/disable snapping to page edges (Ctrl+E)", + tab="Layout", + group="Snapping", + shortcut="Ctrl+E" + ) + def layout_toggle_edge_snap(self): + """Toggle edge snapping (Layout tab)""" + self.toggle_edge_snap() + + @ribbon_action( + label="Guide Snap", + tooltip="Enable/disable snapping to guides", + tab="Layout", + group="Snapping" + ) + def layout_toggle_guide_snap(self): + """Toggle guide snapping (Layout tab)""" + self.toggle_guide_snap() + + @ribbon_action( + label="Show Grid", + tooltip="Toggle visibility of snap lines", + tab="Layout", + group="Snapping" + ) + def layout_toggle_snap_lines(self): + """Toggle snap lines visibility (Layout tab)""" + self.toggle_snap_lines() + + @ribbon_action( + label="Grid Settings...", + tooltip="Configure grid size and snap threshold", + tab="Layout", + group="Snapping" + ) + def layout_set_grid_size(self): + """Open grid settings dialog (Layout tab)""" + self.set_grid_size()