2828import time
2929import traceback
3030import webbrowser
31+ from datetime import datetime
3132from typing import TYPE_CHECKING
3233
3334import guidata .dataset as gds
@@ -158,6 +159,8 @@ def __init__(self, console=None, hide_on_close=False): # pylint: disable=too-ma
158159 execenv .log (self , "Starting initialization" )
159160
160161 self .ready_flag = True
162+ self .started_at = datetime .now ().astimezone ()
163+ self .plugins_last_load_at = self .started_at
161164
162165 self .hide_on_close = hide_on_close
163166 self .__old_size : tuple [int , int ] | None = None
@@ -1051,6 +1054,10 @@ def __register_plugins(self) -> None:
10511054 # None = all plugins enabled (default), [] = no plugins, list = specific plugins
10521055 enabled_list = Conf .main .plugins_enabled_list .get (None )
10531056
1057+ if not Conf .main .plugins_enabled .get ():
1058+ self .plugins_last_load_at = datetime .now ().astimezone ()
1059+ return
1060+
10541061 for plugin_class in PluginRegistry .get_plugin_classes ():
10551062 try :
10561063 # Check if plugin is enabled before instantiation
@@ -1092,6 +1099,8 @@ def __register_plugins(self) -> None:
10921099 plugin_class .__name__ , filepath or "" , tb_text
10931100 )
10941101
1102+ self .plugins_last_load_at = datetime .now ().astimezone ()
1103+
10951104 def __flush_startup_errors (self ) -> None :
10961105 """Write any buffered startup errors to the internal console.
10971106
@@ -1129,6 +1138,11 @@ def __configure_plugins(self) -> None:
11291138 dialog = PluginConfigDialog (self )
11301139 dialog .exec ()
11311140
1141+ def set_plugins_enabled (self , enabled : bool ) -> None :
1142+ """Apply the global third-party plugin enabled state."""
1143+ Conf .main .plugins_enabled .set (enabled )
1144+ self .__apply_plugins_enabled_setting ()
1145+
11321146 def reload_plugins (self ) -> None :
11331147 """Reload third-party plugins at runtime.
11341148
@@ -1143,8 +1157,9 @@ def reload_plugins(self) -> None:
11431157 self ,
11441158 _ ("Plugins" ),
11451159 _ (
1146- "Third-party plugins are disabled. Enable them in the "
1147- "Settings dialog to use this feature."
1160+ "Third-party plugins are disabled. Enable them again "
1161+ "from the plugin configuration dialog to use this "
1162+ "feature."
11481163 ),
11491164 )
11501165 return
@@ -1220,6 +1235,7 @@ def reload_plugins(self) -> None:
12201235 # Update plugin status in the status bar
12211236 self .pluginstatus .update_status ()
12221237 self .__update_plugins_availability ()
1238+ self .plugins_last_load_at = datetime .now ().astimezone ()
12231239
12241240 def __configure_statusbar (self , console : bool ) -> None :
12251241 """Configure status bar
@@ -1255,12 +1271,11 @@ def __update_plugins_availability(self) -> None:
12551271 """Update plugin-related UI according to third-party plugin setting."""
12561272 plugins_enabled = Conf .main .plugins_enabled .get ()
12571273
1258- if self .plugins_menu is not None :
1259- self .plugins_menu .setEnabled (plugins_enabled )
1274+ if self .reload_plugins_action is not None :
1275+ self .reload_plugins_action .setEnabled (plugins_enabled )
12601276
1261- for action in (self .reload_plugins_action , self .configure_plugins_action ):
1262- if action is not None :
1263- action .setEnabled (plugins_enabled )
1277+ if self .configure_plugins_action is not None :
1278+ self .configure_plugins_action .setEnabled (True )
12641279
12651280 if hasattr (self , "pluginstatus" ) and self .pluginstatus is not None :
12661281 self .pluginstatus .update_status ()
@@ -1277,11 +1292,6 @@ def __apply_plugins_enabled_setting(self) -> None:
12771292 for panel in (self .signalpanel , self .imagepanel ):
12781293 panel .acthandler .clear_plugin_actions ()
12791294
1280- PluginRegistry .clear_plugin_classes ()
1281- PluginRegistry .clear_failed_plugins ()
1282- PluginRegistry .clear_discovery_errors ()
1283- self ._startup_errors .clear ()
1284-
12851295 self .__update_actions (update_other_data_panel = True )
12861296 self .__update_plugins_availability ()
12871297
@@ -1867,8 +1877,6 @@ def __update_actions(self, update_other_data_panel: bool = False) -> None:
18671877 panel .selection_changed ()
18681878 self .signalpanel_toolbar .setVisible (is_signal )
18691879 self .imagepanel_toolbar .setVisible (not is_signal )
1870- if self .plugins_menu is not None :
1871- self .plugins_menu .setEnabled (Conf .main .plugins_enabled .get ())
18721880
18731881 def __tab_index_changed (self , index : int ) -> None :
18741882 """Switch from signal to image mode, or vice-versa"""
@@ -1898,12 +1906,11 @@ def __update_generic_menu(self, menu: QW.QMenu | None = None) -> None:
18981906 # no plugin has registered actions yet (so that new plugins can be
18991907 # discovered after they are added on disk).
19001908 if menu is self .plugins_menu :
1901- if Conf .main .plugins_enabled .get ():
1902- actions = list (actions ) + [
1903- None ,
1904- self .configure_plugins_action ,
1905- self .reload_plugins_action ,
1906- ]
1909+ actions = list (actions ) + [
1910+ None ,
1911+ self .configure_plugins_action ,
1912+ self .reload_plugins_action ,
1913+ ]
19071914 add_actions (menu , actions )
19081915
19091916 def __update_file_menu (self ) -> None :
@@ -2513,8 +2520,6 @@ def __edit_settings(self) -> None: # pylint: disable=too-many-branches,too-many
25132520 self .__update_color_mode ()
25142521 if option == "show_console_on_error" :
25152522 self .__update_console_show_mode ()
2516- if option == "plugins_enabled" :
2517- self .__apply_plugins_enabled_setting ()
25182523 if option == "plot_toolbar_position" :
25192524 for dock in self .docks .values ():
25202525 widget = dock .widget ()
0 commit comments