From 66df5c1da06068049b5402e349a09213ed04d058 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Tue, 21 Oct 2025 22:18:55 +0200 Subject: [PATCH] Fix for page selection actions move iages between pages --- pyPhotoAlbum/gl_widget.py | 132 +++++++++++++++++++++++++++++++++----- pyPhotoAlbum/main.py | 2 +- 2 files changed, 117 insertions(+), 17 deletions(-) diff --git a/pyPhotoAlbum/gl_widget.py b/pyPhotoAlbum/gl_widget.py index 4cb6755..d13f6fa 100644 --- a/pyPhotoAlbum/gl_widget.py +++ b/pyPhotoAlbum/gl_widget.py @@ -46,6 +46,9 @@ class GLWidget(QOpenGLWidget): self.is_panning = False self.initial_zoom_set = False # Track if we've set initial fit-to-screen zoom + # Current page tracking for operations that need to know which page to work on + self.current_page_index = 0 + # Enable mouse tracking self.setMouseTracking(True) @@ -380,6 +383,11 @@ class GLWidget(QOpenGLWidget): if self._check_ghost_page_click(x, y): return + # Update current_page_index based on where user clicked + page, page_index, renderer = self._get_page_at(x, y) + if page_index >= 0: + self.current_page_index = page_index + if len(self.selected_elements) == 1 and self.selected_element: if self.rotation_mode: # In rotation mode, start rotation @@ -487,15 +495,34 @@ class GLWidget(QOpenGLWidget): total_dy = (y - self.drag_start_pos[1]) / self.zoom_level self._resize_element(total_dx, total_dy) else: - total_dx = (x - self.drag_start_pos[0]) / self.zoom_level - total_dy = (y - self.drag_start_pos[1]) / self.zoom_level + # Check if mouse is over a different page (for cross-page dragging) + current_page, current_page_index, current_renderer = self._get_page_at(x, y) - new_x = self.drag_start_element_pos[0] + total_dx - new_y = self.drag_start_element_pos[1] + total_dy - - # Simply update position without page-specific snapping for now - # TODO: Find which page the element belongs to for proper snapping - self.selected_element.position = (new_x, new_y) + if current_page and hasattr(self.selected_element, '_parent_page'): + source_page = self.selected_element._parent_page + + # Check if we've crossed into a different page + if current_page is not source_page: + # 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 + 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) + else: + # No page detected or no parent page - update normally + 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) self.update() @@ -572,6 +599,29 @@ class GLWidget(QOpenGLWidget): self.pan_offset[1] += scroll_amount self.update() + def _get_page_at(self, x, y): + """ + Get the page at the given screen coordinates. + + Returns: + Tuple of (page, page_index, renderer) or (None, -1, None) if no page at coordinates + """ + if not hasattr(self, '_page_renderers') or not self._page_renderers: + return None, -1, None + + main_window = self.window() + if not hasattr(main_window, 'project') or not main_window.project.pages: + return None, -1, None + + # Check each page to find which one contains the coordinates + for renderer, page in self._page_renderers: + if renderer.is_point_in_page(x, y): + # Find the page index in the project's pages list + page_index = main_window.project.pages.index(page) + return page, page_index, renderer + + return None, -1, None + def _get_element_at(self, x, y): """Get the element at the given position across all pages""" if not hasattr(self, '_page_renderers') or not self._page_renderers: @@ -639,6 +689,48 @@ class GLWidget(QOpenGLWidget): return None + def _transfer_element_to_page(self, element, source_page, target_page, mouse_x, mouse_y, target_renderer): + """ + Transfer an element from one page to another during drag operation. + + Args: + element: The element to transfer + source_page: Source page object + target_page: Target page object + mouse_x, mouse_y: Current mouse position in screen coordinates + target_renderer: PageRenderer for the target page + """ + # Convert mouse position to target page coordinates + new_page_x, new_page_y = target_renderer.screen_to_page(mouse_x, mouse_y) + + # Get element size + elem_w, elem_h = element.size + + # Center the element on the mouse position + new_x = new_page_x - elem_w / 2 + new_y = new_page_y - elem_h / 2 + + # Remove element from source page + if element in source_page.layout.elements: + source_page.layout.elements.remove(element) + print(f"Removed element from page {source_page.page_number}") + + # Update element position to new page coordinates + element.position = (new_x, new_y) + + # Add element to target page + target_page.layout.add_element(element) + + # Update element's parent page reference + element._parent_page = target_page + element._page_renderer = target_renderer + + # Update drag start position and element position for continued dragging + self.drag_start_pos = (mouse_x, mouse_y) + self.drag_start_element_pos = element.position + + print(f"Transferred element to page {target_page.page_number} at ({new_x:.1f}, {new_y:.1f})") + def _resize_element(self, dx, dy): """Resize the element based on the resize handle""" if not self.selected_element or not self.resize_handle: @@ -1023,32 +1115,40 @@ class GLWidget(QOpenGLWidget): main_window = self.window() if hasattr(main_window, 'project') and main_window.project.pages: - # Add to first page for now - # TODO: Determine which page the drop occurred on - if main_window.project.pages: - current_page = main_window.project.pages[0] + # Detect which page the drop occurred on + target_page, page_index, page_renderer = self._get_page_at(x, y) + + if target_page and page_renderer: + # Update current_page_index + if page_index >= 0: + self.current_page_index = page_index + + # Convert screen coordinates to page-local coordinates + page_local_x, page_local_y = page_renderer.screen_to_page(x, y) try: asset_path = main_window.project.asset_manager.import_asset(image_path) new_image = ImageData( image_path=asset_path, - x=page_rel_x, - y=page_rel_y, + x=page_local_x, + y=page_local_y, width=img_width, height=img_height ) cmd = AddElementCommand( - current_page.layout, + target_page.layout, new_image, asset_manager=main_window.project.asset_manager ) main_window.project.history.execute(cmd) - print(f"Added new image to page 1 at ({page_rel_x:.1f}, {page_rel_y:.1f}): {asset_path}") + print(f"Added new image to page {page_index + 1} at ({page_local_x:.1f}, {page_local_y:.1f}): {asset_path}") except Exception as e: print(f"Error adding dropped image: {e}") + else: + print("Drop location not on any page") event.acceptProposedAction() self.update() diff --git a/pyPhotoAlbum/main.py b/pyPhotoAlbum/main.py index 9fc9567..f0bb659 100644 --- a/pyPhotoAlbum/main.py +++ b/pyPhotoAlbum/main.py @@ -64,7 +64,7 @@ class MainWindow( self._init_ui() # Add a sample page for demonstration - self._add_sample_page() + #self._add_sample_page() def _init_state(self): """Initialize shared application state"""