Fix for page selection actions
Some checks failed
Lint / lint (push) Failing after 14s
Tests / test (3.11) (push) Has been cancelled
Tests / test (3.9) (push) Has been cancelled
Tests / test (3.10) (push) Has been cancelled

move iages between pages
This commit is contained in:
Duncan Tourolle 2025-10-21 22:18:55 +02:00
parent 46585228fd
commit 66df5c1da0
2 changed files with 117 additions and 17 deletions

View File

@ -46,6 +46,9 @@ class GLWidget(QOpenGLWidget):
self.is_panning = False self.is_panning = False
self.initial_zoom_set = False # Track if we've set initial fit-to-screen zoom 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 # Enable mouse tracking
self.setMouseTracking(True) self.setMouseTracking(True)
@ -380,6 +383,11 @@ class GLWidget(QOpenGLWidget):
if self._check_ghost_page_click(x, y): if self._check_ghost_page_click(x, y):
return 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 len(self.selected_elements) == 1 and self.selected_element:
if self.rotation_mode: if self.rotation_mode:
# In rotation mode, start rotation # In rotation mode, start rotation
@ -487,15 +495,34 @@ class GLWidget(QOpenGLWidget):
total_dy = (y - self.drag_start_pos[1]) / self.zoom_level total_dy = (y - self.drag_start_pos[1]) / self.zoom_level
self._resize_element(total_dx, total_dy) self._resize_element(total_dx, total_dy)
else: else:
total_dx = (x - self.drag_start_pos[0]) / self.zoom_level # Check if mouse is over a different page (for cross-page dragging)
total_dy = (y - self.drag_start_pos[1]) / self.zoom_level current_page, current_page_index, current_renderer = self._get_page_at(x, y)
new_x = self.drag_start_element_pos[0] + total_dx if current_page and hasattr(self.selected_element, '_parent_page'):
new_y = self.drag_start_element_pos[1] + total_dy source_page = self.selected_element._parent_page
# Simply update position without page-specific snapping for now # Check if we've crossed into a different page
# TODO: Find which page the element belongs to for proper snapping if current_page is not source_page:
self.selected_element.position = (new_x, new_y) # 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() self.update()
@ -572,6 +599,29 @@ class GLWidget(QOpenGLWidget):
self.pan_offset[1] += scroll_amount self.pan_offset[1] += scroll_amount
self.update() 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): def _get_element_at(self, x, y):
"""Get the element at the given position across all pages""" """Get the element at the given position across all pages"""
if not hasattr(self, '_page_renderers') or not self._page_renderers: if not hasattr(self, '_page_renderers') or not self._page_renderers:
@ -639,6 +689,48 @@ class GLWidget(QOpenGLWidget):
return None 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): def _resize_element(self, dx, dy):
"""Resize the element based on the resize handle""" """Resize the element based on the resize handle"""
if not self.selected_element or not self.resize_handle: if not self.selected_element or not self.resize_handle:
@ -1023,32 +1115,40 @@ class GLWidget(QOpenGLWidget):
main_window = self.window() main_window = self.window()
if hasattr(main_window, 'project') and main_window.project.pages: if hasattr(main_window, 'project') and main_window.project.pages:
# Add to first page for now # Detect which page the drop occurred on
# TODO: Determine which page the drop occurred on target_page, page_index, page_renderer = self._get_page_at(x, y)
if main_window.project.pages:
current_page = main_window.project.pages[0] 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: try:
asset_path = main_window.project.asset_manager.import_asset(image_path) asset_path = main_window.project.asset_manager.import_asset(image_path)
new_image = ImageData( new_image = ImageData(
image_path=asset_path, image_path=asset_path,
x=page_rel_x, x=page_local_x,
y=page_rel_y, y=page_local_y,
width=img_width, width=img_width,
height=img_height height=img_height
) )
cmd = AddElementCommand( cmd = AddElementCommand(
current_page.layout, target_page.layout,
new_image, new_image,
asset_manager=main_window.project.asset_manager asset_manager=main_window.project.asset_manager
) )
main_window.project.history.execute(cmd) 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: except Exception as e:
print(f"Error adding dropped image: {e}") print(f"Error adding dropped image: {e}")
else:
print("Drop location not on any page")
event.acceptProposedAction() event.acceptProposedAction()
self.update() self.update()

View File

@ -64,7 +64,7 @@ class MainWindow(
self._init_ui() self._init_ui()
# Add a sample page for demonstration # Add a sample page for demonstration
self._add_sample_page() #self._add_sample_page()
def _init_state(self): def _init_state(self):
"""Initialize shared application state""" """Initialize shared application state"""