typos, standardization, and file association for project extensions

This commit is contained in:
2026-08-06 02:00:36 -07:00
parent 68e34484ee
commit 074a0681b9
15 changed files with 539 additions and 38 deletions
+1 -2
View File
@@ -21,7 +21,7 @@ from mne.io.base import BaseRaw
from flares import aggregate_fnirs_group_geometry, plot_fir_model_results, brain_3d_visualization
from src.shared.flaresbasewidget import InterGroupUIMixin, FlaresBaseWidget
from src.shared.shareddata import APP_NAME
from mne.io import BaseRaw
PARAMETERIZED_INDEXES: dict[int, list[dict[str, Any]]] = {
0: [
@@ -81,7 +81,6 @@ PARAMETERIZED_INDEXES: dict[int, list[dict[str, Any]]] = {
}
class InterGroupBrainImageWidget(InterGroupUIMixin, FlaresBaseWidget):
def __init__(
self,
@@ -39,7 +39,6 @@ PARAMETERIZED_INDEXES: dict[int, list[dict[str, Any]]] = {
}
class InterGroupFunctionalConnectivityWidget(InterGroupUIMixin, FlaresBaseWidget):
def __init__(
self,
-1
View File
@@ -157,7 +157,6 @@ DESCRIPTION = """0. ROI vs. Zero (run_roi_second_level_analysis)
class InterGroupStatsWidget(InterGroupUIMixin, FlaresBaseWidget):
def __init__(
self,
haemo_dict: dict[str | Path, BaseRaw],
@@ -87,7 +87,6 @@ PARAMETERIZED_INDEXES: dict[int, list[dict[str, Any]]] = {
}
class ParticipantFunctionalConnectivityWidget(ParticipantUIMixin, FlaresBaseWidget):
def __init__(
self,
@@ -106,7 +105,6 @@ class ParticipantFunctionalConnectivityWidget(ParticipantUIMixin, FlaresBaseWidg
self.setup_participant_ui(["0 (Spectral Connectivity Epochs)", "1 (Envelope Correlation)", "2 (Betas)", "3 (Spectral Connectivity Epochs)",])
def process_request(self):
request = self.get_common_request_data(PARAMETERIZED_INDEXES)
if request is None:
@@ -138,7 +136,6 @@ class ParticipantFunctionalConnectivityWidget(ParticipantUIMixin, FlaresBaseWidg
print(f"Skipping {self.participant_map[file_path]}: Event '{selected_event}' not found.")
continue
for idx in selected_indexes:
if idx == 0:
-1
View File
@@ -85,7 +85,6 @@ class ParticipantImageViewerWidget(FlaresBaseWidget):
self.showMaximized()
def show_selected_images(self):
# Clear previous images
while self.grid_layout.count():
+2
View File
@@ -7,11 +7,13 @@ Author: Tyler de Zeeuw
License: GPL-3.0
"""
# External library imports
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
from PySide6.QtCore import Qt
from src.shared.shareddata import APP_NAME, APP_NAME_EXPANDED, CURRENT_VERSION
class AboutWindow(QWidget):
"""
Simple About window displaying basic application information.
+64 -2
View File
@@ -7,16 +7,38 @@ Author: Tyler de Zeeuw
License: GPL-3.0
"""
# Built-in imports
from typing import Any, Callable
# External library imports
from PySide6.QtWidgets import QWidget, QVBoxLayout, QTextEdit, QLineEdit
from PySide6.QtCore import Qt
from PySide6.QtCore import Qt, QThread, Signal
from file_ext_registration import register_file_association, is_windows_admin
from src.shared.shareddata import API_URL, API_URL_SECONDARY, APP_NAME, CURRENT_VERSION, PLATFORM_NAME
from src.window.about import AboutWindow
from updater import UpdateManager
class _AssocWorker(QThread):
"""
Runs register_file_association() off the UI thread. Only actually
needed for the force_admin=True path, since that blocks on
WaitForSingleObject while the UAC prompt is up and the elevated
child process runs — which would otherwise freeze the terminal
window. Used for the non-elevated path too for consistency.
"""
result_ready = Signal(bool, str)
def __init__(self, force_admin: bool, parent: QWidget | None = None) -> None:
super().__init__(parent)
self._force_admin = force_admin
def run(self) -> None:
ok, msg = register_file_association(force_admin=self._force_admin)
self.result_ready.emit(ok, msg)
class TerminalWindow(QWidget):
def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent, Qt.WindowType.Window)
@@ -38,9 +60,13 @@ class TerminalWindow(QWidget):
"help": self.cmd_help,
"version": self.cmd_version,
"about": self.cmd_about,
"assoc": self.cmd_assoc,
"update": self.cmd_update,
}
self._pending_assoc_confirmation: bool = False
self._assoc_worker: _AssocWorker | None = None
self.output_area.append(f"Welcome to {APP_NAME.upper()}. You are running version {CURRENT_VERSION}.")
self.output_area.append("Type 'help' for a list of available commands.\n")
@@ -52,6 +78,12 @@ class TerminalWindow(QWidget):
self.input_line.clear()
self.output_area.append(f"> {command_text}")
if self._pending_assoc_confirmation:
self._pending_assoc_confirmation = False
self._handle_assoc_confirmation(command_text.strip().lower())
return
parts = command_text.strip().split()
if not parts:
return
@@ -101,4 +133,34 @@ class TerminalWindow(QWidget):
self.output_area.append("Checking for updates...")
self.updater.manual_check_for_updates()
return "See status bar for update information."
return "See status bar for update information."
def cmd_assoc(self, *args: Any) -> str | None:
# Non-Windows platforms don't have the admin/non-admin split —
# just register directly.
if PLATFORM_NAME != "windows" or is_windows_admin():
self._run_assoc(force_admin=False)
return None
self._pending_assoc_confirmation = True
return "Not running as admin. Register system-wide via UAC elevation? (y/n)"
def _handle_assoc_confirmation(self, answer: str) -> None:
if answer in ("y", "yes"):
self._run_assoc(force_admin=True)
elif answer in ("n", "no"):
self._run_assoc(force_admin=False)
else:
self.output_area.append("Please answer 'y' or 'n'. Run 'assoc' again to retry.")
def _run_assoc(self, force_admin: bool) -> None:
if force_admin:
self.output_area.append("Requesting elevation. Check for a UAC prompt...")
self._assoc_worker = _AssocWorker(force_admin=force_admin, parent=self)
self._assoc_worker.result_ready.connect(self._on_assoc_result)
self._assoc_worker.start()
def _on_assoc_result(self, ok: bool, msg: str) -> None:
self.output_area.append(msg)
self._assoc_worker = None
+3 -1
View File
@@ -1,11 +1,13 @@
"""
Filename: userguide.py
Description: User guide for FLARES
Description: User guide window
Note: Compliant with pylance strict type checking
Author: Tyler de Zeeuw
License: GPL-3.0
"""
# External library imports
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
from PySide6.QtCore import Qt
+5 -4
View File
@@ -1,18 +1,19 @@
"""
Filename: welcome.py
Description: Welcome dialog for FLARES
Description: Welcome dialog window
Note: Compliant with pylance strict type checking
Author: Tyler de Zeeuw
License: GPL-3.0
"""
# External library imports
from PySide6.QtWidgets import QTextBrowser, QVBoxLayout, QLabel, QDialog, QHBoxLayout, QPushButton
from PySide6.QtGui import QDesktopServices, QIcon
from PySide6.QtCore import QUrl
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from src.shared.shareddata import APP_NAME, CURRENT_VERSION, CHANGELOG_URL, resource_path
from src.shared.shareddata import APP_NAME, PLATFORM_NAME, CURRENT_VERSION, CHANGELOG_URL, resource_path
class WelcomeDialog(QDialog):
@@ -27,8 +28,8 @@ class WelcomeDialog(QDialog):
header_layout = QHBoxLayout()
logo_label = QLabel(self)
# NOTE: might not work on mac and need the icns file
logo_label.setPixmap(QIcon(resource_path("icons/main.ico")).pixmap(48, 48))
icon_ext = "icns" if PLATFORM_NAME == "darwin" else "ico"
logo_label.setPixmap(QIcon(resource_path(f"icons/main.{icon_ext}")).pixmap(48, 48))
if first:
title_label = QLabel(f"<h2>Welcome to {APP_NAME.upper()}!</h2>", self)
elif direct: