lazylabel-gui 1.1.0__py3-none-any.whl → 1.1.1__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,8 +1,17 @@
1
1
  """Right panel with file explorer and segment management."""
2
2
 
3
3
  from PyQt6.QtWidgets import (
4
- QWidget, QVBoxLayout, QPushButton, QLabel, QHBoxLayout,
5
- QTableWidget, QTreeView, QComboBox, QSplitter, QSpacerItem, QHeaderView
4
+ QWidget,
5
+ QVBoxLayout,
6
+ QPushButton,
7
+ QLabel,
8
+ QHBoxLayout,
9
+ QTableWidget,
10
+ QTreeView,
11
+ QComboBox,
12
+ QSplitter,
13
+ QSpacerItem,
14
+ QHeaderView,
6
15
  )
7
16
  from PyQt6.QtCore import Qt, pyqtSignal
8
17
  from PyQt6.QtGui import QBrush, QColor
@@ -13,82 +22,89 @@ from .numeric_table_widget_item import NumericTableWidgetItem
13
22
 
14
23
  class RightPanel(QWidget):
15
24
  """Right panel with file explorer and segment management."""
16
-
25
+
17
26
  # Signals
18
27
  open_folder_requested = pyqtSignal()
19
- image_selected = pyqtSignal('QModelIndex')
28
+ image_selected = pyqtSignal("QModelIndex")
20
29
  merge_selection_requested = pyqtSignal()
21
30
  delete_selection_requested = pyqtSignal()
22
31
  segments_selection_changed = pyqtSignal()
23
32
  class_alias_changed = pyqtSignal(int, str) # class_id, alias
24
33
  reassign_classes_requested = pyqtSignal()
25
34
  class_filter_changed = pyqtSignal()
26
-
35
+ class_toggled = pyqtSignal(int) # class_id
36
+ pop_out_requested = pyqtSignal()
37
+
27
38
  def __init__(self, parent=None):
28
39
  super().__init__(parent)
29
- self.setFixedWidth(350)
40
+ self.setMinimumWidth(50) # Allow collapsing but maintain minimum
41
+ self.preferred_width = 350 # Store preferred width for expansion
30
42
  self._setup_ui()
31
43
  self._connect_signals()
32
-
44
+
33
45
  def _setup_ui(self):
34
46
  """Setup the UI layout."""
35
47
  self.v_layout = QVBoxLayout(self)
36
-
37
- # Toggle button
48
+
49
+ # Top button row
38
50
  toggle_layout = QHBoxLayout()
51
+
52
+ self.btn_popout = QPushButton("⋯")
53
+ self.btn_popout.setToolTip("Pop out panel to separate window")
54
+ self.btn_popout.setMaximumWidth(30)
55
+ toggle_layout.addWidget(self.btn_popout)
56
+
39
57
  toggle_layout.addStretch()
40
- self.btn_toggle_visibility = QPushButton("Hide >")
41
- self.btn_toggle_visibility.setToolTip("Hide this panel")
42
- toggle_layout.addWidget(self.btn_toggle_visibility)
58
+
43
59
  self.v_layout.addLayout(toggle_layout)
44
-
60
+
45
61
  # Main controls widget
46
62
  self.main_controls_widget = QWidget()
47
63
  main_layout = QVBoxLayout(self.main_controls_widget)
48
64
  main_layout.setContentsMargins(0, 0, 0, 0)
49
-
65
+
50
66
  # Vertical splitter for sections
51
67
  v_splitter = QSplitter(Qt.Orientation.Vertical)
52
-
68
+
53
69
  # File explorer section
54
70
  self._setup_file_explorer(v_splitter)
55
-
71
+
56
72
  # Segment management section
57
73
  self._setup_segment_management(v_splitter)
58
-
74
+
59
75
  # Class management section
60
76
  self._setup_class_management(v_splitter)
61
-
77
+
62
78
  main_layout.addWidget(v_splitter)
63
-
79
+
64
80
  # Status label
65
81
  self.status_label = QLabel("")
66
82
  self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
67
83
  main_layout.addWidget(self.status_label)
68
-
84
+
69
85
  self.v_layout.addWidget(self.main_controls_widget)
70
-
86
+
71
87
  def _setup_file_explorer(self, splitter):
72
88
  """Setup file explorer section."""
73
89
  file_explorer_widget = QWidget()
74
90
  layout = QVBoxLayout(file_explorer_widget)
75
91
  layout.setContentsMargins(0, 0, 0, 0)
76
-
92
+
77
93
  self.btn_open_folder = QPushButton("Open Image Folder")
78
94
  self.btn_open_folder.setToolTip("Open a directory of images")
79
95
  layout.addWidget(self.btn_open_folder)
80
-
96
+
81
97
  self.file_tree = QTreeView()
82
98
  layout.addWidget(self.file_tree)
83
-
99
+
84
100
  splitter.addWidget(file_explorer_widget)
85
-
101
+
86
102
  def _setup_segment_management(self, splitter):
87
103
  """Setup segment management section."""
88
104
  segment_widget = QWidget()
89
105
  layout = QVBoxLayout(segment_widget)
90
106
  layout.setContentsMargins(0, 0, 0, 0)
91
-
107
+
92
108
  # Class filter
93
109
  filter_layout = QHBoxLayout()
94
110
  filter_layout.addWidget(QLabel("Filter Class:"))
@@ -96,56 +112,70 @@ class RightPanel(QWidget):
96
112
  self.class_filter_combo.setToolTip("Filter segments list by class")
97
113
  filter_layout.addWidget(self.class_filter_combo)
98
114
  layout.addLayout(filter_layout)
99
-
115
+
100
116
  # Segment table
101
117
  self.segment_table = QTableWidget()
102
118
  self.segment_table.setColumnCount(3)
103
- self.segment_table.setHorizontalHeaderLabels(["Segment ID", "Class ID", "Alias"])
104
- self.segment_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
105
- self.segment_table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
119
+ self.segment_table.setHorizontalHeaderLabels(
120
+ ["Segment ID", "Class ID", "Alias"]
121
+ )
122
+ self.segment_table.horizontalHeader().setSectionResizeMode(
123
+ QHeaderView.ResizeMode.Stretch
124
+ )
125
+ self.segment_table.setSelectionBehavior(
126
+ QTableWidget.SelectionBehavior.SelectRows
127
+ )
106
128
  self.segment_table.setSortingEnabled(True)
107
129
  self.segment_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
108
130
  layout.addWidget(self.segment_table)
109
-
131
+
110
132
  # Action buttons
111
133
  action_layout = QHBoxLayout()
112
134
  self.btn_merge_selection = QPushButton("Merge to Class")
113
- self.btn_merge_selection.setToolTip("Merge selected segments into a single class (M)")
135
+ self.btn_merge_selection.setToolTip(
136
+ "Merge selected segments into a single class (M)"
137
+ )
114
138
  self.btn_delete_selection = QPushButton("Delete")
115
- self.btn_delete_selection.setToolTip("Delete selected segments (Delete/Backspace)")
139
+ self.btn_delete_selection.setToolTip(
140
+ "Delete selected segments (Delete/Backspace)"
141
+ )
116
142
  action_layout.addWidget(self.btn_merge_selection)
117
143
  action_layout.addWidget(self.btn_delete_selection)
118
144
  layout.addLayout(action_layout)
119
-
145
+
120
146
  splitter.addWidget(segment_widget)
121
-
147
+
122
148
  def _setup_class_management(self, splitter):
123
149
  """Setup class management section."""
124
150
  class_widget = QWidget()
125
151
  layout = QVBoxLayout(class_widget)
126
152
  layout.setContentsMargins(0, 0, 0, 0)
127
-
153
+
128
154
  layout.addWidget(QLabel("Class Order:"))
129
-
155
+
130
156
  self.class_table = ReorderableClassTable()
131
157
  self.class_table.setToolTip(
132
- "Double-click to set class aliases and drag to reorder channels for saving."
158
+ "Double-click to set class aliases and drag to reorder channels for saving.\nClick once to toggle as active class for new segments."
133
159
  )
134
160
  self.class_table.setColumnCount(2)
135
161
  self.class_table.setHorizontalHeaderLabels(["Alias", "Class ID"])
136
- self.class_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
137
- self.class_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
162
+ self.class_table.horizontalHeader().setSectionResizeMode(
163
+ 0, QHeaderView.ResizeMode.Stretch
164
+ )
165
+ self.class_table.horizontalHeader().setSectionResizeMode(
166
+ 1, QHeaderView.ResizeMode.ResizeToContents
167
+ )
138
168
  self.class_table.setEditTriggers(QTableWidget.EditTrigger.DoubleClicked)
139
169
  layout.addWidget(self.class_table)
140
-
170
+
141
171
  self.btn_reassign_classes = QPushButton("Reassign Class IDs")
142
172
  self.btn_reassign_classes.setToolTip(
143
173
  "Re-index class channels based on the current order in this table"
144
174
  )
145
175
  layout.addWidget(self.btn_reassign_classes)
146
-
176
+
147
177
  splitter.addWidget(class_widget)
148
-
178
+
149
179
  def _connect_signals(self):
150
180
  """Connect internal signals."""
151
181
  self.btn_open_folder.clicked.connect(self.open_folder_requested)
@@ -154,14 +184,24 @@ class RightPanel(QWidget):
154
184
  self.btn_delete_selection.clicked.connect(self.delete_selection_requested)
155
185
  self.segment_table.itemSelectionChanged.connect(self.segments_selection_changed)
156
186
  self.class_table.itemChanged.connect(self._handle_class_alias_change)
187
+ self.class_table.cellClicked.connect(self._handle_class_toggle)
157
188
  self.btn_reassign_classes.clicked.connect(self.reassign_classes_requested)
158
189
  self.class_filter_combo.currentIndexChanged.connect(self.class_filter_changed)
159
-
190
+ self.btn_popout.clicked.connect(self.pop_out_requested)
191
+
192
+ def mouseDoubleClickEvent(self, event):
193
+ """Handle double-click to expand collapsed panel."""
194
+ if self.width() < 50: # If panel is collapsed
195
+ # Request expansion by calling parent method
196
+ if self.parent() and hasattr(self.parent(), "_expand_right_panel"):
197
+ self.parent()._expand_right_panel()
198
+ super().mouseDoubleClickEvent(event)
199
+
160
200
  def _handle_class_alias_change(self, item):
161
201
  """Handle class alias change in table."""
162
202
  if item.column() != 0: # Only handle alias column
163
203
  return
164
-
204
+
165
205
  class_table = self.class_table
166
206
  id_item = class_table.item(item.row(), 1)
167
207
  if id_item:
@@ -170,35 +210,62 @@ class RightPanel(QWidget):
170
210
  self.class_alias_changed.emit(class_id, item.text())
171
211
  except (ValueError, AttributeError):
172
212
  pass
173
-
213
+
214
+ def _handle_class_toggle(self, row, column):
215
+ """Handle class table cell click for toggling active class."""
216
+ # Get the class ID from the clicked row
217
+ id_item = self.class_table.item(row, 1)
218
+ if id_item:
219
+ try:
220
+ class_id = int(id_item.text())
221
+ self.class_toggled.emit(class_id)
222
+ except (ValueError, AttributeError):
223
+ pass
224
+
225
+ def update_active_class_display(self, active_class_id):
226
+ """Update the visual display to show which class is active."""
227
+ # Block signals to prevent triggering change events during update
228
+ self.class_table.blockSignals(True)
229
+
230
+ for row in range(self.class_table.rowCount()):
231
+ id_item = self.class_table.item(row, 1)
232
+ alias_item = self.class_table.item(row, 0)
233
+ if id_item and alias_item:
234
+ try:
235
+ class_id = int(id_item.text())
236
+ if class_id == active_class_id:
237
+ # Make active class bold and add indicator
238
+ font = alias_item.font()
239
+ font.setBold(True)
240
+ alias_item.setFont(font)
241
+ id_item.setFont(font)
242
+ # Add visual indicator
243
+ if not alias_item.text().startswith("🔸 "):
244
+ alias_item.setText(f"🔸 {alias_item.text()}")
245
+ else:
246
+ # Make inactive classes normal
247
+ font = alias_item.font()
248
+ font.setBold(False)
249
+ alias_item.setFont(font)
250
+ id_item.setFont(font)
251
+ # Remove visual indicator
252
+ if alias_item.text().startswith("🔸 "):
253
+ alias_item.setText(alias_item.text()[2:])
254
+ except (ValueError, AttributeError):
255
+ pass
256
+
257
+ # Re-enable signals
258
+ self.class_table.blockSignals(False)
259
+
174
260
  def setup_file_model(self, file_model):
175
261
  """Setup the file model for the tree view."""
176
262
  self.file_tree.setModel(file_model)
177
263
  self.file_tree.setColumnWidth(0, 200)
178
-
264
+
179
265
  def set_folder(self, folder_path, file_model):
180
266
  """Set the folder for file browsing."""
181
267
  self.file_tree.setRootIndex(file_model.setRootPath(folder_path))
182
-
183
- def toggle_visibility(self):
184
- """Toggle panel visibility."""
185
- is_visible = self.main_controls_widget.isVisible()
186
- self.main_controls_widget.setVisible(not is_visible)
187
-
188
- if is_visible: # Content is now hidden
189
- self.v_layout.addStretch(1)
190
- self.btn_toggle_visibility.setText("< Show")
191
- self.setFixedWidth(self.btn_toggle_visibility.sizeHint().width() + 20)
192
- else: # Content is now visible
193
- # Remove the stretch
194
- for i in range(self.v_layout.count()):
195
- item = self.v_layout.itemAt(i)
196
- if isinstance(item, QSpacerItem):
197
- self.v_layout.removeItem(item)
198
- break
199
- self.btn_toggle_visibility.setText("Hide >")
200
- self.setFixedWidth(350)
201
-
268
+
202
269
  def get_selected_segment_indices(self):
203
270
  """Get indices of selected segments."""
204
271
  selected_items = self.segment_table.selectedItems()
@@ -208,7 +275,7 @@ class RightPanel(QWidget):
208
275
  for row in selected_rows
209
276
  if self.segment_table.item(row, 0)
210
277
  ]
211
-
278
+
212
279
  def get_class_order(self):
213
280
  """Get the current class order from the class table."""
214
281
  ordered_ids = []
@@ -220,20 +287,29 @@ class RightPanel(QWidget):
220
287
  except ValueError:
221
288
  continue
222
289
  return ordered_ids
223
-
290
+
224
291
  def clear_selections(self):
225
292
  """Clear all selections."""
226
293
  self.segment_table.clearSelection()
227
294
  self.class_table.clearSelection()
228
-
295
+
229
296
  def select_all_segments(self):
230
297
  """Select all segments."""
231
298
  self.segment_table.selectAll()
232
-
299
+
233
300
  def set_status(self, message):
234
301
  """Set status message."""
235
302
  self.status_label.setText(message)
236
-
303
+
237
304
  def clear_status(self):
238
305
  """Clear status message."""
239
- self.status_label.clear()
306
+ self.status_label.clear()
307
+
308
+ def set_popout_mode(self, is_popped_out: bool):
309
+ """Update the pop-out button based on panel state."""
310
+ if is_popped_out:
311
+ self.btn_popout.setText("⇤")
312
+ self.btn_popout.setToolTip("Return panel to main window")
313
+ else:
314
+ self.btn_popout.setText("⋯")
315
+ self.btn_popout.setToolTip("Pop out panel to separate window")
@@ -3,5 +3,6 @@
3
3
  from .model_selection_widget import ModelSelectionWidget
4
4
  from .settings_widget import SettingsWidget
5
5
  from .adjustments_widget import AdjustmentsWidget
6
+ from .status_bar import StatusBar
6
7
 
7
- __all__ = ['ModelSelectionWidget', 'SettingsWidget', 'AdjustmentsWidget']
8
+ __all__ = ["ModelSelectionWidget", "SettingsWidget", "AdjustmentsWidget", "StatusBar"]
@@ -0,0 +1,109 @@
1
+ """Status bar widget for displaying active messages."""
2
+
3
+ from PyQt6.QtWidgets import QStatusBar, QLabel
4
+ from PyQt6.QtCore import QTimer, pyqtSignal, Qt
5
+ from PyQt6.QtGui import QFont
6
+
7
+
8
+ class StatusBar(QStatusBar):
9
+ """Custom status bar for displaying messages and app status."""
10
+
11
+ def __init__(self, parent=None):
12
+ super().__init__(parent)
13
+ self._message_timer = QTimer()
14
+ self._message_timer.timeout.connect(self._clear_temporary_message)
15
+ self._setup_ui()
16
+
17
+ def _setup_ui(self):
18
+ """Setup the status bar UI."""
19
+ # Set a reasonable height for the status bar
20
+ self.setFixedHeight(25)
21
+
22
+ # Main message label (centered)
23
+ self.message_label = QLabel()
24
+ self.message_label.setStyleSheet("color: #ffa500; padding: 2px 5px;")
25
+ self.message_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
26
+ font = QFont()
27
+ font.setPointSize(9)
28
+ self.message_label.setFont(font)
29
+
30
+ # Add the message label as the main widget
31
+ self.addWidget(self.message_label, 1) # stretch factor 1
32
+
33
+ # Permanent status label (right side)
34
+ self.permanent_label = QLabel()
35
+ self.permanent_label.setStyleSheet("color: #888; padding: 2px 5px;")
36
+ font = QFont()
37
+ font.setPointSize(9)
38
+ self.permanent_label.setFont(font)
39
+ self.addPermanentWidget(self.permanent_label)
40
+
41
+ # Default state
42
+ self.set_ready_message()
43
+
44
+ def show_message(self, message: str, duration: int = 5000):
45
+ """Show a temporary message for specified duration."""
46
+ self.message_label.setText(message)
47
+ self.message_label.setStyleSheet("color: #ffa500; padding: 2px 5px;")
48
+
49
+ # Stop any existing timer
50
+ self._message_timer.stop()
51
+
52
+ # Start new timer if duration > 0
53
+ if duration > 0:
54
+ self._message_timer.start(duration)
55
+
56
+ def show_error_message(self, message: str, duration: int = 8000):
57
+ """Show an error message with red color."""
58
+ self.message_label.setText(f"Error: {message}")
59
+ self.message_label.setStyleSheet("color: #ff6b6b; padding: 2px 5px;")
60
+
61
+ # Stop any existing timer
62
+ self._message_timer.stop()
63
+
64
+ # Start new timer if duration > 0
65
+ if duration > 0:
66
+ self._message_timer.start(duration)
67
+
68
+ def show_success_message(self, message: str, duration: int = 3000):
69
+ """Show a success message with green color."""
70
+ self.message_label.setText(message)
71
+ self.message_label.setStyleSheet("color: #51cf66; padding: 2px 5px;")
72
+
73
+ # Stop any existing timer
74
+ self._message_timer.stop()
75
+
76
+ # Start new timer if duration > 0
77
+ if duration > 0:
78
+ self._message_timer.start(duration)
79
+
80
+ def show_warning_message(self, message: str, duration: int = 5000):
81
+ """Show a warning message with yellow color."""
82
+ self.message_label.setText(f"Warning: {message}")
83
+ self.message_label.setStyleSheet("color: #ffd43b; padding: 2px 5px;")
84
+
85
+ # Stop any existing timer
86
+ self._message_timer.stop()
87
+
88
+ # Start new timer if duration > 0
89
+ if duration > 0:
90
+ self._message_timer.start(duration)
91
+
92
+ def set_permanent_message(self, message: str):
93
+ """Set a permanent message (usually for status info)."""
94
+ self.permanent_label.setText(message)
95
+
96
+ def set_ready_message(self):
97
+ """Set the default ready message."""
98
+ self.message_label.setText("") # Blank instead of "Ready"
99
+ self.message_label.setStyleSheet("color: #888; padding: 2px 5px;")
100
+ self._message_timer.stop()
101
+
102
+ def _clear_temporary_message(self):
103
+ """Clear temporary message and return to ready state."""
104
+ self.set_ready_message()
105
+ self._message_timer.stop()
106
+
107
+ def clear_message(self):
108
+ """Immediately clear any message."""
109
+ self.set_ready_message()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lazylabel-gui
3
- Version: 1.1.0
3
+ Version: 1.1.1
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
@@ -1,36 +1,37 @@
1
1
  lazylabel/__init__.py,sha256=XTAPk-88MdkJX5IKg0f51CxNlARQ-SZIiqLneV6B3II,197
2
- lazylabel/main.py,sha256=EQdIfp4GX3Qt9Hz1KFldxKiqjG0Wm0-GmuECdfGwL_8,426
2
+ lazylabel/main.py,sha256=U0_bYNiVmmwdhRgBOryRZE91sunDQYEJTGGMNFubj1M,766
3
3
  lazylabel/config/__init__.py,sha256=ahAF6cneEVmq2zyGwydGgGAOzJKkv_aumq5cWmokOms,261
4
4
  lazylabel/config/hotkeys.py,sha256=LrQ4nmLWVOZvNOe4mEARFU3Wd3bZ7nvvsxGeFY6N9wA,7618
5
5
  lazylabel/config/paths.py,sha256=d6lJ0rwdlnLjrhR5fIzb3Pc9Fhl4lsGIf2IZNmi4vZ8,1320
6
6
  lazylabel/config/settings.py,sha256=IkUGz-FdDapF71k_LRpUOLHScglGeYjdLbbELGJ4hOs,1860
7
7
  lazylabel/core/__init__.py,sha256=YIj3IAI6Er5nN7gSuo9E8eoQKbBbSq2Jy2prtU8Fp50,230
8
8
  lazylabel/core/file_manager.py,sha256=cXaSPSUiqTm57hfpUxkuzgqApOZCK1RAJdfjmKRJKRA,4734
9
- lazylabel/core/model_manager.py,sha256=Prski8UZCSj6Rkk5uCtJwhsxSSnZPos-RZwM5CgF0KY,3442
10
- lazylabel/core/segment_manager.py,sha256=mrP6QqeHRFvX4HaX3hUsesnfWqAwUjLVfkxB8Wdy3cY,5097
9
+ lazylabel/core/model_manager.py,sha256=pLTmQlVfambA3y4aypHu_jn_WrW0ZrMu_8j023mr_EM,3435
10
+ lazylabel/core/segment_manager.py,sha256=kLEj5S-fEmoXIiJ2Em97GJlre8OOpSotX5bIWMrBCvE,6006
11
11
  lazylabel/models/__init__.py,sha256=qH0EvkWsou0boS85yM6DfRhJnrPOLc-QzWI0grAwnRI,89
12
- lazylabel/models/sam_model.py,sha256=NPC_Zwc973jos1hV-EfUTlnX44QREgjI-QT2nDd4NUY,6408
12
+ lazylabel/models/sam_model.py,sha256=lMakV3_B-hNJ3BXy1sErkSzH9YvDsColevXLGaeLnP4,7762
13
13
  lazylabel/ui/__init__.py,sha256=i5hgblzrydTkFSJDiFyfRZMNl4Z4J2dumuwx3bWEPvA,266
14
- lazylabel/ui/control_panel.py,sha256=LKPfIgS12rzMbORunUpoHFGKEtEjsJTHtlU1BUAcD7g,8742
14
+ lazylabel/ui/control_panel.py,sha256=Pfv4D3V9oBkTWWzTE944JAUCa0by7jv9h3EruKnJLVM,8894
15
15
  lazylabel/ui/editable_vertex.py,sha256=pMuXvlCkbguUsFisEzj3bC2UZ_xKqfGuM8kyPug5yws,1852
16
16
  lazylabel/ui/hotkey_dialog.py,sha256=3QkthYil_SWYWxRGL_U8cZCsQ4y-6SExQZXJuE5aO8s,15252
17
17
  lazylabel/ui/hoverable_pixelmap_item.py,sha256=kJFOp7WXiyHpNf7l73TZjiob85jgP30b5MZvu_z5L3c,728
18
18
  lazylabel/ui/hoverable_polygon_item.py,sha256=hQKax3vzhtrdB5ThwTINjOCwOYy718zw5YZPLCfLnGM,1251
19
- lazylabel/ui/main_window.py,sha256=DVBmTtGd8EoiN-Qhl_Cx3o9ajNENyAf-OnYnHTs3mOI,52596
19
+ lazylabel/ui/main_window.py,sha256=zjpTH-RqBx5mJ1i1Y0CC8KepgQF28mIJDYc68CUoBIk,64488
20
20
  lazylabel/ui/numeric_table_widget_item.py,sha256=dQUlIFu9syCxTGAHVIlmbgkI7aJ3f3wmDPBz1AGK9Bg,283
21
21
  lazylabel/ui/photo_viewer.py,sha256=PNgm0gU2gnIqvRkrGlQugdobGsKwAi3m3X6ZF487lCo,2055
22
22
  lazylabel/ui/reorderable_class_table.py,sha256=4c-iuSkPcmk5Aey5n2zz49O85x9TQPujKG-JLxtuBCo,2406
23
- lazylabel/ui/right_panel.py,sha256=m5PBRtzwB2x8CKtLzRwVYAsp1Mq-hvIGl7KEGMCcLrg,9988
24
- lazylabel/ui/widgets/__init__.py,sha256=O4FFoTYecZ_dUIpNjqNBVmG5b3HLhv-gYNW7cevbtsE,264
23
+ lazylabel/ui/right_panel.py,sha256=7ksUM7eItHrdXWkuDHohXEShdYYR2FYx-zeSmbfi620,12454
24
+ lazylabel/ui/widgets/__init__.py,sha256=5wJ09bTPlhqHyBIXGDeXiNJf33YelKKLu0aPrar9AxU,314
25
25
  lazylabel/ui/widgets/adjustments_widget.py,sha256=Az8GZgu4Uvhm6nEnwjiYDyShOqwieinjFnTOiUfxdzo,3940
26
26
  lazylabel/ui/widgets/model_selection_widget.py,sha256=X3qVH90yCaCpLDauj-DLWJgAwAkAVQrzhG9X5mESa-o,3590
27
27
  lazylabel/ui/widgets/settings_widget.py,sha256=8zhjLxUxqFqxqMYDzkXWD1Ye5V-a7HNhPjPJjYBxeZw,4361
28
+ lazylabel/ui/widgets/status_bar.py,sha256=71paNOXlxXmWbCG6luyciXRmqC7DNFYDi_Eo2HDzjOg,4026
28
29
  lazylabel/utils/__init__.py,sha256=SX_aZvmFojIJ4Lskat9ly0dmFBXgN7leBdmc68aDLpg,177
29
30
  lazylabel/utils/custom_file_system_model.py,sha256=zK0Z4LY2hzYVtycDWsCLEhXZ0zKZz-Qy5XGwHYrqazQ,4867
30
31
  lazylabel/utils/utils.py,sha256=sYSCoXL27OaLgOZaUkCAhgmKZ7YfhR3Cc5F8nDIa3Ig,414
31
- lazylabel_gui-1.1.0.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
32
- lazylabel_gui-1.1.0.dist-info/METADATA,sha256=HT1KUNRWJsGUjtU8OhcEcIyK8W9TiMqB_00cmpQElfE,8473
33
- lazylabel_gui-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
34
- lazylabel_gui-1.1.0.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
35
- lazylabel_gui-1.1.0.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
36
- lazylabel_gui-1.1.0.dist-info/RECORD,,
32
+ lazylabel_gui-1.1.1.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
33
+ lazylabel_gui-1.1.1.dist-info/METADATA,sha256=RMI2kMGM08gRUJqkKXrMNbkKvmNDawmvjRCutT_Y0bM,8473
34
+ lazylabel_gui-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ lazylabel_gui-1.1.1.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
36
+ lazylabel_gui-1.1.1.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
37
+ lazylabel_gui-1.1.1.dist-info/RECORD,,