mainly whitespace, but also some generic qol improvements

This commit is contained in:
tyler committed 2026-10-14 20:17:23 -07:00
1 parent 2a5e3f5606
commit 3a8ffbdf70
26 files changed
+1871 -1224

No files matched your search

+75 -16
View File
@@ -38,6 +38,23 @@ if TYPE_CHECKING:
from main import MainApplication
class LoadProjectThread(QThread):
finished_signal = Signal(object) # Emits the loaded project data dictionary
error_signal = Signal(str) # Emits the error message string
def __init__(self, filename: str) -> None:
super().__init__()
self.filename = filename
def run(self) -> None:
try:
with open(self.filename, "rb") as f:
project_data = pickle.load(f)
self.finished_signal.emit(project_data)
except Exception as e:
self.error_signal.emit(str(e))
class SaveProjectThread(QThread):
finished_signal = Signal(str)
error_signal = Signal(str)
@@ -56,6 +73,25 @@ class SaveProjectThread(QThread):
self.error_signal.emit(str(e))
class LoadingOverlay(QDialog):
def __init__(self, parent: Optional[QWidget] = None) -> None:
super().__init__(parent)
self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.FramelessWindowHint)
self.setModal(True)
self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
label = QLabel("Loading Project…")
label.setStyleSheet(
"font-size: 18px; color: white; background-color: rgba(0,0,0,150);"
" padding: 20px; border-radius: 10px;"
)
layout.addWidget(label)
self.setLayout(layout)
class SavingOverlay(QDialog):
def __init__(self, parent: Optional[QWidget] = None) -> None:
@@ -64,7 +100,7 @@ class SavingOverlay(QDialog):
self.setModal(True)
self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
@@ -72,7 +108,7 @@ class SavingOverlay(QDialog):
label.setStyleSheet("font-size: 18px; color: white; background-color: rgba(0,0,0,150); padding: 20px; border-radius: 10px;")
layout.addWidget(label)
self.setLayout(layout)
class ProjectManager:
"""
@@ -118,7 +154,7 @@ class ProjectManager:
return f.read(8) == b"\x89HDF\r\n\x1a\n"
except Exception:
return False
def open_file_dialog(self) -> None:
"""Opens dialog to pick a single .snirf file."""
file_path, _ = QFileDialog.getOpenFileName(
@@ -171,6 +207,8 @@ class ProjectManager:
)
return
self._load_files_into_pipeline(snirf_files)
def load_dropped_files(self, file_paths: List[str]) -> None:
"""Public entry point for handling files or folders dropped onto the UI."""
if not file_paths:
@@ -217,7 +255,7 @@ class ProjectManager:
# Delegate to internal pipeline
self._load_files_into_pipeline(valid_files)
def _load_files_into_pipeline(self, file_paths: List[str]) -> None:
"""Loads .snirf files into UI using chunked batches and background workers."""
app = self.app
@@ -243,7 +281,7 @@ class ProjectManager:
# Filter out duplicates AND non-SNIRF files (including macOS ._ shadow files)
new_files = [
p for p in file_paths
p for p in file_paths
if p not in app.selected_paths and self.is_valid_snirf(p)
]
if not new_files:
@@ -339,12 +377,31 @@ class ProjectManager:
self.load_project(filename)
def load_project(self, filename: str) -> None:
"""Loads a .flare project file into the application."""
"""Triggers asynchronous loading of a .flare project file."""
app = self.app
# 1. Show the custom loading overlay matching your saver design
self.loading_overlay = LoadingOverlay(app)
self.loading_overlay.resize(app.size())
self.loading_overlay.move(app.pos())
self.loading_overlay.show()
# 2. Fire up the background thread for pickle loading
self.loader_thread = LoadProjectThread(filename)
self.loader_thread.finished_signal.connect(
lambda data: self._handle_loaded_data(filename, data)
)
self.loader_thread.error_signal.connect(self._handle_load_error)
self.loader_thread.start()
def _handle_loaded_data(self, filename: str, data: dict) -> None:
# Close overlay
if hasattr(self, "loading_overlay"):
self.loading_overlay.close()
self.loading_overlay.deleteLater()
app = self.app
try:
with open(filename, "rb") as f:
data = pickle.load(f)
checks = [
("version", "<=1.1.7"),
("file_metadata", "<=1.2.2"),
@@ -358,7 +415,7 @@ class ProjectManager:
f"This project was saved in an earlier version of {APP_NAME.upper()} ({ver_str}) "
"and is potentially not compatible with this version. "
)
if getattr(app, "incompatible_save_bypass", False):
if getattr(app, "processing_incompatible_save_bypass", False):
QMessageBox.warning(
app, f"Warning - {APP_NAME.upper()}", msg + "Attempting load."
)
@@ -438,16 +495,19 @@ class ProjectManager:
if hasattr(app, "button3"):
app.button3.setVisible(has_data)
self.add_to_recent_projects(os.path.normpath(filename))
# Reset baselines cleanly
self.reset_all_dirty_states()
QMessageBox.information(app, "Loaded", f"Project loaded from:\n{filename}")
except Exception as e:
QMessageBox.critical(app, "Error", f"Failed to load project:\n{e}")
QMessageBox.critical(app, "Error", f"Failed to process loaded project data:\n{e}")
def _handle_load_error(self, error_msg: str) -> None:
if hasattr(self, "loading_overlay"):
self.loading_overlay.close()
self.loading_overlay.deleteLater()
QMessageBox.critical(self.app, "Error", f"Failed to read project file:\n{error_msg}")
# =========================================================================
# Project Saving (Save / Save As)
@@ -863,7 +923,6 @@ def _get_bids_demographics(snirf_path: str) -> dict[str, str]:
return {}
def extract_metadata_worker(file_name: str) -> dict[str, Any]:
"""Runs in the separate worker process. Returns a clean dict."""
@@ -921,7 +980,7 @@ def extract_metadata_worker(file_name: str) -> dict[str, Any]:
if "hand" in demographics:
snirf_info["BIDS - Handedness"] = demographics["hand"]
return snirf_info
except Exception as e:
print(f"Worker safely caught failure on {file_name}: {str(e)}")
return {'status': 'error', 'reason': str(e)}