imagebaker 0.0.41__py3-none-any.whl → 0.0.48__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. imagebaker/__init__.py +1 -1
  2. imagebaker/core/__init__.py +0 -0
  3. imagebaker/core/configs/__init__.py +1 -0
  4. imagebaker/core/configs/configs.py +156 -0
  5. imagebaker/core/defs/__init__.py +1 -0
  6. imagebaker/core/defs/defs.py +258 -0
  7. imagebaker/core/plugins/__init__.py +0 -0
  8. imagebaker/core/plugins/base_plugin.py +39 -0
  9. imagebaker/core/plugins/cosine_plugin.py +39 -0
  10. imagebaker/layers/__init__.py +3 -0
  11. imagebaker/layers/annotable_layer.py +847 -0
  12. imagebaker/layers/base_layer.py +724 -0
  13. imagebaker/layers/canvas_layer.py +1007 -0
  14. imagebaker/list_views/__init__.py +3 -0
  15. imagebaker/list_views/annotation_list.py +203 -0
  16. imagebaker/list_views/canvas_list.py +185 -0
  17. imagebaker/list_views/image_list.py +138 -0
  18. imagebaker/list_views/layer_list.py +390 -0
  19. imagebaker/list_views/layer_settings.py +219 -0
  20. imagebaker/models/__init__.py +0 -0
  21. imagebaker/models/base_model.py +150 -0
  22. imagebaker/tabs/__init__.py +2 -0
  23. imagebaker/tabs/baker_tab.py +496 -0
  24. imagebaker/tabs/layerify_tab.py +837 -0
  25. imagebaker/utils/__init__.py +0 -0
  26. imagebaker/utils/image.py +105 -0
  27. imagebaker/utils/state_utils.py +92 -0
  28. imagebaker/utils/transform_mask.py +107 -0
  29. imagebaker/window/__init__.py +1 -0
  30. imagebaker/window/app.py +136 -0
  31. imagebaker/window/main_window.py +181 -0
  32. imagebaker/workers/__init__.py +3 -0
  33. imagebaker/workers/baker_worker.py +247 -0
  34. imagebaker/workers/layerify_worker.py +91 -0
  35. imagebaker/workers/model_worker.py +54 -0
  36. {imagebaker-0.0.41.dist-info → imagebaker-0.0.48.dist-info}/METADATA +6 -6
  37. imagebaker-0.0.48.dist-info/RECORD +41 -0
  38. {imagebaker-0.0.41.dist-info → imagebaker-0.0.48.dist-info}/WHEEL +1 -1
  39. imagebaker-0.0.41.dist-info/RECORD +0 -7
  40. {imagebaker-0.0.41.dist-info/licenses → imagebaker-0.0.48.dist-info}/LICENSE +0 -0
  41. {imagebaker-0.0.41.dist-info → imagebaker-0.0.48.dist-info}/entry_points.txt +0 -0
  42. {imagebaker-0.0.41.dist-info → imagebaker-0.0.48.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,3 @@
1
+ from .layer_list import LayerList # noqa
2
+ from .annotation_list import AnnotationList # noqa
3
+ from .layer_settings import LayerSettings # noqa
@@ -0,0 +1,203 @@
1
+ from PySide6.QtCore import QSize, Qt, Signal
2
+ from PySide6.QtGui import (
3
+ QColor,
4
+ QPixmap,
5
+ QIcon,
6
+ )
7
+ from PySide6.QtWidgets import (
8
+ QWidget,
9
+ QVBoxLayout,
10
+ QHBoxLayout,
11
+ QPushButton,
12
+ QLabel,
13
+ QSizePolicy,
14
+ QDockWidget,
15
+ QListWidget,
16
+ QListWidgetItem,
17
+ )
18
+
19
+ from imagebaker.layers.annotable_layer import AnnotableLayer
20
+ from imagebaker import logger
21
+
22
+
23
+ class AnnotationList(QDockWidget):
24
+ messageSignal = Signal(str)
25
+
26
+ def __init__(self, layer: AnnotableLayer, parent=None):
27
+ super().__init__("Annotations", parent)
28
+ self.layer = layer
29
+ self.init_ui()
30
+
31
+ def init_ui(self):
32
+ logger.info("Initializing AnnotationList")
33
+ self.setMinimumWidth(150)
34
+ self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
35
+
36
+ widget = QWidget()
37
+ layout = QVBoxLayout(widget)
38
+ self.list_widget = QListWidget()
39
+
40
+ # Set the size policy for the list widget to expand dynamically
41
+ self.list_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
42
+
43
+ layout.addWidget(self.list_widget)
44
+ self.setWidget(widget)
45
+ self.setFeatures(
46
+ QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable
47
+ )
48
+
49
+ def update_list(self):
50
+ self.list_widget.clear()
51
+ if self.layer is None:
52
+ return
53
+ for idx, ann in enumerate(self.layer.annotations):
54
+ item = QListWidgetItem(self.list_widget)
55
+
56
+ # Create container widget
57
+ widget = QWidget()
58
+ widget.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
59
+
60
+ layout = QHBoxLayout(widget)
61
+ layout.setContentsMargins(1, 1, 2, 2)
62
+
63
+ # on clicking this element, select the annotation
64
+ widget.mousePressEvent = lambda event, i=idx: self.on_annotation_selected(i)
65
+
66
+ widget.setCursor(Qt.PointingHandCursor)
67
+
68
+ # Color indicator
69
+ color_label = QLabel()
70
+ color = QColor(ann.color)
71
+ if not ann.visible:
72
+ color.setAlpha(128)
73
+ pixmap = QPixmap(20, 20)
74
+ pixmap.fill(ann.color)
75
+ color_label.setPixmap(pixmap)
76
+ layout.addWidget(color_label)
77
+
78
+ # Text container
79
+ text_container = QWidget()
80
+ text_layout = QVBoxLayout(text_container)
81
+ text_layout.setContentsMargins(0, 0, 0, 0)
82
+
83
+ # Main label with conditional color
84
+ main_label = QLabel(f"{ann.name}")
85
+ main_color = "#666" if not ann.visible else "black"
86
+ main_label.setStyleSheet(f"font-weight: bold; color: {main_color};")
87
+ text_layout.addWidget(main_label)
88
+
89
+ # Change the text color of the selected annotation
90
+ if ann.selected:
91
+ main_label.setStyleSheet("font-weight: bold; color: blue;")
92
+ else:
93
+ main_label.setStyleSheet(f"font-weight: bold; color: {main_color};")
94
+
95
+ # Secondary info
96
+ secondary_text = []
97
+ score_text = (
98
+ f"{ann.annotator}: {ann.score:.2f}"
99
+ if ann.score is not None
100
+ else ann.annotator
101
+ )
102
+ secondary_text.append(score_text)
103
+ short_path = ann.file_path.stem
104
+ secondary_text.append(f"<span style='color:#666;'>{short_path}</span>")
105
+
106
+ if secondary_text:
107
+ info_color = "#888" if not ann.visible else "#444"
108
+ info_label = QLabel("<br>".join(secondary_text))
109
+ info_label.setStyleSheet(f"color: {info_color}; font-size: 10px;")
110
+ text_layout.addWidget(info_label)
111
+
112
+ text_layout.addStretch()
113
+ layout.addWidget(text_container)
114
+ layout.addStretch()
115
+
116
+ # Buttons
117
+ btn_container = QWidget()
118
+ btn_layout = QHBoxLayout(btn_container)
119
+
120
+ layerify_btn = QPushButton("🖨")
121
+ layerify_btn.setFixedWidth(30)
122
+ layerify_btn.setToolTip("Make AnnotableLayer from annotation")
123
+ layerify_btn.clicked.connect(lambda _, i=idx: self.layerify_annotation(i))
124
+ btn_layout.addWidget(layerify_btn)
125
+
126
+ vis_btn = QPushButton("👀" if ann.visible else "👁️")
127
+ vis_btn.setFixedWidth(30)
128
+ vis_btn.setCheckable(True)
129
+ vis_btn.setChecked(ann.visible)
130
+ vis_btn.setToolTip("Visible" if ann.visible else "Hidden")
131
+ vis_btn.clicked.connect(lambda _, i=idx: self.toggle_visibility(i))
132
+ btn_layout.addWidget(vis_btn)
133
+
134
+ del_btn = QPushButton("🗑️")
135
+ del_btn.setFixedWidth(30)
136
+ del_btn.setToolTip("Delete annotation")
137
+ del_btn.clicked.connect(lambda _, i=idx: self.delete_annotation(i))
138
+ btn_layout.addWidget(del_btn)
139
+
140
+ layout.addWidget(btn_container)
141
+
142
+ item.setSizeHint(widget.sizeHint())
143
+ self.list_widget.setItemWidget(item, widget)
144
+ self.update()
145
+
146
+ def create_color_icon(self, color):
147
+ pixmap = QPixmap(16, 16)
148
+ pixmap.fill(color)
149
+ return QIcon(pixmap)
150
+
151
+ def on_annotation_selected(self, index):
152
+ if 0 <= index < len(self.layer.annotations):
153
+ ann = self.layer.annotations[index]
154
+ ann.selected = not ann.selected
155
+ # Set other annotations to not selected
156
+ for i, a in enumerate(self.layer.annotations):
157
+ if i != index:
158
+ a.selected = False
159
+ self.layer.update()
160
+ self.update_list()
161
+
162
+ def delete_annotation(self, index):
163
+ if 0 <= index < len(self.layer.annotations):
164
+ logger.info(f"Deleting annotation: {self.layer.annotations[index].label}")
165
+ del self.layer.annotations[index]
166
+ self.layer.update()
167
+ self.update_list()
168
+ logger.info("Annotation deleted")
169
+
170
+ def toggle_visibility(self, index):
171
+ if 0 <= index < len(self.layer.annotations):
172
+ ann = self.layer.annotations[index]
173
+ ann.visible = not ann.visible
174
+ self.layer.update()
175
+ self.update_list()
176
+ logger.info(f"Annotation visibility toggled: {ann.label}, {ann.visible}")
177
+
178
+ def layerify_annotation(self, index):
179
+ if 0 <= index < len(self.layer.annotations):
180
+ ann = self.layer.annotations[index]
181
+ logger.info(f"Layerifying annotation: {ann.label}")
182
+
183
+ self.update_list()
184
+ self.layer.layerify_annotation([ann])
185
+ self.layer.update()
186
+
187
+ def sizeHint(self):
188
+ """Calculate the preferred size based on the content."""
189
+ base_size = super().sizeHint()
190
+ content_width = self.list_widget.sizeHintForColumn(0) + 40 # Add padding
191
+ return QSize(max(base_size.width(), content_width), base_size.height())
192
+
193
+ def keyPressEvent(self, event):
194
+ key = event.key()
195
+ logger.info(f"Key pressed in AnnotationList: {key}")
196
+ if event.key() == Qt.Key_C and event.modifiers() == Qt.ControlModifier:
197
+ self.layer.copy_annotation()
198
+ elif event.key() == Qt.Key_V and event.modifiers() == Qt.ControlModifier:
199
+ self.layer.paste_annotation()
200
+ elif event.key() == Qt.Key_Delete:
201
+ self.delete_annotation(self.layer.selected_annotation_index)
202
+ else:
203
+ self.parentWidget().keyPressEvent(event)
@@ -0,0 +1,185 @@
1
+ from PySide6.QtCore import Qt, Signal
2
+ from PySide6.QtWidgets import (
3
+ QWidget,
4
+ QVBoxLayout,
5
+ QHBoxLayout,
6
+ QPushButton,
7
+ QLabel,
8
+ QSizePolicy,
9
+ QDockWidget,
10
+ QListWidget,
11
+ QListWidgetItem,
12
+ QInputDialog,
13
+ )
14
+ from functools import partial
15
+ from imagebaker.layers.canvas_layer import CanvasLayer
16
+ from imagebaker import logger
17
+
18
+
19
+ class CanvasList(QDockWidget):
20
+ canvasSelected = Signal(CanvasLayer)
21
+ canvasDeleted = Signal(CanvasLayer)
22
+ canvasAdded = Signal(CanvasLayer)
23
+
24
+ def __init__(self, canvases: list[CanvasLayer], parent=None):
25
+ """
26
+ :param canvases: List of CanvasLayer objects to display.
27
+ """
28
+ super().__init__("Canvas List", parent)
29
+ self.canvases = canvases
30
+ self.current_page = 0
31
+ self.canvases_per_page = 10
32
+ self.init_ui()
33
+
34
+ def init_ui(self):
35
+ """Initialize the UI for the canvas list panel."""
36
+ logger.info("Initializing CanvasList")
37
+ self.setMinimumWidth(150)
38
+ self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
39
+
40
+ widget = QWidget()
41
+ layout = QVBoxLayout(widget)
42
+
43
+ # Add "Create New Canvas" button
44
+ self.create_canvas_button = QPushButton("Create New Canvas")
45
+ self.create_canvas_button.clicked.connect(self.create_new_canvas)
46
+ layout.addWidget(self.create_canvas_button)
47
+
48
+ # Canvas list widget
49
+ self.list_widget = QListWidget()
50
+ self.list_widget.itemClicked.connect(self.handle_item_clicked)
51
+ layout.addWidget(self.list_widget)
52
+ # set first item as selected
53
+ if len(self.canvases) > 0:
54
+ self.list_widget.setCurrentRow(0)
55
+
56
+ # Pagination controls
57
+ pagination_layout = QHBoxLayout()
58
+ self.prev_page_btn = QPushButton("Prev")
59
+ self.prev_page_btn.clicked.connect(self.show_prev_page)
60
+ self.next_page_btn = QPushButton("Next")
61
+ self.next_page_btn.clicked.connect(self.show_next_page)
62
+ pagination_layout.addWidget(self.prev_page_btn)
63
+ pagination_layout.addWidget(self.next_page_btn)
64
+ layout.addLayout(pagination_layout)
65
+
66
+ # Pagination info
67
+ self.pagination_label = QLabel("Showing 0 of 0")
68
+ layout.addWidget(self.pagination_label)
69
+
70
+ self.setWidget(widget)
71
+ self.setFeatures(
72
+ QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable
73
+ )
74
+
75
+ self.update_canvas_list()
76
+
77
+ def create_new_canvas(self):
78
+ """Create a new canvas and emit the canvasAdded signal."""
79
+ canvas_idx = len(self.canvases) + 1
80
+ default_name = f"Canvas {canvas_idx}"
81
+
82
+ # Show input dialog to ask for canvas name
83
+ canvas_name, ok = QInputDialog.getText(
84
+ self, "New Canvas", "Enter canvas name:", text=default_name
85
+ )
86
+
87
+ # If the user cancels or provides an empty name, use the default name
88
+ if not ok or not canvas_name.strip():
89
+ canvas_name = default_name
90
+
91
+ # Create the new canvas
92
+ new_canvas = CanvasLayer(parent=self.parent())
93
+ new_canvas.layer_name = canvas_name # Assign the name to the canvas
94
+ self.canvases.append(new_canvas) # Add the new canvas to the list
95
+ self.canvasAdded.emit(
96
+ new_canvas
97
+ ) # Emit the signal to notify about the new canvas
98
+ self.update_canvas_list() # Refresh the canvas list
99
+
100
+ def show_next_page(self):
101
+ """Show the next page of canvases."""
102
+ if (self.current_page + 1) * self.canvases_per_page < len(self.canvases):
103
+ self.current_page += 1
104
+ self.update_canvas_list()
105
+
106
+ def show_prev_page(self):
107
+ """Show the previous page of canvases."""
108
+ if self.current_page > 0:
109
+ self.current_page -= 1
110
+ self.update_canvas_list()
111
+
112
+ def update_canvas_list(self):
113
+ """Update the canvas list with pagination."""
114
+ self.list_widget.clear()
115
+
116
+ canvases_list = list(self.canvases)
117
+
118
+ start_idx = self.current_page * self.canvases_per_page
119
+ end_idx = min(start_idx + self.canvases_per_page, len(canvases_list))
120
+
121
+ for idx, canvas in enumerate(canvases_list[start_idx:end_idx], start=start_idx):
122
+ item_widget = QWidget()
123
+ item_layout = QHBoxLayout(item_widget)
124
+ item_layout.setContentsMargins(5, 5, 5, 5)
125
+
126
+ # Thumbnail
127
+ thumbnail_label = QLabel()
128
+ thumbnail_pixmap = canvas.get_thumbnail().scaled(
129
+ 50, 50, Qt.KeepAspectRatio, Qt.SmoothTransformation
130
+ )
131
+ thumbnail_label.setPixmap(thumbnail_pixmap)
132
+ item_layout.addWidget(thumbnail_label)
133
+
134
+ # Canvas name
135
+ canvas_name = getattr(canvas, "layer_name", f"Canvas {idx + 1}")
136
+ name_label = QLabel(canvas_name)
137
+ name_label.setStyleSheet("font-weight: bold;")
138
+ item_layout.addWidget(name_label)
139
+
140
+ # Delete button
141
+ delete_button = QPushButton("Delete")
142
+ delete_button.setStyleSheet(
143
+ "background-color: red; color: white; font-weight: bold;"
144
+ )
145
+ delete_button.clicked.connect(partial(self.delete_canvas, canvas))
146
+ item_layout.addWidget(delete_button)
147
+
148
+ item_layout.addStretch()
149
+
150
+ # Add the custom widget to the list
151
+ list_item = QListWidgetItem(self.list_widget)
152
+ list_item.setSizeHint(item_widget.sizeHint())
153
+ self.list_widget.addItem(list_item)
154
+ self.list_widget.setItemWidget(list_item, item_widget)
155
+
156
+ # Store metadata for the canvas
157
+ list_item.setData(Qt.UserRole, canvas)
158
+
159
+ # Select the first item by default if it exists
160
+ if self.list_widget.count() > 0:
161
+ self.list_widget.setCurrentRow(0)
162
+ first_item = self.list_widget.item(0)
163
+ self.handle_item_clicked(first_item)
164
+
165
+ self.pagination_label.setText(
166
+ f"Showing {start_idx + 1} to {end_idx} of {len(canvases_list)}"
167
+ )
168
+ self.update()
169
+
170
+ def handle_item_clicked(self, item: QListWidgetItem):
171
+ """Handle item click and emit the canvasSelected signal."""
172
+ canvas = item.data(Qt.UserRole)
173
+ if canvas:
174
+ self.canvasSelected.emit(canvas)
175
+
176
+ def delete_canvas(self, canvas: CanvasLayer):
177
+ """Delete a canvas from the list."""
178
+ if canvas in self.canvases:
179
+ canvas.layers.clear()
180
+ logger.info(f"Deleting canvas: {canvas.layer_name}")
181
+ canvas.setVisible(False)
182
+ canvas.deleteLater()
183
+ self.canvases.remove(canvas)
184
+ self.canvasDeleted.emit(canvas)
185
+ self.update_canvas_list()
@@ -0,0 +1,138 @@
1
+ from imagebaker import logger
2
+
3
+
4
+ from PySide6.QtCore import Qt, Signal
5
+ from PySide6.QtGui import QPixmap
6
+ from PySide6.QtWidgets import (
7
+ QWidget,
8
+ QVBoxLayout,
9
+ QHBoxLayout,
10
+ QPushButton,
11
+ QLabel,
12
+ QSizePolicy,
13
+ QDockWidget,
14
+ QListWidget,
15
+ QListWidgetItem,
16
+ )
17
+ from pathlib import Path
18
+
19
+
20
+ class ImageListPanel(QDockWidget):
21
+ imageSelected = Signal(Path)
22
+
23
+ def __init__(
24
+ self,
25
+ image_entries: list["ImageEntry"],
26
+ processed_images: set[Path],
27
+ parent=None,
28
+ ):
29
+ """
30
+ :param image_entries: List of image paths to display.
31
+ :param processed_images: Set of image paths that have already been processed.
32
+ """
33
+ super().__init__("Image List", parent)
34
+ self.image_entries: list["ImageEntry"] = image_entries
35
+ self.processed_images = processed_images
36
+ self.current_page = 0
37
+ self.images_per_page = 10
38
+ self.init_ui()
39
+
40
+ def init_ui(self):
41
+ """Initialize the UI for the image list panel."""
42
+ logger.info("Initializing ImageListPanel")
43
+ self.setMinimumWidth(150)
44
+ self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
45
+
46
+ widget = QWidget()
47
+ layout = QVBoxLayout(widget)
48
+
49
+ # Image list widget
50
+ self.list_widget = QListWidget()
51
+ self.list_widget.itemClicked.connect(self.handle_item_clicked) # Connect signal
52
+ layout.addWidget(self.list_widget)
53
+
54
+ # Pagination controls
55
+ pagination_layout = QHBoxLayout()
56
+ self.prev_page_btn = QPushButton("Prev")
57
+ self.prev_page_btn.clicked.connect(self.show_prev_page)
58
+ self.next_page_btn = QPushButton("Next")
59
+ self.next_page_btn.clicked.connect(self.show_next_page)
60
+ pagination_layout.addWidget(self.prev_page_btn)
61
+ pagination_layout.addWidget(self.next_page_btn)
62
+ layout.addLayout(pagination_layout)
63
+
64
+ # Pagination info
65
+ self.pagination_label = QLabel("Showing 0 of 0")
66
+ layout.addWidget(self.pagination_label)
67
+
68
+ self.setWidget(widget)
69
+ self.setFeatures(
70
+ QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable
71
+ )
72
+
73
+ self.update_image_list(self.image_entries)
74
+
75
+ def show_next_page(self):
76
+ """Show the next page of images"""
77
+ if (self.current_page + 1) * self.images_per_page < len(self.image_entries):
78
+ self.current_page += 1
79
+ self.update_image_list(self.image_entries)
80
+
81
+ def show_prev_page(self):
82
+ """Show the previous page of images"""
83
+ if self.current_page > 0:
84
+ self.current_page -= 1
85
+ self.update_image_list(self.image_entries)
86
+
87
+ def update_image_list(self, image_entries):
88
+ """Update the image list with image paths and baked results."""
89
+ self.list_widget.clear()
90
+
91
+ for idx, image_entry in enumerate(image_entries):
92
+ item_widget = QWidget()
93
+ item_layout = QHBoxLayout(item_widget)
94
+ item_layout.setContentsMargins(5, 5, 5, 5)
95
+
96
+ # Generate thumbnail
97
+ thumbnail_label = QLabel()
98
+ if image_entry.is_baked_result:
99
+ thumbnail_pixmap = (
100
+ image_entry.data.get_thumbnail()
101
+ ) # Baked result thumbnail
102
+ name_label_text = f"Baked Result {idx + 1}"
103
+ else:
104
+ thumbnail_pixmap = QPixmap(str(image_entry.data)).scaled(
105
+ 50, 50, Qt.KeepAspectRatio, Qt.SmoothTransformation
106
+ )
107
+ name_label_text = Path(image_entry.data).name
108
+
109
+ thumbnail_label.setPixmap(thumbnail_pixmap)
110
+ item_layout.addWidget(thumbnail_label)
111
+
112
+ # Text for image
113
+ name_label = QLabel(name_label_text)
114
+ name_label.setStyleSheet("font-weight: bold;")
115
+ item_layout.addWidget(name_label)
116
+
117
+ item_layout.addStretch()
118
+
119
+ # Add the custom widget to the list
120
+ list_item = QListWidgetItem(self.list_widget)
121
+ list_item.setSizeHint(item_widget.sizeHint())
122
+ self.list_widget.addItem(list_item)
123
+ self.list_widget.setItemWidget(list_item, item_widget)
124
+
125
+ # Store metadata for the image
126
+ list_item.setData(Qt.UserRole, image_entry)
127
+ self.pagination_label.setText(
128
+ f"Showing {self.current_page * self.images_per_page + 1} to "
129
+ f"{min((self.current_page + 1) * self.images_per_page, len(image_entries))} "
130
+ f"of {len(image_entries)}"
131
+ )
132
+ self.update()
133
+
134
+ def handle_item_clicked(self, item: QListWidgetItem):
135
+ """Handle item click and emit the imageSelected signal."""
136
+ item_data = item.data(Qt.UserRole)
137
+ if item_data:
138
+ self.imageSelected.emit(item_data)