feat: persistent Library tab in ScanResultsPanel (survives per-file rebuilds)

This commit is contained in:
2026-07-04 00:20:23 +02:00
parent 5dc7499d7f
commit f32d303d26
2 changed files with 55 additions and 5 deletions
+25 -5
View File
@@ -897,9 +897,10 @@ class ScanResultsPanel(QWidget):
# col 0: UserRole+2 = disabled (bool)
# col 1: UserRole = end_time (float)
def __init__(self, db, parent=None):
def __init__(self, db, settings=None, parent=None):
super().__init__(parent)
self._db = db
self._settings = settings or QSettings("8cut", "8cut")
self._filename = ""
self._profile = ""
self._neg_times: set[float] = set()
@@ -916,6 +917,10 @@ class ScanResultsPanel(QWidget):
self._tabs.currentChanged.connect(lambda: self.tab_changed.emit())
layout.addWidget(self._tabs)
# Persistent Library tab (index 0) — survives per-file model-tab rebuilds.
self._library = AudioLibraryTab(self._settings, key="audio_library")
self._tabs.addTab(self._library, "Library")
btn_row = QHBoxLayout()
self._btn_neg = QPushButton("Add to Negatives")
self._btn_neg.setToolTip("Mark selected rows as hard-negative training examples")
@@ -963,6 +968,12 @@ class ScanResultsPanel(QWidget):
return table
return None
def _clear_model_tabs(self) -> None:
"""Remove all per-model result tabs but keep the persistent Library tab."""
for i in range(self._tabs.count() - 1, -1, -1):
if self._tabs.widget(i) is not self._library:
self._tabs.removeTab(i)
def load_for_file(self, filename: str, profile: str) -> None:
"""Load saved scan results for a file — DB reads run off the UI thread,
the table rebuild happens in _on_scan_bundle_loaded when they finish."""
@@ -970,7 +981,7 @@ class ScanResultsPanel(QWidget):
self._profile = profile
# Show an empty panel immediately; the worker fills it in shortly.
self._tabs.blockSignals(True)
self._tabs.clear()
self._clear_model_tabs()
self._tabs.blockSignals(False)
self._neg_times = set()
self._exported_times = []
@@ -996,10 +1007,14 @@ class ScanResultsPanel(QWidget):
self._neg_times = neg
self._exported_times = exported
self._tabs.blockSignals(True)
self._tabs.clear()
self._clear_model_tabs()
for model, rows in results.items():
self._add_tab(model, rows)
self._populate_version_combos()
# Select the first model tab (index 1), not the persistent Library at 0,
# so _current_table()/current_regions_with_orig() resolve before `loaded`.
if self._tabs.count() > 1:
self._tabs.setCurrentIndex(1)
self._tabs.blockSignals(False)
self.loaded.emit(filename)
@@ -1215,6 +1230,9 @@ class ScanResultsPanel(QWidget):
def current_model_name(self) -> str:
"""Return the model name of the currently active tab."""
# A non-table tab (e.g. the persistent Library) has no model name.
if self._current_table() is None:
return ""
idx = self._tabs.currentIndex()
if idx >= 0:
return self._tabs.tabText(idx).split(" (")[0]
@@ -1642,7 +1660,9 @@ class ScanResultsPanel(QWidget):
return out
def has_results(self) -> bool:
return self._tabs.count() > 0
# Count only per-model result tabs, not the persistent Library tab.
return any(self._tabs.widget(i) is not self._library
for i in range(self._tabs.count()))
def undo(self) -> None:
"""Pop the last action from the undo stack and revert it."""
@@ -5276,7 +5296,7 @@ class MainWindow(QMainWindow):
left_layout.addWidget(self._list_stack)
# Scan results panel (right side)
self._scan_panel = ScanResultsPanel(self._db)
self._scan_panel = ScanResultsPanel(self._db, self._settings)
self._scan_panel.seek_requested.connect(self._on_scan_seek)
self._scan_panel.active_region_changed.connect(
self._timeline.set_active_scan_region)