7d98759b43
- BatchExport worker + BatchExportController (threaded, busy flag) - SourcePanel: Export Maps button → FolderDialog → batch export with progress/summary banner (dismissible) - StreamControlPanel: name single export after loaded CSV + timestamp
63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import threading
|
|
|
|
from PySide6.QtCore import Property, QObject, Qt, Signal, Slot
|
|
|
|
from pygui.backend.utils import slot_error_boundary
|
|
from pygui.backend.wafer.batch_export import BatchExportResult, export_batch
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class BatchExportController(QObject):
|
|
busyChanged = Signal()
|
|
exportFinished = Signal(str)
|
|
|
|
_batchFinished = Signal(list)
|
|
|
|
def __init__(self, parent: QObject | None = None) -> None:
|
|
super().__init__(parent)
|
|
self._busy = False
|
|
self._batchFinished.connect(self._handle_batch_finished, Qt.ConnectionType.QueuedConnection)
|
|
|
|
@Property(bool, notify=busyChanged)
|
|
def busy(self) -> bool:
|
|
return self._busy
|
|
|
|
@Slot("QVariantList", str)
|
|
def start(self, file_paths: list, output_dir: str) -> None:
|
|
if self._busy:
|
|
return
|
|
self._busy = True
|
|
self.busyChanged.emit()
|
|
threading.Thread(
|
|
target=self._worker, args=(list(file_paths), output_dir), daemon=True
|
|
).start()
|
|
|
|
def _worker(self, file_paths: list[str], output_dir: str) -> None:
|
|
try:
|
|
results = export_batch(file_paths, output_dir)
|
|
except Exception as exc:
|
|
log.exception("Batch export worker crashed: %s", exc)
|
|
results = []
|
|
self._batchFinished.emit(results)
|
|
|
|
@Slot(list)
|
|
@slot_error_boundary
|
|
def _handle_batch_finished(self, results: list[BatchExportResult]) -> None:
|
|
try:
|
|
total = len(results)
|
|
succeeded = sum(1 for r in results if r.success)
|
|
failed = total - succeeded
|
|
summary = (
|
|
f"Exported {succeeded}/{total} — {failed} failed"
|
|
if failed
|
|
else f"Exported {succeeded}/{total}"
|
|
)
|
|
self.exportFinished.emit(summary)
|
|
finally:
|
|
self._busy = False
|
|
self.busyChanged.emit()
|