1 """

2 Element operations mixin for pyPhotoAlbum

3 """

4

5 from PyQt6.QtWidgets import QFileDialog

6 from pyPhotoAlbum.decorators import ribbon_action

7 from pyPhotoAlbum.models import ImageData, TextBoxData, PlaceholderData

8 from pyPhotoAlbum.commands import AddElementCommand

9 from pyPhotoAlbum.async_backend import get_image_dimensions

10

11

12 class 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}")