MainController¶
- class poriscope.controllers.main_controller.MainController(main_model: MainModel, main_view: MainView)¶
Bases:
QObjectApp-shell controller: owns the DataPluginController and every instantiated analysis-tab controller, and wires their signals together. A tab reaches a data plugin through MetaModel.call rather than through this class; what is wired here is the typed create/edit/delete trio onto the DataPluginController singleton, plus the display, progress and history signals. Also drives session/plugin-history persistence and restore.
- handle_abort_all_analysis() None¶
Stop running operations in every open analysis tab.
Backs the Analysis -> Abort Analysis menu item, which previously emitted a signal that was connected to nothing and named a single hard-coded tab, so it never aborted anything. Each tab reports its own outcome on the display panel, so nothing is emitted here.
- instantiate_analysis_tab(subclass: str) None¶
Instantiate a new analysis-tab controller of the given subclass and wire it into the app (add its page, sync the sidebar highlight to it, connect its signals, register it in plugin history), or reuse the existing instance if a tab of that type has already been instantiated.
Exceptions raised while instantiating the controller itself are caught and logged here. Exceptions raised afterward, while wiring up or registering the new tab, are not caught by this method and will propagate to the caller.
- Parameters:
subclass (str) – The class name of the MetaController subclass to instantiate (e.g. “RawDataController”).
- load_session(file_name: str | Path | None = None) None¶
Load a saved session, replacing whatever is currently instantiated.
Applying the loaded plugin history on top of an already-populated workspace collided with anything the current session already held under the same key or name - a plugin key already registered, a named filter already added - and surfaced as an “already exists” error for state the user never meant to keep.
reset_session()clears the workspace first, the same as it does for its own menu action, so a load always starts from nothing regardless of what was open before it. Both “Load Session” (a chosen file) and “Restore Session” (file_name=None, the last saved session) route through this same method.A message naming what was loaded is left on the status/log panel, since
reset_session()above already leaves one there of its own - without this, the user would see that the workspace was cleared but not what, if anything, replaced it.- Parameters:
file_name (Optional[Union[str, Path]]) – Path to the session file to load, or None to restore the last saved session.
- refresh_available_plugins() None¶
Re-scan the plugin directories and push the result to everyone holding it.
The scan ran once, in
MainModel’s constructor, and its results were copied into three places at construction: this controller’s data plugin controller, that controller’s model, and the view’s menus. Changing the user plugin folder therefore had no visible effect until the next launch.Instantiated plugins are untouched.
self.data_pluginsis the list of instantiated plugins rather than available classes, so it is not part of this refresh, and an existing instance keeps working through its own class reference regardless - seeMainModel.refresh_available_pluginsfor why a re-scan does not hand back the same class object it did before.
- reset_app_config() None¶
Restore the stored settings to their defaults and apply them live.
The model persists the defaults; each is then routed back through the same path a manual edit takes, because rewriting
config.jsonalone would leave the running application on the old values until restart - data plugins keep the previous parent folder, and the logger keeps the previous level. Finally the settings window is refreshed, which would otherwise go on displaying what the user had before.Saved sessions and log files are not affected.
Resetting the user plugin folder re-scans it immediately, the same way editing it in Settings does: this routes through
update_user_plugin_locationbelow, which already callsrefresh_available_plugins()at the end of its own path. The plugin menus reflect the default folder right away rather than waiting for the next launch.
- reset_session() None¶
Return the application to the state it has when launched from scratch.
Deletes every instantiated data plugin, closes every analysis tab, drops both in-memory histories and returns to the landing page - so the user gets a clean workspace without quitting and starting the app again.
The saved session files are deliberately left on disk, because that is what launching from scratch does:
load_sessionreads them at startup and nothing applies them until the user chooses Restore Session. Leaving them means this is reversible - reset, then Restore, and the workspace comes back.Keeping them takes active effort. Both histories save themselves on every change, and deleting a plugin emits a history update per plugin, so the teardown below would otherwise write an empty session over the file before the user ever got the chance to restore it.
_suppress_session_saveholds that off for the duration.Anything that refuses to delete is reported rather than passed over, so a partial clear is never announced as a complete one.
The Settings page, if it was open, is removed too rather than kept around - a freshly launched application has never opened it either. Its widget is a singleton rather than something disposable, though, so
close_settings_page()detaches it first; see that method for why.Running workers are stopped first, as they are on quit - deleting a plugin closes its resources, so a worker still running against one would be reading from a handle that has just been closed.
The sidebar highlight, the sidebar layout, the status/log panel and the floating Help window are reset too. None of those follow from tearing down tabs and plugins on their own: the sidebar only ever gains a checked button, never loses one; an expanded sidebar stays expanded; the log panel only ever grows; and Help is a separate top-level window that closing tabs never touches. Left alone, the landing page would still show whichever section was last open, whichever sidebar layout was last chosen, everything logged before the reset, and a Help window a fresh launch would never have open.
The plugin menus are re-scanned too, the same way changing the user plugin folder already does.
populate_available_plugins()otherwise only ever runs once, inMainModel’s constructor, so a plugin file dropped into the plugin folder mid-session would be invisible in the menus after a reset even though a genuine relaunch would pick it up.
- update_plugin_history(history: Dict[str, Any] | None, delete_key: str | None) None¶
Record a plugin being added, removed or renamed, then persist the session.
The two arguments form a small truth table. history alone adds or replaces an entry; delete_key alone removes one; both together are a rename, where the entry named by delete_key becomes the one history describes. Neither is not an error - it still re-syncs and saves, which is how a change to a tab’s own state reaches the session file without any plugin having changed.