functional connectivity, pylance, and other improvements
This commit is contained in:
+26
-23
@@ -6,19 +6,22 @@ Author: Tyler de Zeeuw
|
||||
License: GPL-3.0
|
||||
"""
|
||||
|
||||
# Built-in imports
|
||||
import os
|
||||
import json
|
||||
from enum import Enum, auto
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
# External library imports
|
||||
import numpy as np
|
||||
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton, QComboBox, QHBoxLayout, QMessageBox, QFileDialog
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from mne import Annotations
|
||||
from mne.io import read_raw_snirf
|
||||
from mne_nirs.io import write_raw_snirf
|
||||
from mne.io import read_raw_snirf #type: ignore
|
||||
from mne_nirs.io import write_raw_snirf #type: ignore
|
||||
|
||||
from src.shared.shareddata import APP_NAME
|
||||
|
||||
@@ -29,7 +32,7 @@ class EventUpdateMode(Enum):
|
||||
|
||||
|
||||
class UpdateEventsWindow(QWidget):
|
||||
def __init__(self, parent=None, mode=EventUpdateMode.WRITE_SNIRF, caller=None):
|
||||
def __init__(self, parent: Optional[QWidget]=None, mode=EventUpdateMode.WRITE_SNIRF, caller=None):
|
||||
super().__init__(parent, Qt.WindowType.Window)
|
||||
|
||||
self.mode = mode
|
||||
@@ -91,7 +94,7 @@ class UpdateEventsWindow(QWidget):
|
||||
help_btn_a = QPushButton("?")
|
||||
help_btn_a.setFixedWidth(25)
|
||||
help_btn_a.setToolTip(help_text_a)
|
||||
help_btn_a.clicked.connect(lambda _, text=help_text_a: self.show_help_popup(text))
|
||||
help_btn_a.clicked.connect(lambda: self.show_help_popup(help_text_a))
|
||||
file_a_layout.addWidget(help_btn_a)
|
||||
|
||||
# Container for label + line_edit + browse button with tooltip
|
||||
@@ -114,7 +117,7 @@ class UpdateEventsWindow(QWidget):
|
||||
help_btn_b = QPushButton("?")
|
||||
help_btn_b.setFixedWidth(25)
|
||||
help_btn_b.setToolTip(help_text_b)
|
||||
help_btn_b.clicked.connect(lambda _, text=help_text_b: self.show_help_popup(text))
|
||||
help_btn_b.clicked.connect(lambda: self.show_help_popup(help_text_b))
|
||||
file_b_layout.addWidget(help_btn_b)
|
||||
|
||||
file_b_container = QWidget()
|
||||
@@ -136,7 +139,7 @@ class UpdateEventsWindow(QWidget):
|
||||
help_btn_suffix = QPushButton("?")
|
||||
help_btn_suffix.setFixedWidth(25)
|
||||
help_btn_suffix.setToolTip(help_text_suffix)
|
||||
help_btn_suffix.clicked.connect(lambda _, text=help_text_suffix: self.show_help_popup(text))
|
||||
help_btn_suffix.clicked.connect(lambda: self.show_help_popup(help_text_suffix))
|
||||
suffix_layout.addWidget(help_btn_suffix)
|
||||
|
||||
suffix_container = QWidget()
|
||||
@@ -157,7 +160,7 @@ class UpdateEventsWindow(QWidget):
|
||||
help_btn_suffix = QPushButton("?")
|
||||
help_btn_suffix.setFixedWidth(25)
|
||||
help_btn_suffix.setToolTip(help_text_suffix)
|
||||
help_btn_suffix.clicked.connect(lambda _, text=help_text_suffix: self.show_help_popup(text))
|
||||
help_btn_suffix.clicked.connect(lambda: self.show_help_popup(help_text_suffix))
|
||||
suffix2_layout.addWidget(help_btn_suffix)
|
||||
|
||||
suffix2_container = QWidget()
|
||||
@@ -177,7 +180,7 @@ class UpdateEventsWindow(QWidget):
|
||||
help_btn_snirf_events = QPushButton("?")
|
||||
help_btn_snirf_events.setFixedWidth(25)
|
||||
help_btn_snirf_events.setToolTip(help_text_snirf_events)
|
||||
help_btn_snirf_events.clicked.connect(lambda _, text=help_text_snirf_events: self.show_help_popup(text))
|
||||
help_btn_snirf_events.clicked.connect(lambda: self.show_help_popup(help_text_snirf_events))
|
||||
snirf_events_layout.addWidget(help_btn_snirf_events)
|
||||
|
||||
snirf_events_container = QWidget()
|
||||
@@ -199,13 +202,13 @@ class UpdateEventsWindow(QWidget):
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def show_help_popup(self, text):
|
||||
def show_help_popup(self, text: str) -> None:
|
||||
msg = QMessageBox(self)
|
||||
msg.setWindowTitle(f"Parameter Info - {APP_NAME.upper()}")
|
||||
msg.setText(text)
|
||||
msg.exec()
|
||||
|
||||
def browse_file_a(self):
|
||||
def browse_file_a(self) -> None:
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "Select SNIRF File", "", "SNIRF Files (*.snirf)")
|
||||
if file_path:
|
||||
self.line_edit_file_a.setText(file_path)
|
||||
@@ -235,7 +238,7 @@ class UpdateEventsWindow(QWidget):
|
||||
self.combo_snirf_events.clear()
|
||||
self.combo_snirf_events.setEnabled(False)
|
||||
|
||||
def browse_file_b(self):
|
||||
def browse_file_b(self) -> None:
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "Select BORIS File", "", "BORIS project Files (*.boris)")
|
||||
if file_path:
|
||||
self.line_edit_file_b.setText(file_path)
|
||||
@@ -288,11 +291,11 @@ class UpdateEventsWindow(QWidget):
|
||||
self.combo_events.addItems(event_entries)
|
||||
self.combo_events.setEnabled(bool(event_entries))
|
||||
|
||||
def clear_files(self):
|
||||
def clear_files(self) -> None:
|
||||
self.line_edit_file_a.clear()
|
||||
self.line_edit_file_b.clear()
|
||||
|
||||
def go_action(self):
|
||||
def go_action(self) -> None:
|
||||
|
||||
file_a = self.line_edit_file_a.text()
|
||||
suffix = "flare"
|
||||
@@ -540,7 +543,7 @@ class UpdateEventsWindow(QWidget):
|
||||
|
||||
class UpdateEventsBlazesWindow(QWidget):
|
||||
|
||||
def __init__(self, parent=None, mode=EventUpdateMode.WRITE_SNIRF, caller=None):
|
||||
def __init__(self, parent: Optional[QWidget]=None, mode=EventUpdateMode.WRITE_SNIRF, caller=None):
|
||||
super().__init__(parent, Qt.WindowType.Window)
|
||||
|
||||
self.mode = mode
|
||||
@@ -595,7 +598,7 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
help_btn_a = QPushButton("?")
|
||||
help_btn_a.setFixedWidth(25)
|
||||
help_btn_a.setToolTip(help_text_a)
|
||||
help_btn_a.clicked.connect(lambda _, text=help_text_a: self.show_help_popup(text))
|
||||
help_btn_a.clicked.connect(lambda: self.show_help_popup(help_text_a))
|
||||
file_a_layout.addWidget(help_btn_a)
|
||||
|
||||
# Container for label + line_edit + browse button with tooltip
|
||||
@@ -618,7 +621,7 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
help_btn_b = QPushButton("?")
|
||||
help_btn_b.setFixedWidth(25)
|
||||
help_btn_b.setToolTip(help_text_b)
|
||||
help_btn_b.clicked.connect(lambda _, text=help_text_b: self.show_help_popup(text))
|
||||
help_btn_b.clicked.connect(lambda: self.show_help_popup(help_text_b))
|
||||
file_b_layout.addWidget(help_btn_b)
|
||||
|
||||
file_b_container = QWidget()
|
||||
@@ -640,7 +643,7 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
help_btn_suffix = QPushButton("?")
|
||||
help_btn_suffix.setFixedWidth(25)
|
||||
help_btn_suffix.setToolTip(help_text_suffix)
|
||||
help_btn_suffix.clicked.connect(lambda _, text=help_text_suffix: self.show_help_popup(text))
|
||||
help_btn_suffix.clicked.connect(lambda: self.show_help_popup(help_text_suffix))
|
||||
suffix2_layout.addWidget(help_btn_suffix)
|
||||
|
||||
suffix2_container = QWidget()
|
||||
@@ -660,7 +663,7 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
help_btn_snirf_events = QPushButton("?")
|
||||
help_btn_snirf_events.setFixedWidth(25)
|
||||
help_btn_snirf_events.setToolTip(help_text_snirf_events)
|
||||
help_btn_snirf_events.clicked.connect(lambda _, text=help_text_snirf_events: self.show_help_popup(text))
|
||||
help_btn_snirf_events.clicked.connect(lambda: self.show_help_popup(help_text_snirf_events))
|
||||
snirf_events_layout.addWidget(help_btn_snirf_events)
|
||||
|
||||
snirf_events_container = QWidget()
|
||||
@@ -683,13 +686,13 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
def show_help_popup(self, text):
|
||||
def show_help_popup(self, text: str) -> None:
|
||||
msg = QMessageBox(self)
|
||||
msg.setWindowTitle(f"Parameter Info - {APP_NAME.upper()}")
|
||||
msg.setText(text)
|
||||
msg.exec()
|
||||
|
||||
def browse_file_a(self):
|
||||
def browse_file_a(self) -> None:
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "Select SNIRF File", "", "SNIRF Files (*.snirf)")
|
||||
if file_path:
|
||||
self.line_edit_file_a.setText(file_path)
|
||||
@@ -719,7 +722,7 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
self.combo_snirf_events.clear()
|
||||
self.combo_snirf_events.setEnabled(False)
|
||||
|
||||
def browse_file_b(self):
|
||||
def browse_file_b(self) -> None:
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "Select JSON Timeline File", "", "JSON Files (*.json)")
|
||||
if file_path:
|
||||
self.line_edit_file_b.setText(file_path)
|
||||
@@ -762,12 +765,12 @@ class UpdateEventsBlazesWindow(QWidget):
|
||||
return event_strings
|
||||
|
||||
|
||||
def clear_files(self):
|
||||
def clear_files(self) -> None:
|
||||
self.line_edit_file_a.clear()
|
||||
self.line_edit_file_b.clear()
|
||||
|
||||
|
||||
def go_action(self):
|
||||
def go_action(self) -> None:
|
||||
file_a = self.line_edit_file_a.text()
|
||||
file_b = self.line_edit_file_b.text()
|
||||
suffix = APP_NAME
|
||||
|
||||
+33
-18
@@ -1,16 +1,21 @@
|
||||
"""
|
||||
Filename: updateoptodes.py
|
||||
Description: Methods to update optode locations for FLARES
|
||||
Note: Compliant with pylance strict type checking
|
||||
|
||||
Author: Tyler de Zeeuw
|
||||
License: GPL-3.0
|
||||
"""
|
||||
|
||||
# Built-in imports
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Union
|
||||
|
||||
# External library imports
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout, QMessageBox, QLineEdit, QPushButton, QFileDialog
|
||||
from PySide6.QtCore import Qt
|
||||
@@ -24,7 +29,7 @@ from src.shared.shareddata import APP_NAME
|
||||
|
||||
class UpdateOptodesWindow(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent: Optional[QWidget] = None) -> None:
|
||||
super().__init__(parent, Qt.WindowType.Window)
|
||||
self.setWindowTitle(f"Update optode positions - {APP_NAME.upper()}")
|
||||
self.resize(760, 200)
|
||||
@@ -50,7 +55,6 @@ class UpdateOptodesWindow(QWidget):
|
||||
self.btn_clear.clicked.connect(self.clear_files)
|
||||
self.btn_go.clicked.connect(self.go_action)
|
||||
|
||||
# ---
|
||||
layout = QVBoxLayout()
|
||||
self.description = QLabel()
|
||||
self.description.setTextFormat(Qt.TextFormat.RichText)
|
||||
@@ -75,7 +79,7 @@ class UpdateOptodesWindow(QWidget):
|
||||
help_btn_a = QPushButton("?")
|
||||
help_btn_a.setFixedWidth(25)
|
||||
help_btn_a.setToolTip(help_text_a)
|
||||
help_btn_a.clicked.connect(lambda _, text=help_text_a: self.show_help_popup(text))
|
||||
help_btn_a.clicked.connect(lambda: self.show_help_popup(help_text_a))
|
||||
file_a_layout.addWidget(help_btn_a)
|
||||
|
||||
# Container for label + line_edit + browse button with tooltip
|
||||
@@ -98,7 +102,7 @@ class UpdateOptodesWindow(QWidget):
|
||||
help_btn_b = QPushButton("?")
|
||||
help_btn_b.setFixedWidth(25)
|
||||
help_btn_b.setToolTip(help_text_b)
|
||||
help_btn_b.clicked.connect(lambda _, text=help_text_b: self.show_help_popup(text))
|
||||
help_btn_b.clicked.connect(lambda: self.show_help_popup(help_text_b))
|
||||
file_b_layout.addWidget(help_btn_b)
|
||||
|
||||
file_b_container = QWidget()
|
||||
@@ -121,7 +125,7 @@ class UpdateOptodesWindow(QWidget):
|
||||
help_btn_suffix = QPushButton("?")
|
||||
help_btn_suffix.setFixedWidth(25)
|
||||
help_btn_suffix.setToolTip(help_text_suffix)
|
||||
help_btn_suffix.clicked.connect(lambda _, text=help_text_suffix: self.show_help_popup(text))
|
||||
help_btn_suffix.clicked.connect(lambda: self.show_help_popup(help_text_suffix))
|
||||
suffix_layout.addWidget(help_btn_suffix)
|
||||
|
||||
suffix_container = QWidget()
|
||||
@@ -143,13 +147,13 @@ class UpdateOptodesWindow(QWidget):
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def show_help_popup(self, text):
|
||||
def show_help_popup(self, text: str) -> None:
|
||||
msg = QMessageBox(self)
|
||||
msg.setWindowTitle(f"Parameter Info - {APP_NAME.upper()}")
|
||||
msg.setText(text)
|
||||
msg.exec()
|
||||
|
||||
def handle_link_click(self, link):
|
||||
def handle_link_click(self, link: str) -> None:
|
||||
if link == "custom_link":
|
||||
msg = QMessageBox(self)
|
||||
msg.setWindowTitle("Example Digitization File")
|
||||
@@ -166,21 +170,21 @@ class UpdateOptodesWindow(QWidget):
|
||||
msg.setText(text)
|
||||
msg.exec()
|
||||
|
||||
def browse_file_a(self):
|
||||
def browse_file_a(self) -> None:
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "Select SNIRF File", "", "SNIRF Files (*.snirf)")
|
||||
if file_path:
|
||||
self.line_edit_file_a.setText(file_path)
|
||||
|
||||
def browse_file_b(self):
|
||||
def browse_file_b(self) -> None:
|
||||
file_path, _ = QFileDialog.getOpenFileName(self, "Select File", "", "Supported Files (*.txt *.xlsx)")
|
||||
if file_path:
|
||||
self.line_edit_file_b.setText(file_path)
|
||||
|
||||
def clear_files(self):
|
||||
def clear_files(self) -> None:
|
||||
self.line_edit_file_a.clear()
|
||||
self.line_edit_file_b.clear()
|
||||
|
||||
def go_action(self):
|
||||
def go_action(self) -> None:
|
||||
file_a = self.line_edit_file_a.text()
|
||||
file_b = self.line_edit_file_b.text()
|
||||
suffix = self.line_edit_suffix.text().strip() or "flare"
|
||||
@@ -220,7 +224,12 @@ class UpdateOptodesWindow(QWidget):
|
||||
|
||||
QMessageBox.information(self, "File Saved", f"File was saved to:\n{save_path}")
|
||||
|
||||
def update_optode_positions(self, file_a, file_b, save_path):
|
||||
def update_optode_positions(
|
||||
self,
|
||||
file_a: Union[str, Path],
|
||||
file_b: Union[str, Path],
|
||||
save_path: Union[str, Path]
|
||||
) -> None:
|
||||
|
||||
fiducials = {}
|
||||
ch_positions = {}
|
||||
@@ -247,16 +256,22 @@ class UpdateOptodesWindow(QWidget):
|
||||
elif extension == '.xlsx':
|
||||
|
||||
# TODO: Bad! Why assume sheet1 has the contents?
|
||||
df = pd.read_excel(file_b, sheet_name='Sheet1')
|
||||
df = pd.read_excel(file_b, sheet_name='Sheet1') # type: ignore
|
||||
|
||||
def _get_block_data(df, block_id, row_mapping, scale=0.001):
|
||||
def _get_block_data(
|
||||
target_df: pd.DataFrame,
|
||||
block_id: int,
|
||||
row_mapping: Union[Dict[int, str], str],
|
||||
scale: float = 0.001
|
||||
) -> Dict[str, npt.NDArray[np.float64]]:
|
||||
|
||||
"""Isolates a block, cleans numeric data, and returns a scaled dictionary."""
|
||||
# 1. Isolate and clean
|
||||
block = df[df['block_id'] == block_id].iloc[:, [1, 2, 3]].copy()
|
||||
block = target_df[target_df['block_id'] == block_id].iloc[:, [1, 2, 3]].copy()
|
||||
block = block.apply(pd.to_numeric, errors='coerce')
|
||||
|
||||
# 2. Extract into dictionary based on mapping
|
||||
result = {}
|
||||
result: Dict[str, npt.NDArray[np.float64]] = {}
|
||||
|
||||
# If row_mapping is a dict (like {0: 'nz'}), use it directly
|
||||
if isinstance(row_mapping, dict):
|
||||
@@ -265,7 +280,7 @@ class UpdateOptodesWindow(QWidget):
|
||||
result[key] = block.iloc[row_idx].to_numpy(dtype=float) * scale
|
||||
|
||||
# If row_mapping is a string prefix (like 'D' or 'S'), auto-generate keys
|
||||
elif isinstance(row_mapping, str):
|
||||
else:
|
||||
for i in range(len(block)):
|
||||
result[f"{row_mapping}{i+1}"] = block.iloc[i].to_numpy(dtype=float) * scale
|
||||
|
||||
@@ -292,5 +307,5 @@ class UpdateOptodesWindow(QWidget):
|
||||
|
||||
# Read the SNIRF file, set the montage, and write it back
|
||||
raw = read_raw_snirf(file_a, preload=True)
|
||||
raw.set_montage(initial_montage)
|
||||
raw.set_montage(initial_montage) # type: ignore
|
||||
write_raw_snirf(raw, save_path)
|
||||
@@ -1,15 +1,25 @@
|
||||
"""
|
||||
Filename: viewerlauncher.py
|
||||
Description: Viewer launcher window
|
||||
Note: Compliant with pylance strict type checking
|
||||
|
||||
Author: Tyler de Zeeuw
|
||||
License: GPL-3.0
|
||||
"""
|
||||
|
||||
# Built-in imports
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Type
|
||||
|
||||
# External library imports
|
||||
from pandas import DataFrame
|
||||
|
||||
from PySide6.QtWidgets import QPushButton, QWidget, QVBoxLayout
|
||||
from PySide6.QtCore import QTimer
|
||||
|
||||
from mne import Epochs
|
||||
from mne.io.base import BaseRaw
|
||||
|
||||
from src.analysis.exporttocsv import ExportToCSVWidget
|
||||
from src.analysis.intragroupbrainimage import IntraGroupBrainImageWidget
|
||||
from src.analysis.intergroupbrainimage import InterGroupBrainImageWidget
|
||||
@@ -24,18 +34,31 @@ from src.shared.shareddata import APP_NAME
|
||||
|
||||
|
||||
class ViewerLauncherWidget(QWidget):
|
||||
def __init__(self, haemo_dict, epochs_dict, cha_dict, df_ind_dict, design_matrix_dict, config_dict, fig_bytes_dict, contrast_results_dict, roi_channel_map_dict, folding_bypass):
|
||||
def __init__(
|
||||
self,
|
||||
haemo_dict: dict[str | Path, BaseRaw],
|
||||
epochs_dict: dict[str, Epochs],
|
||||
cha_dict: dict[str, DataFrame],
|
||||
df_ind_dict: dict[str, DataFrame],
|
||||
design_matrix_dict: dict[str, DataFrame],
|
||||
config_dict: dict[str, dict[str, Any]],
|
||||
fig_bytes_dict: dict[str, dict[str, bytes]],
|
||||
contrast_results_dict: dict[str, dict[str, Any]],
|
||||
roi_channel_map_dict: dict[str, dict[str, str]],
|
||||
folding_bypass: bool,
|
||||
) -> None:
|
||||
|
||||
super().__init__()
|
||||
self.setWindowTitle(f"Viewer Launcher - {APP_NAME.upper()}")
|
||||
|
||||
group_dict = {f: c.get("GROUP", "Unknown") for f, c in config_dict.items()}
|
||||
|
||||
btn_data = [
|
||||
btn_data: list[tuple[str, Type[QWidget], list[Any], bool]] = [
|
||||
("Participant Image Viewer", ParticipantImageViewerWidget, [haemo_dict, fig_bytes_dict], True),
|
||||
("Participant Brain Viewer", ParticipantBrainViewerWidget, [haemo_dict, cha_dict], True),
|
||||
("Participant Fold Channels Viewer", ParticipantFoldChannelsWidget, [haemo_dict, cha_dict], False),
|
||||
("Participant Functional Connectivity Viewer [BETA]", ParticipantFunctionalConnectivityWidget, [haemo_dict, epochs_dict], True),
|
||||
("Intra-Group Functional Connectivity Viewer [BETA]", IntraGroupFunctionalConnectivityWidget, [haemo_dict, group_dict, config_dict], True),
|
||||
("Intra-Group Functional Connectivity Viewer [BETA]", IntraGroupFunctionalConnectivityWidget, [haemo_dict, epochs_dict, group_dict], True),
|
||||
("Intra-Group Stats Viewer", IntraGroupStatsWidget, [haemo_dict, cha_dict, df_ind_dict, design_matrix_dict, contrast_results_dict, roi_channel_map_dict, group_dict], True),
|
||||
("Inter-Group Stats Viewer", InterGroupStatsWidget, [haemo_dict, cha_dict, df_ind_dict, design_matrix_dict, contrast_results_dict, roi_channel_map_dict, group_dict], True),
|
||||
("Intra-Group Brain and Image Viewer", IntraGroupBrainImageWidget, [haemo_dict, cha_dict, df_ind_dict, design_matrix_dict, contrast_results_dict, group_dict], True),
|
||||
@@ -47,21 +70,43 @@ class ViewerLauncherWidget(QWidget):
|
||||
for label, widget_class, args, requires_bypass in btn_data:
|
||||
btn = QPushButton(f"Open {label}")
|
||||
# Connect directly to the generic opener
|
||||
btn.clicked.connect(lambda _, c=widget_class, b=btn, a=args: self._open_viewer(c, b, *a))
|
||||
btn.clicked.connect(self._make_viewer_callback(widget_class, btn, args))
|
||||
btn.setEnabled(not (requires_bypass and folding_bypass))
|
||||
layout.addWidget(btn)
|
||||
|
||||
def _open_viewer(self, widget_class, btn, *args):
|
||||
def _make_viewer_callback(
|
||||
self,
|
||||
widget_class: Type[QWidget],
|
||||
btn: QPushButton,
|
||||
args: list[Any],
|
||||
) -> Callable[[bool], None]:
|
||||
def callback(_checked: bool = False) -> None:
|
||||
self._open_viewer(widget_class, btn, *args)
|
||||
return callback
|
||||
|
||||
def _open_viewer(
|
||||
self,
|
||||
widget_class: Type[QWidget],
|
||||
btn: QPushButton,
|
||||
*args: Any
|
||||
) -> None:
|
||||
|
||||
# Instantiate and show dynamically
|
||||
self.active_viewer = widget_class(*args)
|
||||
self.active_viewer.show()
|
||||
self._trigger_success(btn)
|
||||
|
||||
def _launch(self, func, btn, *args):
|
||||
def _launch(
|
||||
self,
|
||||
func: Callable[..., Any],
|
||||
btn: QPushButton,
|
||||
*args: Any
|
||||
|
||||
) -> None:
|
||||
func(*args)
|
||||
self._trigger_success(btn)
|
||||
|
||||
def _trigger_success(self, button):
|
||||
def _trigger_success(self, button: QPushButton) -> None:
|
||||
"""Temporarily adds a green checkmark to the button text."""
|
||||
original_text = button.text()
|
||||
button.setText(f"{original_text} ✔")
|
||||
@@ -70,6 +115,6 @@ class ViewerLauncherWidget(QWidget):
|
||||
# Revert after 1 second
|
||||
QTimer.singleShot(1000, lambda: self._revert_button(button, original_text))
|
||||
|
||||
def _revert_button(self, button, original_text):
|
||||
def _revert_button(self, button: QPushButton, original_text: str) -> None:
|
||||
button.setText(original_text)
|
||||
button.setStyleSheet("")
|
||||
Reference in New Issue
Block a user