Coverage for pyPhotoAlbum/mixins/operations/element_ops.py: 91%

70 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-20 12:55 +0000

1""" 

2Element operations mixin for pyPhotoAlbum 

3""" 

4 

5from PyQt6.QtWidgets import QFileDialog 

6from pyPhotoAlbum.decorators import ribbon_action 

7from pyPhotoAlbum.models import ImageData, TextBoxData, PlaceholderData 

8from pyPhotoAlbum.commands import AddElementCommand 

9from pyPhotoAlbum.async_backend import get_image_dimensions 

10 

11 

12class ElementOperationsMixin: 

13 """Mixin providing element creation and manipulation operations""" 

14 

15 @ribbon_action( 

16 label="Image", tooltip="Add an image to the current page", tab="Insert", group="Media", requires_page=True 

17 ) 

18 def add_image(self): 

19 """Add an image to the current page""" 

20 if not self.require_page(): 

21 return 

22 

23 file_path, _ = QFileDialog.getOpenFileName( 

24 self, "Select Image", "", "Image Files (*.jpg *.jpeg *.png *.gif *.bmp *.tiff *.webp);;All Files (*)" 

25 ) 

26 

27 if not file_path: 

28 return 

29 

30 current_page = self.get_current_page() 

31 if not current_page: 

32 return 

33 

34 try: 

35 # Import asset to project 

36 asset_path = self.project.asset_manager.import_asset(file_path) 

37 

38 # Get dimensions using centralized utility (max 300px for UI display) 

39 full_asset_path = self.get_asset_full_path(asset_path) 

40 dimensions = get_image_dimensions(full_asset_path, max_size=300) 

41 if dimensions: 

42 img_width, img_height = dimensions 

43 else: 

44 # Fallback dimensions if image cannot be read 

45 img_width, img_height = 200, 150 

46 

47 # Create image element at center of page 

48 page_width_mm = current_page.layout.size[0] 

49 page_height_mm = current_page.layout.size[1] 

50 

51 # Center position 

52 x = (page_width_mm - img_width) / 2 

53 y = (page_height_mm - img_height) / 2 

54 

55 new_image = ImageData(image_path=asset_path, x=x, y=y, width=img_width, height=img_height) 

56 

57 # Add element using command pattern for undo/redo 

58 cmd = AddElementCommand(current_page.layout, new_image, asset_manager=self.project.asset_manager) 

59 self.project.history.execute(cmd) 

60 

61 self.update_view() 

62 self.show_status("Added image (Ctrl+Z to undo)", 2000) 

63 print(f"Added image to page {self.get_current_page_index() + 1}: {asset_path}") 

64 

65 except Exception as e: 

66 self.show_error("Error", f"Failed to add image: {str(e)}") 

67 print(f"Error adding image: {e}") 

68 

69 @ribbon_action( 

70 label="Text", tooltip="Add a text box to the current page", tab="Insert", group="Media", requires_page=True 

71 ) 

72 def add_text(self): 

73 """Add text to the current page""" 

74 if not self.require_page(): 

75 return 

76 

77 current_page = self.get_current_page() 

78 if not current_page: 

79 return 

80 

81 # Create text box element at center of page 

82 page_width_mm = current_page.layout.size[0] 

83 page_height_mm = current_page.layout.size[1] 

84 

85 text_width = 200 

86 text_height = 50 

87 

88 # Center position 

89 x = (page_width_mm - text_width) / 2 

90 y = (page_height_mm - text_height) / 2 

91 

92 new_text = TextBoxData(text_content="New Text", x=x, y=y, width=text_width, height=text_height) 

93 

94 current_page.layout.add_element(new_text) 

95 self.update_view() 

96 

97 print(f"Added text box to page {self.get_current_page_index() + 1}") 

98 

99 @ribbon_action( 

100 label="Placeholder", 

101 tooltip="Add a placeholder to the current page", 

102 tab="Insert", 

103 group="Media", 

104 requires_page=True, 

105 ) 

106 def add_placeholder(self): 

107 """Add a placeholder to the current page""" 

108 if not self.require_page(): 

109 return 

110 

111 current_page = self.get_current_page() 

112 if not current_page: 

113 return 

114 

115 # Create placeholder element at center of page 

116 page_width_mm = current_page.layout.size[0] 

117 page_height_mm = current_page.layout.size[1] 

118 

119 placeholder_width = 200 

120 placeholder_height = 150 

121 

122 # Center position 

123 x = (page_width_mm - placeholder_width) / 2 

124 y = (page_height_mm - placeholder_height) / 2 

125 

126 new_placeholder = PlaceholderData( 

127 placeholder_type="image", x=x, y=y, width=placeholder_width, height=placeholder_height 

128 ) 

129 

130 current_page.layout.add_element(new_placeholder) 

131 self.update_view() 

132 

133 print(f"Added placeholder to page {self.get_current_page_index() + 1}")