Attempt to stop plugins from spontaneously re-enabling themselves.

This commit is contained in:
Storm Dragon
2026-02-19 02:40:46 -05:00
parent 95d33047fa
commit 11bd7107d2
3 changed files with 76 additions and 30 deletions
+14 -2
View File
@@ -85,12 +85,16 @@ class Backend:
with open(fileName, 'w', encoding='utf-8') as settingsFile:
settingsFile.write(dumps(prefsDoc))
def _updateTable(self, targetTable, newValues):
def _updateTable(self, targetTable, newValues, preserveMissingKeys=None):
if not isinstance(newValues, dict):
return
preserveMissingKeys = set(preserveMissingKeys or [])
for key in list(targetTable.keys()):
if key not in newValues:
if key in preserveMissingKeys:
continue
del targetTable[key]
continue
newValue = newValues[key]
@@ -173,7 +177,12 @@ class Backend:
profiles[profile] = {}
profileTable = profiles[profile]
self._updateTable(profileTable, general)
# Keep plugin persistence keys when callers provide partial updates.
self._updateTable(
profileTable,
general,
preserveMissingKeys={"activePlugins", "pluginSources"},
)
self._writeDocument(self.settingsFile, prefsDoc)
def _getSettings(self):
@@ -219,6 +228,9 @@ class Backend:
self._getSettings()
generalSettings = self.general.copy()
generalSettings = self._migrateSettings(generalSettings)
# Plugin state is profile-scoped; ignore legacy/global values.
generalSettings.pop('activePlugins', None)
generalSettings.pop('pluginSources', None)
defaultProfile = generalSettings.get('startingProfile',
['Default', 'default'])
if profile is None:
+3 -19
View File
@@ -21,10 +21,8 @@ from gi.repository import Gtk, Gdk, Pango
from cthulhu.plugin import Plugin, cthulhu_hookimpl
from cthulhu import cthulhu
from cthulhu import debug
from cthulhu import settings_manager
logger = logging.getLogger(__name__)
_settingsManager = None # Removed - use cthulhu.cthulhuApp.settingsManager
class PluginManager(Plugin):
@@ -473,25 +471,11 @@ class PluginManager(Plugin):
current_general['activePlugins'] = active_plugins
cthulhu.cthulhuApp.settingsManager.profile = profile_name
cthulhu.cthulhuApp.settingsManager._setProfileGeneral(current_general)
pronunciations = cthulhu.cthulhuApp.settingsManager.getPronunciations(profile_name) or {}
keybindings = cthulhu.cthulhuApp.settingsManager.getKeybindings(profile_name) or {}
backend = cthulhu.cthulhuApp.settingsManager._backend
if backend:
backend.saveProfileSettings(
profile_name,
cthulhu.cthulhuApp.settingsManager.profileGeneral,
pronunciations,
keybindings
)
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Settings saved to backend (profile {profile_name})", True)
else:
debug.printMessage(debug.LEVEL_INFO, "PluginManager: No backend available for saving", True)
cthulhu.cthulhuApp.settingsManager.saveProfileSettings(current_general)
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Settings saved via settings manager (profile {profile_name})", True)
except Exception as save_error:
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error saving via backend: {save_error}", True)
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Error saving plugin state: {save_error}", True)
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Updated active plugins: {active_plugins}", True)
+59 -9
View File
@@ -379,6 +379,18 @@ class SettingsManager(object):
def getSetting(self, settingName: str) -> Any:
return getattr(settings, settingName, None)
def _getListSetting(self, settingName: str) -> List[str]:
value = self.getSetting(settingName)
if isinstance(value, (list, tuple)):
return [item for item in value if isinstance(item, str)]
return []
def _ensurePluginPersistenceSettings(self, general: Dict[str, Any]) -> None:
if 'activePlugins' not in general:
general['activePlugins'] = self._getListSetting('activePlugins')
if 'pluginSources' not in general:
general['pluginSources'] = self._getListSetting('pluginSources')
def getVoiceLocale(self, voice: str = 'default') -> str:
voices = self.getSetting('voices')
v = ACSS(voices.get(voice, {}))
@@ -626,6 +638,8 @@ class SettingsManager(object):
continue
elif key == 'profile':
self.profileGeneral[key] = value
elif key in ['activePlugins', 'pluginSources']:
self.profileGeneral[key] = copy.deepcopy(value)
elif value != self.defaultGeneral.get(key):
self.profileGeneral[key] = value
elif self.general.get(key) != value:
@@ -634,6 +648,46 @@ class SettingsManager(object):
msg = 'SETTINGS MANAGER: General settings for profile set'
debug.printMessage(debug.LEVEL_INFO, msg, True)
def saveProfileSettings(
self,
general: Dict[str, Any],
pronunciations: Optional[Dict[str, Any]] = None,
keybindings: Optional[Dict[str, Any]] = None,
) -> None:
profileName: Optional[str] = self.profile
profileSetting = general.get('profile')
if isinstance(profileSetting, (list, tuple)) and len(profileSetting) > 1:
profileName = profileSetting[1]
elif not profileName:
defaultProfile = settings.profile
if isinstance(defaultProfile, (list, tuple)) and len(defaultProfile) > 1:
profileName = defaultProfile[1]
else:
profileName = 'default'
self.profile = profileName
generalCopy = dict(general)
self._ensurePluginPersistenceSettings(generalCopy)
self._setProfileGeneral(generalCopy)
if self.profile is None:
return
profileName = self.profile
if pronunciations is None:
pronunciations = self.getPronunciations(profileName) or {}
if keybindings is None:
keybindings = self.getKeybindings(profileName) or {}
self._setProfilePronunciations(pronunciations)
self._setProfileKeybindings(keybindings)
if self._backend:
self._backend.saveProfileSettings(self.profile,
self.profileGeneral,
self.profilePronunciations,
self.profileKeybindings)
def _setProfilePronunciations(self, pronunciations: Dict[str, Any]) -> None:
"""Set the changed pronunciations settings from the defaults' ones
as the profile's."""
@@ -664,9 +718,12 @@ class SettingsManager(object):
if not self._backend:
return
profileScopedKeys = {'activePlugins', 'pluginSources'}
appGeneral = {}
profileGeneral = self.getGeneralSettings(self.profile) if self.profile else {}
for key, value in general.items():
if key in profileScopedKeys:
continue
if value != profileGeneral.get(key):
appGeneral[key] = value
@@ -705,24 +762,17 @@ class SettingsManager(object):
currentProfile = _profile[1]
self.profile = currentProfile
self._ensurePluginPersistenceSettings(general)
# Elements that need to stay updated in main configuration.
self.defaultGeneral['startingProfile'] = general.get('startingProfile',
_profile)
self._setProfileGeneral(general)
self._setProfilePronunciations(pronunciations)
self._setProfileKeybindings(keybindings)
self.saveProfileSettings(general, pronunciations, keybindings)
tokens = ["SETTINGS MANAGER: Saving for backend", self._backend]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
if self._backend and self.profile:
self._backend.saveProfileSettings(self.profile,
self.profileGeneral,
self.profilePronunciations,
self.profileKeybindings)
tokens = ["SETTINGS MANAGER: Settings for", script, "(app:", script.app, ") saved"]
debug.printTokens(debug.LEVEL_INFO, tokens, True)
return self._enableAccessibility()