lazylabel-gui 1.1.4__py3-none-any.whl → 1.1.5__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.
@@ -1,183 +1,188 @@
1
- """Segment management functionality."""
2
-
3
- from typing import Any
4
-
5
- import cv2
6
- import numpy as np
7
- from PyQt6.QtCore import QPointF
8
-
9
-
10
- class SegmentManager:
11
- """Manages image segments and classes."""
12
-
13
- def __init__(self):
14
- self.segments: list[dict[str, Any]] = []
15
- self.class_aliases: dict[int, str] = {}
16
- self.next_class_id: int = 0
17
- self.active_class_id: int | None = None # Currently active/toggled class
18
-
19
- def clear(self) -> None:
20
- """Clear all segments and reset state."""
21
- self.segments.clear()
22
- self.class_aliases.clear()
23
- self.next_class_id = 0
24
- self.active_class_id = None
25
-
26
- def add_segment(self, segment_data: dict[str, Any]) -> None:
27
- """Add a new segment.
28
-
29
- If the segment is a polygon, convert QPointF objects to simple lists
30
- for serialization compatibility.
31
- """
32
- if "class_id" not in segment_data:
33
- # Use active class if available, otherwise use next class ID
34
- if self.active_class_id is not None:
35
- segment_data["class_id"] = self.active_class_id
36
- else:
37
- segment_data["class_id"] = self.next_class_id
38
-
39
- # Convert QPointF to list for storage if it's a polygon
40
- if segment_data.get("type") == "Polygon" and segment_data.get("vertices"):
41
- segment_data["vertices"] = [
42
- [p.x(), p.y()] for p in segment_data["vertices"]
43
- ]
44
-
45
- self.segments.append(segment_data)
46
- self._update_next_class_id()
47
-
48
- def delete_segments(self, indices: list[int]) -> None:
49
- """Delete segments by indices."""
50
- for i in sorted(indices, reverse=True):
51
- if 0 <= i < len(self.segments):
52
- del self.segments[i]
53
- self._update_next_class_id()
54
-
55
- def assign_segments_to_class(self, indices: list[int]) -> None:
56
- """Assign selected segments to a class."""
57
- if not indices:
58
- return
59
-
60
- existing_class_ids = [
61
- self.segments[i]["class_id"]
62
- for i in indices
63
- if i < len(self.segments) and self.segments[i].get("class_id") is not None
64
- ]
65
-
66
- if existing_class_ids:
67
- target_class_id = min(existing_class_ids)
68
- else:
69
- target_class_id = self.next_class_id
70
-
71
- for i in indices:
72
- if i < len(self.segments):
73
- self.segments[i]["class_id"] = target_class_id
74
-
75
- self._update_next_class_id()
76
-
77
- def get_unique_class_ids(self) -> list[int]:
78
- """Get sorted list of unique class IDs."""
79
- return sorted(
80
- {
81
- seg.get("class_id")
82
- for seg in self.segments
83
- if seg.get("class_id") is not None
84
- }
85
- )
86
-
87
- def rasterize_polygon(
88
- self, vertices: list[QPointF], image_size: tuple[int, int]
89
- ) -> np.ndarray | None:
90
- """Convert polygon vertices to binary mask."""
91
- if not vertices:
92
- return None
93
-
94
- h, w = image_size
95
- points_np = np.array([[p.x(), p.y()] for p in vertices], dtype=np.int32)
96
- mask = np.zeros((h, w), dtype=np.uint8)
97
- cv2.fillPoly(mask, [points_np], 1)
98
- return mask.astype(bool)
99
-
100
- def create_final_mask_tensor(
101
- self, image_size: tuple[int, int], class_order: list[int]
102
- ) -> np.ndarray:
103
- """Create final mask tensor for saving."""
104
- h, w = image_size
105
- id_map = {old_id: new_id for new_id, old_id in enumerate(class_order)}
106
- num_final_classes = len(class_order)
107
- final_mask_tensor = np.zeros((h, w, num_final_classes), dtype=np.uint8)
108
-
109
- for seg in self.segments:
110
- class_id = seg.get("class_id")
111
- if class_id not in id_map:
112
- continue
113
-
114
- new_channel_idx = id_map[class_id]
115
-
116
- if seg["type"] == "Polygon":
117
- # Convert stored list of lists back to QPointF objects for rasterization
118
- qpoints = [QPointF(p[0], p[1]) for p in seg["vertices"]]
119
- mask = self.rasterize_polygon(qpoints, image_size)
120
- else:
121
- mask = seg.get("mask")
122
-
123
- if mask is not None:
124
- final_mask_tensor[:, :, new_channel_idx] = np.logical_or(
125
- final_mask_tensor[:, :, new_channel_idx], mask
126
- )
127
-
128
- return final_mask_tensor
129
-
130
- def reassign_class_ids(self, new_order: list[int]) -> None:
131
- """Reassign class IDs based on new order."""
132
- id_map = {old_id: new_id for new_id, old_id in enumerate(new_order)}
133
-
134
- for seg in self.segments:
135
- old_id = seg.get("class_id")
136
- if old_id in id_map:
137
- seg["class_id"] = id_map[old_id]
138
-
139
- # Update aliases
140
- new_aliases = {
141
- id_map[old_id]: self.class_aliases.get(old_id, str(old_id))
142
- for old_id in new_order
143
- if old_id in self.class_aliases
144
- }
145
- self.class_aliases = new_aliases
146
- self._update_next_class_id()
147
-
148
- def set_class_alias(self, class_id: int, alias: str) -> None:
149
- """Set alias for a class."""
150
- self.class_aliases[class_id] = alias
151
-
152
- def get_class_alias(self, class_id: int) -> str:
153
- """Get alias for a class."""
154
- return self.class_aliases.get(class_id, str(class_id))
155
-
156
- def set_active_class(self, class_id: int | None) -> None:
157
- """Set the active class ID."""
158
- self.active_class_id = class_id
159
-
160
- def get_active_class(self) -> int | None:
161
- """Get the active class ID."""
162
- return self.active_class_id
163
-
164
- def toggle_active_class(self, class_id: int) -> bool:
165
- """Toggle a class as active. Returns True if now active, False if deactivated."""
166
- if self.active_class_id == class_id:
167
- self.active_class_id = None
168
- return False
169
- else:
170
- self.active_class_id = class_id
171
- return True
172
-
173
- def _update_next_class_id(self) -> None:
174
- """Update the next available class ID."""
175
- all_ids = {
176
- seg.get("class_id")
177
- for seg in self.segments
178
- if seg.get("class_id") is not None
179
- }
180
- if not all_ids:
181
- self.next_class_id = 0
182
- else:
183
- self.next_class_id = max(all_ids) + 1
1
+ """Segment management functionality."""
2
+
3
+ from typing import Any
4
+
5
+ import cv2
6
+ import numpy as np
7
+ from PyQt6.QtCore import QPointF
8
+
9
+
10
+ class SegmentManager:
11
+ """Manages image segments and classes."""
12
+
13
+ def __init__(self):
14
+ self.segments: list[dict[str, Any]] = []
15
+ self.class_aliases: dict[int, str] = {}
16
+ self.next_class_id: int = 0
17
+ self.active_class_id: int | None = None # Currently active/toggled class
18
+
19
+ def clear(self) -> None:
20
+ """Clear all segments and reset state."""
21
+ self.segments.clear()
22
+ self.class_aliases.clear()
23
+ self.next_class_id = 0
24
+ self.active_class_id = None
25
+
26
+ def add_segment(self, segment_data: dict[str, Any]) -> None:
27
+ """Add a new segment.
28
+
29
+ If the segment is a polygon, convert QPointF objects to simple lists
30
+ for serialization compatibility.
31
+ """
32
+ if "class_id" not in segment_data:
33
+ # Use active class if available, otherwise use next class ID
34
+ if self.active_class_id is not None:
35
+ segment_data["class_id"] = self.active_class_id
36
+ else:
37
+ segment_data["class_id"] = self.next_class_id
38
+
39
+ # Convert QPointF to list for storage if it's a polygon and contains QPointF objects
40
+ if (
41
+ segment_data.get("type") == "Polygon"
42
+ and segment_data.get("vertices")
43
+ and segment_data["vertices"]
44
+ and isinstance(segment_data["vertices"][0], QPointF)
45
+ ):
46
+ segment_data["vertices"] = [
47
+ [p.x(), p.y()] for p in segment_data["vertices"]
48
+ ]
49
+
50
+ self.segments.append(segment_data)
51
+ self._update_next_class_id()
52
+
53
+ def delete_segments(self, indices: list[int]) -> None:
54
+ """Delete segments by indices."""
55
+ for i in sorted(indices, reverse=True):
56
+ if 0 <= i < len(self.segments):
57
+ del self.segments[i]
58
+ self._update_next_class_id()
59
+
60
+ def assign_segments_to_class(self, indices: list[int]) -> None:
61
+ """Assign selected segments to a class."""
62
+ if not indices:
63
+ return
64
+
65
+ existing_class_ids = [
66
+ self.segments[i]["class_id"]
67
+ for i in indices
68
+ if i < len(self.segments) and self.segments[i].get("class_id") is not None
69
+ ]
70
+
71
+ if existing_class_ids:
72
+ target_class_id = min(existing_class_ids)
73
+ else:
74
+ target_class_id = self.next_class_id
75
+
76
+ for i in indices:
77
+ if i < len(self.segments):
78
+ self.segments[i]["class_id"] = target_class_id
79
+
80
+ self._update_next_class_id()
81
+
82
+ def get_unique_class_ids(self) -> list[int]:
83
+ """Get sorted list of unique class IDs."""
84
+ return sorted(
85
+ {
86
+ seg.get("class_id")
87
+ for seg in self.segments
88
+ if seg.get("class_id") is not None
89
+ }
90
+ )
91
+
92
+ def rasterize_polygon(
93
+ self, vertices: list[QPointF], image_size: tuple[int, int]
94
+ ) -> np.ndarray | None:
95
+ """Convert polygon vertices to binary mask."""
96
+ if not vertices:
97
+ return None
98
+
99
+ h, w = image_size
100
+ points_np = np.array([[p.x(), p.y()] for p in vertices], dtype=np.int32)
101
+ mask = np.zeros((h, w), dtype=np.uint8)
102
+ cv2.fillPoly(mask, [points_np], 1)
103
+ return mask.astype(bool)
104
+
105
+ def create_final_mask_tensor(
106
+ self, image_size: tuple[int, int], class_order: list[int]
107
+ ) -> np.ndarray:
108
+ """Create final mask tensor for saving."""
109
+ h, w = image_size
110
+ id_map = {old_id: new_id for new_id, old_id in enumerate(class_order)}
111
+ num_final_classes = len(class_order)
112
+ final_mask_tensor = np.zeros((h, w, num_final_classes), dtype=np.uint8)
113
+
114
+ for seg in self.segments:
115
+ class_id = seg.get("class_id")
116
+ if class_id not in id_map:
117
+ continue
118
+
119
+ new_channel_idx = id_map[class_id]
120
+
121
+ if seg["type"] == "Polygon":
122
+ # Convert stored list of lists back to QPointF objects for rasterization
123
+ qpoints = [QPointF(p[0], p[1]) for p in seg["vertices"]]
124
+ mask = self.rasterize_polygon(qpoints, image_size)
125
+ else:
126
+ mask = seg.get("mask")
127
+
128
+ if mask is not None:
129
+ final_mask_tensor[:, :, new_channel_idx] = np.logical_or(
130
+ final_mask_tensor[:, :, new_channel_idx], mask
131
+ )
132
+
133
+ return final_mask_tensor
134
+
135
+ def reassign_class_ids(self, new_order: list[int]) -> None:
136
+ """Reassign class IDs based on new order."""
137
+ id_map = {old_id: new_id for new_id, old_id in enumerate(new_order)}
138
+
139
+ for seg in self.segments:
140
+ old_id = seg.get("class_id")
141
+ if old_id in id_map:
142
+ seg["class_id"] = id_map[old_id]
143
+
144
+ # Update aliases
145
+ new_aliases = {
146
+ id_map[old_id]: self.class_aliases.get(old_id, str(old_id))
147
+ for old_id in new_order
148
+ if old_id in self.class_aliases
149
+ }
150
+ self.class_aliases = new_aliases
151
+ self._update_next_class_id()
152
+
153
+ def set_class_alias(self, class_id: int, alias: str) -> None:
154
+ """Set alias for a class."""
155
+ self.class_aliases[class_id] = alias
156
+
157
+ def get_class_alias(self, class_id: int) -> str:
158
+ """Get alias for a class."""
159
+ return self.class_aliases.get(class_id, str(class_id))
160
+
161
+ def set_active_class(self, class_id: int | None) -> None:
162
+ """Set the active class ID."""
163
+ self.active_class_id = class_id
164
+
165
+ def get_active_class(self) -> int | None:
166
+ """Get the active class ID."""
167
+ return self.active_class_id
168
+
169
+ def toggle_active_class(self, class_id: int) -> bool:
170
+ """Toggle a class as active. Returns True if now active, False if deactivated."""
171
+ if self.active_class_id == class_id:
172
+ self.active_class_id = None
173
+ return False
174
+ else:
175
+ self.active_class_id = class_id
176
+ return True
177
+
178
+ def _update_next_class_id(self) -> None:
179
+ """Update the next available class ID."""
180
+ all_ids = {
181
+ seg.get("class_id")
182
+ for seg in self.segments
183
+ if seg.get("class_id") is not None
184
+ }
185
+ if not all_ids:
186
+ self.next_class_id = 0
187
+ else:
188
+ self.next_class_id = max(all_ids) + 1
@@ -55,8 +55,8 @@ class EditableVertexItem(QGraphicsEllipseItem):
55
55
  "type": "move_vertex",
56
56
  "segment_index": self.segment_index,
57
57
  "vertex_index": self.vertex_index,
58
- "old_pos": self.initial_pos,
59
- "new_pos": self.pos(),
58
+ "old_pos": [self.initial_pos.x(), self.initial_pos.y()],
59
+ "new_pos": [self.pos().x(), self.pos().y()],
60
60
  }
61
61
  )
62
62
  self.initial_pos = None
@@ -912,7 +912,7 @@ class MainWindow(QMainWindow):
912
912
  return
913
913
 
914
914
  new_segment = {
915
- "vertices": list(self.polygon_points),
915
+ "vertices": [[p.x(), p.y()] for p in self.polygon_points],
916
916
  "type": "Polygon",
917
917
  "mask": None,
918
918
  }
@@ -1070,7 +1070,9 @@ class MainWindow(QMainWindow):
1070
1070
  elif action_type == "move_polygon":
1071
1071
  initial_vertices = last_action.get("initial_vertices")
1072
1072
  for i, vertices in initial_vertices.items():
1073
- self.segment_manager.segments[i]["vertices"] = vertices
1073
+ self.segment_manager.segments[i]["vertices"] = [
1074
+ [p[0], p[1]] for p in vertices
1075
+ ]
1074
1076
  self._update_polygon_item(i)
1075
1077
  self._display_edit_handles()
1076
1078
  self._highlight_selected_segments()
@@ -1079,13 +1081,27 @@ class MainWindow(QMainWindow):
1079
1081
  segment_index = last_action.get("segment_index")
1080
1082
  vertex_index = last_action.get("vertex_index")
1081
1083
  old_pos = last_action.get("old_pos")
1082
- self.segment_manager.segments[segment_index]["vertices"][vertex_index] = (
1083
- old_pos
1084
- )
1085
- self._update_polygon_item(segment_index)
1086
- self._display_edit_handles()
1087
- self._highlight_selected_segments()
1088
- self._show_notification("Undid: Move Vertex")
1084
+ if (
1085
+ segment_index is not None
1086
+ and vertex_index is not None
1087
+ and old_pos is not None
1088
+ ):
1089
+ if segment_index < len(self.segment_manager.segments):
1090
+ self.segment_manager.segments[segment_index]["vertices"][
1091
+ vertex_index
1092
+ ] = old_pos
1093
+ self._update_polygon_item(segment_index)
1094
+ self._display_edit_handles()
1095
+ self._highlight_selected_segments()
1096
+ self._show_notification("Undid: Move Vertex")
1097
+ else:
1098
+ self._show_warning_notification(
1099
+ "Cannot undo: Segment no longer exists"
1100
+ )
1101
+ self.redo_history.pop() # Remove from redo history if segment is gone
1102
+ else:
1103
+ self._show_warning_notification("Cannot undo: Missing vertex data")
1104
+ self.redo_history.pop() # Remove from redo history if data is incomplete
1089
1105
 
1090
1106
  # Add more undo logic for other action types here in the future
1091
1107
  else:
@@ -1147,8 +1163,7 @@ class MainWindow(QMainWindow):
1147
1163
  for i, vertices in final_vertices.items():
1148
1164
  if i < len(self.segment_manager.segments):
1149
1165
  self.segment_manager.segments[i]["vertices"] = [
1150
- [v.x(), v.y()]
1151
- for v in [QPointF(p[0], p[1]) for p in vertices]
1166
+ [p[0], p[1]] for p in vertices
1152
1167
  ]
1153
1168
  self._update_polygon_item(i)
1154
1169
  self._display_edit_handles()
@@ -1178,10 +1193,10 @@ class MainWindow(QMainWindow):
1178
1193
  self._show_warning_notification(
1179
1194
  "Cannot redo: Segment no longer exists"
1180
1195
  )
1181
- self.action_history.pop()
1196
+ self.action_history.pop() # Remove from action history if segment is gone
1182
1197
  else:
1183
1198
  self._show_warning_notification("Cannot redo: Missing vertex data")
1184
- self.action_history.pop()
1199
+ self.action_history.pop() # Remove from action history if data is incomplete
1185
1200
  else:
1186
1201
  self._show_warning_notification(
1187
1202
  f"Redo for action '{action_type}' not implemented."
@@ -1321,7 +1336,7 @@ class MainWindow(QMainWindow):
1321
1336
  selected_indices = self.right_panel.get_selected_segment_indices()
1322
1337
  self.drag_initial_vertices = {
1323
1338
  i: [
1324
- QPointF(p[0], p[1])
1339
+ [p.x(), p.y()] if isinstance(p, QPointF) else p
1325
1340
  for p in self.segment_manager.segments[i]["vertices"]
1326
1341
  ]
1327
1342
  for i in selected_indices
@@ -1360,7 +1375,7 @@ class MainWindow(QMainWindow):
1360
1375
  self.drag_start_pos = pos
1361
1376
  self.rubber_band_rect = QGraphicsRectItem()
1362
1377
  self.rubber_band_rect.setPen(
1363
- QPen(Qt.GlobalColor.red, 2, Qt.PenStyle.DashLine)
1378
+ QPen(Qt.GlobalColor.red, self.line_thickness, Qt.PenStyle.DashLine)
1364
1379
  )
1365
1380
  self.viewer.scene().addItem(self.rubber_band_rect)
1366
1381
  elif self.mode == "selection" and event.button() == Qt.MouseButton.LeftButton:
@@ -1371,9 +1386,13 @@ class MainWindow(QMainWindow):
1371
1386
  if self.mode == "edit" and self.is_dragging_polygon:
1372
1387
  delta = event.scenePos() - self.drag_start_pos
1373
1388
  for i, initial_verts in self.drag_initial_vertices.items():
1374
- # initial_verts are already QPointF objects
1389
+ # initial_verts are lists, convert to QPointF for addition with delta
1375
1390
  self.segment_manager.segments[i]["vertices"] = [
1376
- [(p + delta).x(), (p + delta).y()] for p in initial_verts
1391
+ [
1392
+ (QPointF(p[0], p[1]) + delta).x(),
1393
+ (QPointF(p[0], p[1]) + delta).y(),
1394
+ ]
1395
+ for p in initial_verts
1377
1396
  ]
1378
1397
  self._update_polygon_item(i)
1379
1398
  self._display_edit_handles() # Redraw handles at new positions
@@ -1395,7 +1414,10 @@ class MainWindow(QMainWindow):
1395
1414
  if self.mode == "edit" and self.is_dragging_polygon:
1396
1415
  # Record the action for undo
1397
1416
  final_vertices = {
1398
- i: list(self.segment_manager.segments[i]["vertices"])
1417
+ i: [
1418
+ [p.x(), p.y()] if isinstance(p, QPointF) else p
1419
+ for p in self.segment_manager.segments[i]["vertices"]
1420
+ ]
1399
1421
  for i in self.drag_initial_vertices
1400
1422
  }
1401
1423
  self.action_history.append(
@@ -1431,7 +1453,7 @@ class MainWindow(QMainWindow):
1431
1453
  polygon.append(rect.bottomLeft())
1432
1454
 
1433
1455
  new_segment = {
1434
- "vertices": list(polygon),
1456
+ "vertices": [[p.x(), p.y()] for p in list(polygon)],
1435
1457
  "type": "Polygon", # Bounding boxes are stored as polygons
1436
1458
  "mask": None,
1437
1459
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lazylabel-gui
3
- Version: 1.1.4
3
+ Version: 1.1.5
4
4
  Summary: An image segmentation GUI for generating ML ready mask tensors and annotations.
5
5
  Author-email: "Deniz N. Cakan" <deniz.n.cakan@gmail.com>
6
6
  License: MIT License
@@ -7,16 +7,16 @@ lazylabel/config/settings.py,sha256=Ud27cSadJ7M4l30XN0KrxZ3ixAOPXTUhj-SvvanMjaI,
7
7
  lazylabel/core/__init__.py,sha256=FmRjop_uIBSJwKMGhaZ-3Iwu34LkoxTuD-hnq5vbTSY,232
8
8
  lazylabel/core/file_manager.py,sha256=Blo55jXW-uGVLrreGRmlHUtK2yTbyj3jsTKkfjD0z7k,4796
9
9
  lazylabel/core/model_manager.py,sha256=P3IahI0xUk6-F7Y5U4r5RpnUQSelJqX2KBtcmUGNeNY,3368
10
- lazylabel/core/segment_manager.py,sha256=1lABdVdaa69_RPKx6ftYKJh7lNWCanodTsh7Utrpn2Q,6477
10
+ lazylabel/core/segment_manager.py,sha256=M6kHcYeiub3WqL01NElCvKOc2GNmf72LUM1W8XwSaxc,6465
11
11
  lazylabel/models/__init__.py,sha256=fIlk_0DuZfiClcm0XlZdimeHzunQwBmTMI4PcGsaymw,91
12
12
  lazylabel/models/sam_model.py,sha256=89v99hpD0ngAAQKiuRyIib0E-5u9zTDJcubtmxxG-PM,7878
13
13
  lazylabel/ui/__init__.py,sha256=4qDIh9y6tABPmD8MAMGZn_G7oSRyrcHt2HkjoWgbGH4,268
14
14
  lazylabel/ui/control_panel.py,sha256=UlETN2IZv1l2xiaWPQvdalaK_f9YQf9iiB1Jb_EEgfs,9260
15
- lazylabel/ui/editable_vertex.py,sha256=xzc5QdFJJXiy035C3HgR4ph-tuJu8245l-Ar7aBvVv8,2399
15
+ lazylabel/ui/editable_vertex.py,sha256=nAFC2UuFfbvMbGBbAiLWA77cS5-Hn3a08xe1_QLz2yk,2449
16
16
  lazylabel/ui/hotkey_dialog.py,sha256=ZlZoPvY822ke8YkbCy22o2RUjxtkXSoEOg8eVETIKpQ,15118
17
17
  lazylabel/ui/hoverable_pixelmap_item.py,sha256=kJFOp7WXiyHpNf7l73TZjiob85jgP30b5MZvu_z5L3c,728
18
18
  lazylabel/ui/hoverable_polygon_item.py,sha256=aclUwd0P8H8xbcep6GwhnfaVs1zSkqeZKAL-xeDyMiU,1222
19
- lazylabel/ui/main_window.py,sha256=ta3nzb6MWG-eLexlGKBc3oKtlsF9HpI-q1SvlrA-W2o,78623
19
+ lazylabel/ui/main_window.py,sha256=h0wfVjQRskiTIq6X-Wd7OvM-PfOdKEKdFcwgx0iRIj0,79831
20
20
  lazylabel/ui/numeric_table_widget_item.py,sha256=dQUlIFu9syCxTGAHVIlmbgkI7aJ3f3wmDPBz1AGK9Bg,283
21
21
  lazylabel/ui/photo_viewer.py,sha256=4n2zSpFAnausCoIU-wwWDHDo6vsNp_RGIkhDyhuM2_A,1997
22
22
  lazylabel/ui/reorderable_class_table.py,sha256=sxHhQre5O_MXLDFgKnw43QnvXXoqn5xRKMGitgO7muI,2371
@@ -29,9 +29,9 @@ lazylabel/ui/widgets/status_bar.py,sha256=wTbMQNEOBfmtNj8EVFZS_lxgaemu-CbRXeZzEQ
29
29
  lazylabel/utils/__init__.py,sha256=V6IR5Gim-39HgM2NyTVT-n8gy3mjilCSFW9y0owN5nc,179
30
30
  lazylabel/utils/custom_file_system_model.py,sha256=-3EimlybvevH6bvqBE0qdFnLADVtayylmkntxPXK0Bk,4869
31
31
  lazylabel/utils/utils.py,sha256=sYSCoXL27OaLgOZaUkCAhgmKZ7YfhR3Cc5F8nDIa3Ig,414
32
- lazylabel_gui-1.1.4.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
33
- lazylabel_gui-1.1.4.dist-info/METADATA,sha256=hYVIAtM7vZNaJ8-0QOnFtNyaK3UpScgswNyJuaiJaFE,9506
34
- lazylabel_gui-1.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- lazylabel_gui-1.1.4.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
36
- lazylabel_gui-1.1.4.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
37
- lazylabel_gui-1.1.4.dist-info/RECORD,,
32
+ lazylabel_gui-1.1.5.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
33
+ lazylabel_gui-1.1.5.dist-info/METADATA,sha256=2MNsqA48WN9e7YJMg864WZYGMZixitm3XtMnD2uZin4,9506
34
+ lazylabel_gui-1.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ lazylabel_gui-1.1.5.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
36
+ lazylabel_gui-1.1.5.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
37
+ lazylabel_gui-1.1.5.dist-info/RECORD,,