PyImageLabeling 1.0.0__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 (99) hide show
  1. PyImageLabeling/__init__.py +22 -0
  2. PyImageLabeling/config.json +289 -0
  3. PyImageLabeling/controller/Controller.py +25 -0
  4. PyImageLabeling/controller/Events.py +147 -0
  5. PyImageLabeling/controller/FileEvents.py +69 -0
  6. PyImageLabeling/controller/ImageEvents.py +32 -0
  7. PyImageLabeling/controller/LabelEvents.py +219 -0
  8. PyImageLabeling/controller/LabelingEvents.py +123 -0
  9. PyImageLabeling/controller/settings/ContourFillinSetting.py +93 -0
  10. PyImageLabeling/controller/settings/CoutourFillingApplyCancel.py +37 -0
  11. PyImageLabeling/controller/settings/EraserSetting.py +73 -0
  12. PyImageLabeling/controller/settings/LabelSetting.py +91 -0
  13. PyImageLabeling/controller/settings/MagicPenSetting.py +125 -0
  14. PyImageLabeling/controller/settings/OpacitySetting.py +66 -0
  15. PyImageLabeling/controller/settings/PaintBrushSetting.py +66 -0
  16. PyImageLabeling/icons/apply.png +0 -0
  17. PyImageLabeling/icons/asterisk-green.png +0 -0
  18. PyImageLabeling/icons/asterisk-red.png +0 -0
  19. PyImageLabeling/icons/back.png +0 -0
  20. PyImageLabeling/icons/border.png +0 -0
  21. PyImageLabeling/icons/cancel.png +0 -0
  22. PyImageLabeling/icons/cleaner.png +0 -0
  23. PyImageLabeling/icons/close.png +0 -0
  24. PyImageLabeling/icons/down.png +0 -0
  25. PyImageLabeling/icons/ellipse.png +0 -0
  26. PyImageLabeling/icons/eraser.png +0 -0
  27. PyImageLabeling/icons/filling.png +0 -0
  28. PyImageLabeling/icons/logoMAIA.png +0 -0
  29. PyImageLabeling/icons/magic.png +0 -0
  30. PyImageLabeling/icons/maia.png +0 -0
  31. PyImageLabeling/icons/maia1.png +0 -0
  32. PyImageLabeling/icons/maia3.ico +0 -0
  33. PyImageLabeling/icons/maia_icon.png +0 -0
  34. PyImageLabeling/icons/move.png +0 -0
  35. PyImageLabeling/icons/opacity.png +0 -0
  36. PyImageLabeling/icons/open_image.png +0 -0
  37. PyImageLabeling/icons/open_layer.png +0 -0
  38. PyImageLabeling/icons/paint.png +0 -0
  39. PyImageLabeling/icons/plus.png +0 -0
  40. PyImageLabeling/icons/polygon.png +0 -0
  41. PyImageLabeling/icons/rectangle.png +0 -0
  42. PyImageLabeling/icons/reset.png +0 -0
  43. PyImageLabeling/icons/save.png +0 -0
  44. PyImageLabeling/icons/setting.png +0 -0
  45. PyImageLabeling/icons/transparency.png:Zone.Identifier +4 -0
  46. PyImageLabeling/icons/up.png +0 -0
  47. PyImageLabeling/icons/visibility.png +0 -0
  48. PyImageLabeling/icons/zoom_minus.png +0 -0
  49. PyImageLabeling/icons/zoom_plus.png +0 -0
  50. PyImageLabeling/model/Core.py +795 -0
  51. PyImageLabeling/model/File/Files.py +166 -0
  52. PyImageLabeling/model/File/NextImage.py +36 -0
  53. PyImageLabeling/model/File/PreviousImage.py +19 -0
  54. PyImageLabeling/model/Image/MoveImage.py +32 -0
  55. PyImageLabeling/model/Image/ResetMoveZoomImage.py +16 -0
  56. PyImageLabeling/model/Image/ZoomMinus.py +25 -0
  57. PyImageLabeling/model/Image/ZoomPlus.py +16 -0
  58. PyImageLabeling/model/Labeling/ClearAll.py +22 -0
  59. PyImageLabeling/model/Labeling/ContourFilling.py +135 -0
  60. PyImageLabeling/model/Labeling/Ellipse.py +350 -0
  61. PyImageLabeling/model/Labeling/Eraser.py +131 -0
  62. PyImageLabeling/model/Labeling/MagicPen.py +131 -0
  63. PyImageLabeling/model/Labeling/PaintBrush.py +207 -0
  64. PyImageLabeling/model/Labeling/Polygon.py +279 -0
  65. PyImageLabeling/model/Labeling/Rectangle.py +248 -0
  66. PyImageLabeling/model/Labeling/Undo.py +12 -0
  67. PyImageLabeling/model/Model.py +40 -0
  68. PyImageLabeling/model/Utils.py +40 -0
  69. PyImageLabeling/old_version/label_rectangle_properties.json +6 -0
  70. PyImageLabeling/old_version/main.py +2073 -0
  71. PyImageLabeling/old_version/models/EraseSettingsDialog.py +51 -0
  72. PyImageLabeling/old_version/models/LabeledRectangle.py +80 -0
  73. PyImageLabeling/old_version/models/MagicSettingsDialog.py +119 -0
  74. PyImageLabeling/old_version/models/OverlayOpacityDialog.py +63 -0
  75. PyImageLabeling/old_version/models/PaintSettingsDialog.py +289 -0
  76. PyImageLabeling/old_version/models/PointItem.py +66 -0
  77. PyImageLabeling/old_version/models/ProcessWorker.py +52 -0
  78. PyImageLabeling/old_version/models/ZoomableGraphicsView.py +1214 -0
  79. PyImageLabeling/old_version/models/tools/ContourTool.py +279 -0
  80. PyImageLabeling/old_version/models/tools/EraserTool.py +290 -0
  81. PyImageLabeling/old_version/models/tools/MagicPenTool.py +199 -0
  82. PyImageLabeling/old_version/models/tools/OverlayTool.py +179 -0
  83. PyImageLabeling/old_version/models/tools/PaintTool.py +68 -0
  84. PyImageLabeling/old_version/models/tools/PolygonTool.py +786 -0
  85. PyImageLabeling/old_version/models/tools/RectangleTool.py +1036 -0
  86. PyImageLabeling/parameters.json +1 -0
  87. PyImageLabeling/style.css +611 -0
  88. PyImageLabeling/view/Builder.py +333 -0
  89. PyImageLabeling/view/QBackgroundItem.py +30 -0
  90. PyImageLabeling/view/QWidgets.py +10 -0
  91. PyImageLabeling/view/View.py +226 -0
  92. PyImageLabeling/view/ZoomableGraphicsView.py +91 -0
  93. PyImageLabeling/view/__init__.py +0 -0
  94. pyimagelabeling-1.0.0.dist-info/METADATA +55 -0
  95. pyimagelabeling-1.0.0.dist-info/RECORD +99 -0
  96. pyimagelabeling-1.0.0.dist-info/WHEEL +5 -0
  97. pyimagelabeling-1.0.0.dist-info/licenses/LICENCE +22 -0
  98. pyimagelabeling-1.0.0.dist-info/top_level.txt +2 -0
  99. pypi/publish_pypi.py +18 -0
@@ -0,0 +1,333 @@
1
+
2
+
3
+
4
+
5
+ from PyQt6.QtWidgets import QVBoxLayout, QWidget, QListWidget, QHBoxLayout, QPushButton, QStatusBar, QGroupBox, QLayout, QStackedLayout, QLabel, QScrollArea, QGridLayout, QProgressBar
6
+ from PyQt6.QtGui import QIcon
7
+ from PyQt6.QtCore import Qt, QSize, QRect
8
+ from PyImageLabeling.model.Utils import Utils
9
+
10
+ from PyImageLabeling.view.ZoomableGraphicsView import ZoomableGraphicsView
11
+
12
+ from PyImageLabeling.view.QWidgets import QBlanckWidget1, QSeparator1
13
+ import os
14
+
15
+ class Builder:
16
+
17
+ def __init__(self, view):
18
+ self.view = view
19
+
20
+ def build(self):
21
+
22
+ # Central widget
23
+ self.view.central_widget = QWidget()
24
+ self.view.setCentralWidget(self.view.central_widget)
25
+ self.view.main_layout = QGridLayout(self.view.central_widget)
26
+ self.view.main_layout.setSpacing(0)
27
+ self.build_labeling_bar()
28
+ self.build_graphics_view()
29
+ self.build_label_bar()
30
+ self.build_image_bar()
31
+ self.build_file_bar()
32
+ self.build_status_bar()
33
+
34
+ #self.build_apply_cancel_bar()
35
+
36
+ # def build_apply_cancel_bar(self):
37
+ # self.apply_cancel_bar_container = QWidget()
38
+ # apply_cancel_bar_layout = QHBoxLayout(self.apply_cancel_bar_container)
39
+
40
+ # for button in self.view.config["apply_cancel_bar"]:
41
+ # button_name = button["name"]
42
+ # self.view.buttons_apply_cancel_bar[button_name] = QPushButton()
43
+ # self.view.buttons_apply_cancel_bar[button_name].setToolTip(button["tooltip"]) # Detailed tooltip
44
+ # self.view.buttons_apply_cancel_bar[button_name].setObjectName("permanent")
45
+ # icon_path = Utils.get_icon_path(button["icon"])
46
+ # if os.path.exists(icon_path):
47
+ # self.view.buttons_apply_cancel_bar[button_name].setIcon(QIcon(icon_path))
48
+ # self.view.buttons_apply_cancel_bar[button_name].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
49
+ # self.view.buttons_apply_cancel_bar[button_name].clicked.connect(getattr(self.view.controller, button["name"]))
50
+ # self.view.buttons_apply_cancel_bar[button_name].setCheckable(button["checkable"])
51
+
52
+ # apply_cancel_bar_layout.addWidget(self.view.buttons_apply_cancel_bar[button_name])
53
+ # self.apply_cancel_bar_container.setGeometry(QRect(0, 0, 200, 220))
54
+ # self.view.main_layout.addWidget(self.apply_cancel_bar_container)
55
+
56
+ def build_status_bar(self):
57
+ self.view.statusBar().showMessage('Ready')
58
+ self.view.progressBar = QProgressBar()
59
+ self.view.statusBar().addPermanentWidget(self.view.progressBar)
60
+
61
+ def build_file_bar(self):
62
+ self.view.file_bar_container = QWidget()
63
+ self.view.file_bar_layout = QVBoxLayout(self.view.file_bar_container)
64
+ self.file_bar_scroll = QScrollArea()
65
+ self.file_bar_button_container = QWidget()
66
+ self.file_bar_button_container.setObjectName("file_bar")
67
+
68
+ self.file_bar_button_layout = QHBoxLayout(self.file_bar_button_container)
69
+
70
+ for button in self.view.config["file_bar"]:
71
+ button_name = button["name"]
72
+ self.view.buttons_file_bar[button_name] = QPushButton()
73
+ self.view.buttons_file_bar[button_name].setToolTip(button["tooltip"]) # Detailed tooltip
74
+ self.view.buttons_file_bar[button_name].setObjectName("permanent")
75
+ icon_path = Utils.get_icon_path(button["icon"])
76
+ if os.path.exists(icon_path):
77
+ self.view.buttons_file_bar[button_name].setIcon(QIcon(icon_path))
78
+ self.view.buttons_file_bar[button_name].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
79
+ self.view.buttons_file_bar[button_name].clicked.connect(getattr(self.view.controller, button["name"]))
80
+ self.view.buttons_file_bar[button_name].setCheckable(button["checkable"])
81
+ if 'previous' in button_name or 'next' in button_name or 'save' in button_name:
82
+ self.view.buttons_file_bar[button_name].setEnabled(False)
83
+
84
+ self.file_bar_button_layout.addWidget(self.view.buttons_file_bar[button_name])
85
+ self.view.file_bar_layout.addWidget(self.file_bar_button_container)
86
+ self.file_bar_button_layout.setAlignment(Qt.AlignmentFlag.AlignLeft)
87
+
88
+ self.view.file_bar_list = QListWidget()
89
+ self.view.file_bar_list.itemSelectionChanged.connect(self.view.file_bar_select)
90
+ #self.view.file_bar_list.itemClicked.connect(self.view.controller.on_file_double_clicked)
91
+ """
92
+ self.file_bar_list.addItem("un tres llllllllllllllllllllllllloooooooooooooooooonnnnnnnnnnnnnnnnnnnng fichier.png")
93
+ for i in range(100):
94
+ self.file_bar_list.addItem("file_"+str(i)+".png")
95
+ """
96
+ self.view.file_bar_list.setMinimumWidth(0)
97
+
98
+ self.view.file_bar_layout.addWidget(self.view.file_bar_list)
99
+ self.view.file_bar_layout.setSpacing(0)
100
+ self.view.file_bar_layout.setContentsMargins(0,0,0,self.view.config["window_size"]["margin"])
101
+
102
+ self.view.file_bar_container.setMinimumWidth(self.view.config["window_size"]["file_bar"]["width"])
103
+ self.view.file_bar_container.setMaximumWidth(self.view.config["window_size"]["file_bar"]["width"])
104
+
105
+ self.view.main_layout.addWidget(self.view.file_bar_container, 0, 3, 2, 1)
106
+
107
+ def build_labeling_bar(self):
108
+ self.labeling_bar_container = QWidget()
109
+
110
+ labeling_bar_layout = QVBoxLayout(self.labeling_bar_container)
111
+ #left_layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
112
+
113
+ setting_buttons = {}
114
+ for category in self.view.config["labeling_bar_setting"]:
115
+ category_name = tuple(category.keys())[0]
116
+ if "Setting" in category_name:
117
+ for button in category[category_name]:
118
+ # Extract the base name (remove "_setting" suffix)
119
+ base_name = button["name"].replace("_setting", "")
120
+ setting_buttons[base_name] = button
121
+
122
+ for category_key in self.view.config["labeling_bar"].keys():
123
+ category = self.view.config["labeling_bar"][category_key]
124
+ category_name = category["name_view"]
125
+ frame = QGroupBox()
126
+ frame.setTitle(category_name)
127
+ buttons_layout = QVBoxLayout(frame)
128
+
129
+ for button in category["buttons"]:
130
+ button_name = button["name"]
131
+ self.view.buttons_labeling_bar[button_name] = QPushButton(button["name_view"])
132
+ self.view.buttons_labeling_bar[button_name].setToolTip(button["tooltip"]) # Detailed tooltip
133
+ icon_path = Utils.get_icon_path(button["icon"])
134
+ if os.path.exists(icon_path):
135
+ self.view.buttons_labeling_bar[button_name].setIcon(QIcon(icon_path))
136
+ self.view.buttons_labeling_bar[button_name].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
137
+ self.view.buttons_labeling_bar[button_name].clicked.connect(getattr(self.view.controller, button["name"]))
138
+ self.view.buttons_labeling_bar[button_name].setCheckable(button["checkable"])
139
+ self.view.buttons_labeling_bar[button_name].setEnabled(False)
140
+
141
+ if button_name in setting_buttons:
142
+ setting_button_config = setting_buttons[button_name]
143
+
144
+ # Create horizontal layout: tool button + setting button
145
+ h_layout = QHBoxLayout()
146
+ self.view.buttons_labeling_bar[button_name].setObjectName("with_parameters")
147
+ h_layout.addWidget(self.view.buttons_labeling_bar[button_name])
148
+
149
+ # Create setting button
150
+ setting_button_name = setting_button_config["name"]
151
+ self.view.buttons_labeling_bar[setting_button_name] = QPushButton()
152
+ self.view.buttons_labeling_bar[setting_button_name].setObjectName("setting_button")
153
+ self.view.buttons_labeling_bar[setting_button_name].setToolTip(setting_button_config["tooltip"])
154
+
155
+ setting_icon_path = Utils.get_icon_path(setting_button_config["icon"])
156
+ if os.path.exists(setting_icon_path):
157
+ self.view.buttons_labeling_bar[setting_button_name].setIcon(QIcon(setting_icon_path))
158
+ self.view.buttons_labeling_bar[setting_button_name].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
159
+
160
+ self.view.buttons_labeling_bar[setting_button_name].clicked.connect(getattr(self.view.controller, setting_button_name))
161
+ self.view.buttons_labeling_bar[setting_button_name].setCheckable(setting_button_config["checkable"])
162
+ self.view.buttons_labeling_bar[setting_button_name].setEnabled(False)
163
+
164
+ h_layout.setSpacing(0)
165
+ h_layout.addWidget(self.view.buttons_labeling_bar[setting_button_name])
166
+
167
+ buttons_layout.addLayout(h_layout)
168
+ else:
169
+ # No setting button, add main button directly
170
+ self.view.buttons_labeling_bar[button_name].setObjectName("without_parameters")
171
+ buttons_layout.addWidget(self.view.buttons_labeling_bar[button_name])
172
+
173
+ labeling_bar_layout.addWidget(frame)
174
+ self.labeling_bar_container.setMinimumWidth(self.view.config["window_size"]["labeling_bar"]["width"])
175
+ self.labeling_bar_container.setMaximumWidth(self.view.config["window_size"]["labeling_bar"]["width"])
176
+ labeling_bar_layout.setContentsMargins(0,0,0,self.view.config["window_size"]["margin"])
177
+ labeling_bar_layout.setSpacing(self.view.config["window_size"]["margin"])
178
+
179
+
180
+ labeling_bar_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
181
+ self.view.main_layout.addWidget(self.labeling_bar_container, 0, 0)
182
+
183
+
184
+ def build_graphics_view(self):
185
+ self.graphics_view_container = QWidget()
186
+ self.graphics_view_layout = QStackedLayout(self.graphics_view_container)
187
+
188
+
189
+ self.view.zoomable_graphics_view = ZoomableGraphicsView(self.view)
190
+ self.view.zoomable_graphics_view.setAlignment(Qt.AlignmentFlag.AlignLeft)
191
+ self.graphics_view_layout.addWidget(self.view.zoomable_graphics_view)
192
+
193
+ self.view.main_layout.addWidget(self.graphics_view_container, 0, 1, 2, 2)
194
+ self.graphics_view_container.setMinimumWidth(self.view.config["window_size"]["graphics_view"]["width"])
195
+
196
+ #self.right_layout_container.setMinimumSize(self.view.right_panel_width, self.view.right_panel_height)
197
+
198
+ def build_image_bar(self):
199
+ self.image_bar_container_1 = QWidget()
200
+
201
+ self.image_bar_container_1.setMinimumHeight(self.view.config["window_size"]["image_bar"]["height"])
202
+ self.image_bar_container_1.setMaximumHeight(self.view.config["window_size"]["image_bar"]["height"])
203
+
204
+ self.view.image_bar_layout_1 = QVBoxLayout(self.image_bar_container_1)
205
+
206
+ self.image_bar_container_2 = QWidget()
207
+ self.image_bar_container_2.setObjectName("image_bar")
208
+ self.view.image_bar_layout_1.addWidget(self.image_bar_container_2)
209
+ self.view.image_bar_layout_1.setContentsMargins(0,0,0,self.view.config["window_size"]["margin"])
210
+
211
+ self.view.image_bar_layout_1.setAlignment(Qt.AlignmentFlag.AlignRight)
212
+
213
+ self.view.image_bar_layout_2 = QVBoxLayout(self.image_bar_container_2)
214
+
215
+ self.image_bar_container_2.setMinimumWidth(self.view.config["window_size"]["image_bar"]["width"])
216
+ self.image_bar_container_2.setMaximumWidth(self.view.config["window_size"]["image_bar"]["width"])
217
+
218
+ for button in self.view.config["image_bar"]:
219
+ button_name = button["name"]
220
+ self.view.buttons_image_bar[button_name] = QPushButton()
221
+ self.view.buttons_image_bar[button_name].setObjectName("permanent")
222
+ self.view.buttons_image_bar[button_name].setToolTip(button["tooltip"])
223
+ icon_path = Utils.get_icon_path(button["icon"])
224
+ if os.path.exists(icon_path):
225
+ self.view.buttons_image_bar[button_name].setIcon(QIcon(icon_path))
226
+ self.view.buttons_image_bar[button_name].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
227
+ self.view.buttons_image_bar[button_name].clicked.connect(getattr(self.view.controller, button["name"]))
228
+ self.view.buttons_image_bar[button_name].setCheckable(button["checkable"])
229
+ self.view.buttons_image_bar[button_name].setEnabled(False)
230
+ self.view.image_bar_layout_2.addWidget(self.view.buttons_image_bar[button_name])
231
+
232
+ self.view.image_bar_layout_2.setAlignment(Qt.AlignmentFlag.AlignRight)
233
+ self.view.main_layout.addWidget(self.image_bar_container_1, 1, 0)
234
+
235
+ def build_label_bar(self):
236
+ self.label_bar_container = QWidget()
237
+ self.label_bar_scroll = QScrollArea()
238
+ self.label_bar_container.setObjectName("label_bar")
239
+ self.view.label_bar_layout = QHBoxLayout(self.label_bar_container)
240
+
241
+ self.view.label_bar_layout.addWidget(QBlanckWidget1())
242
+
243
+ for button in self.view.config["label_bar"]["permanent"]:
244
+ button_name = button["name"]
245
+ self.view.buttons_label_bar_permanent[button_name] = QPushButton()
246
+ self.view.buttons_label_bar_permanent[button_name].setObjectName("permanent")
247
+ self.view.buttons_label_bar_permanent[button_name].setToolTip(button["tooltip"])
248
+ self.view.buttons_label_bar_permanent[button_name].setCheckable(button["checkable"])
249
+ self.view.buttons_label_bar_permanent[button_name].setEnabled(False)
250
+
251
+ icon_path = Utils.get_icon_path(button["icon"])
252
+ if os.path.exists(icon_path):
253
+ self.view.buttons_label_bar_permanent[button_name].setIcon(QIcon(icon_path))
254
+ self.view.buttons_label_bar_permanent[button_name].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
255
+ self.view.buttons_label_bar_permanent[button_name].clicked.connect(getattr(self.view.controller, button["name"]))
256
+ self.view.label_bar_layout.addWidget(self.view.buttons_label_bar_permanent[button_name])
257
+
258
+ self.view.label_bar_layout.setContentsMargins(0,0,0,0)
259
+ self.view.label_bar_layout.setAlignment(Qt.AlignmentFlag.AlignLeft)
260
+
261
+ self.label_bar_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
262
+ self.label_bar_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
263
+ self.label_bar_scroll.setWidgetResizable(True)
264
+ self.label_bar_scroll.setWidget(self.label_bar_container)
265
+ self.label_bar_scroll.setMaximumHeight(self.view.config["window_size"]["label_bar"]["height"])
266
+
267
+
268
+
269
+ self.view.main_layout.addWidget(self.label_bar_scroll, 2, 0, 1, 4)
270
+
271
+
272
+
273
+
274
+ def build_new_layer_label_bar(self, label_id, name, labeling_mode, color):
275
+
276
+ push_buttons = dict() # Dictionnary of push buttons for this label
277
+
278
+ new_layer_label_bar_container = QWidget()
279
+ new_layer_label_bar_container.setObjectName("label_bar_new")
280
+
281
+ new_layer_label_bar_layout = QHBoxLayout(new_layer_label_bar_container)
282
+ new_layer_label_bar_layout.setContentsMargins(0,0,0,0)
283
+ new_layer_label_bar_layout.setSpacing(0)
284
+ new_layer_label_bar_layout.setSizeConstraint(QLayout.SizeConstraint.SetFixedSize)
285
+
286
+ # Activation button
287
+ push_buttons["activation"] = QPushButton(name)
288
+ push_buttons["activation"].setObjectName('activation')
289
+ push_buttons["activation"].setCheckable(True)
290
+ push_buttons["activation"].setChecked(True)
291
+ push_buttons["activation"].clicked.connect(lambda: self.view.controller.select_label(label_id))
292
+ new_layer_label_bar_layout.addWidget(push_buttons["activation"])
293
+ separator = QSeparator1()
294
+ self.view.label_bar_layout.addWidget(separator)
295
+
296
+ # The others buttons
297
+ for button in self.view.config["label_bar"]["layer"]:
298
+ type_name_button = button["name"]
299
+
300
+ push_buttons[type_name_button] = QPushButton()
301
+ push_buttons[type_name_button].setObjectName(button["name"])
302
+ push_buttons[type_name_button].setToolTip(button["tooltip"])
303
+ push_buttons[type_name_button].setCheckable(button["checkable"])
304
+
305
+ if type_name_button != "color":
306
+ icon_path = Utils.get_icon_path(button["icon"])
307
+ if os.path.exists(icon_path):
308
+ push_buttons[type_name_button].setIcon(QIcon(icon_path))
309
+ push_buttons[type_name_button].setIconSize(QSize(*self.view.config["window_size"]["icon"]))
310
+
311
+ if type_name_button == "color":
312
+ push_buttons[type_name_button].setStyleSheet(Utils.color_to_stylesheet(color))
313
+ push_buttons[type_name_button].clicked.connect(lambda: self.view.controller.color(label_id))
314
+
315
+ elif type_name_button == "visibility":
316
+ push_buttons[type_name_button].setChecked(True)
317
+ push_buttons[type_name_button].clicked.connect(lambda: self.view.controller.visibility(label_id))
318
+
319
+ elif type_name_button == "label_setting":
320
+ push_buttons[type_name_button].clicked.connect(lambda: self.view.controller.label_setting(label_id))
321
+
322
+ elif type_name_button == "remove_label":
323
+ push_buttons[type_name_button].clicked.connect(lambda: self.view.controller.remove_label(label_id))
324
+
325
+ new_layer_label_bar_layout.addWidget(push_buttons[type_name_button])
326
+
327
+
328
+ self.view.label_bar_layout.addWidget(new_layer_label_bar_container)
329
+
330
+ self.view.buttons_label_bar_temporary[label_id] = push_buttons # Usefull to control all buttons :)
331
+ self.view.container_label_bar_temporary[label_id] = (new_layer_label_bar_container, separator) # Usefull to delete these qwidget :)
332
+
333
+
@@ -0,0 +1,30 @@
1
+
2
+ from PyQt6.QtWidgets import QGraphicsItem
3
+ from PyQt6.QtGui import QColor
4
+
5
+
6
+ class QBackgroundItem(QGraphicsItem):
7
+ def __init__(self, rect, controller, alpha_color):
8
+ super().__init__()
9
+ self.rect = rect
10
+ self.controller = controller
11
+ self.background_color = QColor(*alpha_color)
12
+
13
+ def set_model(self, model):
14
+ self.model = model
15
+
16
+ def sceneEvent(self, event):
17
+ return self.controller.event_eater.eventFilter(event)
18
+
19
+ def boundingRect(self):
20
+ return self.rect
21
+
22
+ def set_background_color(self, background_color):
23
+ self.background_color = background_color
24
+ self.update()
25
+
26
+ def paint(self, painter, option, widget):
27
+ #painter.setPen(QColor(139,161,255))
28
+ #painter.drawRect(self.rect)
29
+ painter.fillRect(self.rect, self.background_color)
30
+
@@ -0,0 +1,10 @@
1
+ from PyQt6.QtWidgets import QWidget, QFrame
2
+
3
+ class QBlanckWidget1(QWidget):
4
+ def __init__(self):
5
+ super().__init__()
6
+
7
+ class QSeparator1(QFrame):
8
+ def __init__(self):
9
+ super().__init__()
10
+
@@ -0,0 +1,226 @@
1
+
2
+ from PyImageLabeling.view.Builder import Builder
3
+ from PyImageLabeling.model.Utils import Utils
4
+
5
+ from PyQt6.QtWidgets import QListWidget, QProgressDialog, QApplication, QMainWindow, QWidget, QHBoxLayout, QListWidgetItem, QLabel, QPushButton, QGraphicsItem, QGraphicsEllipseItem
6
+ from PyQt6.QtGui import QPixmap, QMouseEvent, QImage, QPainter, QColor, QPen, QBrush, QCursor, QIcon, QPainterPath, QFont
7
+ from PyQt6.QtCore import Qt, QPoint, QPointF, QTimer, QThread, pyqtSignal, QSize, QRectF, QObject, QLineF, QDateTime
8
+ from functools import partial
9
+ import os
10
+ import time
11
+
12
+ class View(QMainWindow):
13
+ def __init__(self, controller, config):
14
+
15
+ super().__init__()
16
+ # Parameters
17
+ self.controller = controller
18
+ self.config = config
19
+
20
+ #Components of the view
21
+ self.buttons_labeling_bar = dict()
22
+ self.buttons_label_bar_permanent = dict()
23
+ self.buttons_label_bar_temporary = dict()
24
+ self.buttons_image_bar = dict()
25
+ self.buttons_file_bar = dict()
26
+ self.buttons_apply_cancel_bar = dict()
27
+
28
+ self.container_label_bar_temporary = dict()
29
+
30
+ self.zoomable_graphics_view = None
31
+
32
+ self.file_bar_layout = None
33
+
34
+ # Set the main properties of the view
35
+ self.initialize()
36
+
37
+ # Build the components of the view
38
+ self.builder = Builder(self)
39
+ self.builder.build()
40
+
41
+ self.icon_asterisk_green = QPixmap(Utils.get_icon_path("asterisk-green"))
42
+ self.icon_asterisk_green = self.icon_asterisk_green.scaled(QSize(*self.config["window_size"]["icon_save_marker"]), aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio)
43
+
44
+ self.icon_asterisk_red = QPixmap(Utils.get_icon_path("asterisk-red"))
45
+ self.icon_asterisk_red = self.icon_asterisk_red.scaled(QSize(*self.config["window_size"]["icon_save_marker"]), aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio)
46
+
47
+ self.controller.set_view(self)
48
+
49
+
50
+ # Display
51
+ self.show()
52
+
53
+ # Here we are sure that clicked is checkable
54
+ def desactivate_buttons(self, clicked, list_buttons_bars):
55
+ for buttons_bar in list_buttons_bars:
56
+ for button in buttons_bar.keys():
57
+ # The button have not to be the same that clicked
58
+ # The button have to be checked
59
+ # The clicked button have to be checkable
60
+ #print("button:",button)
61
+ if button != clicked and buttons_bar[button].isChecked() is True:
62
+ buttons_bar[button].setChecked(False)
63
+ if button == clicked:
64
+ buttons_bar[button].setChecked(True)
65
+
66
+
67
+
68
+ def update_labeling_buttons(self, labeling_mode):
69
+ print("labeling_mode", labeling_mode)
70
+ category_key_selected = None
71
+ for category_key in self.config["labeling_bar"].keys():
72
+ category_name = self.config["labeling_bar"][category_key]["name_view"]
73
+ if category_name == labeling_mode:
74
+ category_key_selected = category_key
75
+ if category_key_selected is None:
76
+ raise ValueError("Bad category_key in the dictionnary `self.config[labeling_bar]` for " + str(labeling_mode)+ ".")
77
+
78
+ #print("ess:", self.buttons_labeling_bar)
79
+ #print("Labeling Type:", category_key_selected)
80
+
81
+ for button_key in self.buttons_labeling_bar.keys():
82
+ self.buttons_labeling_bar[button_key].setEnabled(False)
83
+
84
+ for config_buttons in self.config["labeling_bar"][category_key_selected]["buttons"]:
85
+ name = config_buttons["name"]
86
+ self.buttons_labeling_bar[name].setEnabled(True)
87
+ if name+"_setting" in self.buttons_labeling_bar.keys():
88
+ self.buttons_labeling_bar[name+"_setting"].setEnabled(True)
89
+
90
+ for config_buttons in self.config["labeling_bar"]["edit"]["buttons"]:
91
+ name = config_buttons["name"]
92
+ self.buttons_labeling_bar[name].setEnabled(True)
93
+ if name+"_setting" in self.buttons_labeling_bar.keys():
94
+ self.buttons_labeling_bar[name+"_setting"].setEnabled(True)
95
+
96
+ # exit(0)
97
+ # buttons = self.buttons_labeling_bar
98
+ # pixel_tools = ["contour_filling", "paintbrush", "magic_pen"]
99
+ # geometric_tools = ["ellipse", "rectangle", "polygon"]
100
+ # for button in buttons.items():
101
+ # if labeling_mode == "Geometric":
102
+ # for button in geometric_tools:
103
+ # self.buttons_labeling_bar[button].setEnabled(True)
104
+ # for button in pixel_tools:
105
+ # self.buttons_labeling_bar[button].setEnabled(False)
106
+ # elif labeling_mode == "Pixel":
107
+ # for button in pixel_tools:
108
+ # self.buttons_labeling_bar[button].setEnabled(True)
109
+ # for button in geometric_tools:
110
+ # self.buttons_labeling_bar[button].setEnabled(False)
111
+
112
+
113
+
114
+ def file_bar_add(self, current_file_paths):
115
+
116
+ item_widgets = []
117
+ for file in current_file_paths:
118
+
119
+ filename = os.path.basename(file)
120
+
121
+ # Create list item
122
+ item = QListWidgetItem()
123
+ item.file_path = file
124
+ item.filename = filename
125
+
126
+ self.file_bar_list.addItem(item)
127
+
128
+ # Create custom widget for the item
129
+ item_widget = QWidget()
130
+ item_widget.setObjectName("file_item")
131
+ item_layout = QHBoxLayout(item_widget)
132
+ item_layout.setContentsMargins(5, 2, 5, 2)
133
+
134
+ # The save marker
135
+ icon_button = QLabel()
136
+ icon_button.setPixmap(self.icon_asterisk_green)
137
+ icon_button.setObjectName("save_marker")
138
+ self.controller.model.icon_button_files[file] = icon_button
139
+
140
+ # File name label
141
+ file_label = QLabel(filename)
142
+ file_label.setObjectName("label_files")
143
+ file_label.setToolTip(filename) # Full filename as tooltip
144
+
145
+ # Remove button
146
+ remove_button = QPushButton("×")
147
+ remove_button.setToolTip("Remove file")
148
+ remove_button.setObjectName("remove_image_button")
149
+
150
+ # Connect remove button to removal function
151
+ remove_button.clicked.connect(partial(self.file_bar_remove, item, self.controller.model.file_paths, self.controller.model.image_items))
152
+
153
+ item_layout.addWidget(icon_button)
154
+ item_layout.addWidget(file_label)
155
+ item_layout.addWidget(remove_button)
156
+ item_widgets.append((item, item_widget))
157
+
158
+ for item, item_widget in item_widgets:
159
+ self.file_bar_list.setItemWidget(item, item_widget)
160
+
161
+
162
+ def file_bar_remove(self, item, loaded_image_paths, image_items):
163
+ # Get the row of the item
164
+ for path in loaded_image_paths:
165
+ if item.filename in path:
166
+ loaded_image_paths.remove(path)
167
+ del image_items[path]
168
+ row = self.file_bar_list.row(item)
169
+ if row >= 0:
170
+ # Remove the item from the list
171
+ self.file_bar_list.takeItem(row)
172
+ if len(loaded_image_paths) == 0:
173
+ for button_name in self.buttons_file_bar:
174
+ if 'previous' in button_name or 'next' in button_name:
175
+ self.buttons_file_bar[button_name].setEnabled(False)
176
+ for button_names in self.buttons_image_bar:
177
+ self.buttons_image_bar[button_names].setEnabled(False)
178
+
179
+
180
+ self.zoomable_graphics_view.scene.clear()
181
+ #self.pixmap_item = None
182
+ #self.zoomable_graphics_view.setSceneRect(0, 0, 0, 0)
183
+ #self.zoomable_graphics_view.resetTransform()
184
+
185
+ def file_bar_select(self):
186
+ """Handle selection change to update styling"""
187
+ for i in range(self.file_bar_list.count()):
188
+ item = self.file_bar_list.item(i)
189
+ item_widget = self.file_bar_list.itemWidget(item)
190
+
191
+ if item_widget:
192
+ if item.isSelected():
193
+ # Apply selected style
194
+ item_widget.setObjectName("selected_file_item")
195
+ self.controller.select_image(item)
196
+ else:
197
+ # Apply normal style
198
+ item_widget.setObjectName("file_item")
199
+
200
+ # Force style update
201
+ item_widget.style().unpolish(item_widget)
202
+ item_widget.style().polish(item_widget)
203
+
204
+
205
+
206
+ def initialize(self):
207
+ self.setWindowTitle("PyImageLabeling")
208
+ self.label_properties_dialogs = []
209
+ # Get screen information
210
+ self.screen = QApplication.primaryScreen()
211
+
212
+ self.screen_geometry = self.screen.availableGeometry()
213
+
214
+ self.screen_width = self.screen_geometry.width()
215
+ self.screen_height = self.screen_geometry.height()
216
+
217
+ # Calculate dynamic window size based on screen dimensions
218
+ self.window_width = int(self.screen_width * 0.80) # Use 85% of screen width
219
+ self.window_height = int(self.screen_height * 0.80) # Use 85% of screen height
220
+
221
+ self.setWindowIcon(QIcon(Utils.get_icon_path("maia_icon")))
222
+ self.setStyleSheet(Utils.get_style_css())
223
+
224
+ self.resize(self.window_width, self.window_height)
225
+
226
+