Attempt to stop plugins from spontaneously re-enabling themselves.
This commit is contained in:
@@ -85,12 +85,16 @@ class Backend:
|
|||||||
with open(fileName, 'w', encoding='utf-8') as settingsFile:
|
with open(fileName, 'w', encoding='utf-8') as settingsFile:
|
||||||
settingsFile.write(dumps(prefsDoc))
|
settingsFile.write(dumps(prefsDoc))
|
||||||
|
|
||||||
def _updateTable(self, targetTable, newValues):
|
def _updateTable(self, targetTable, newValues, preserveMissingKeys=None):
|
||||||
if not isinstance(newValues, dict):
|
if not isinstance(newValues, dict):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
preserveMissingKeys = set(preserveMissingKeys or [])
|
||||||
|
|
||||||
for key in list(targetTable.keys()):
|
for key in list(targetTable.keys()):
|
||||||
if key not in newValues:
|
if key not in newValues:
|
||||||
|
if key in preserveMissingKeys:
|
||||||
|
continue
|
||||||
del targetTable[key]
|
del targetTable[key]
|
||||||
continue
|
continue
|
||||||
newValue = newValues[key]
|
newValue = newValues[key]
|
||||||
@@ -173,7 +177,12 @@ class Backend:
|
|||||||
profiles[profile] = {}
|
profiles[profile] = {}
|
||||||
profileTable = 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)
|
self._writeDocument(self.settingsFile, prefsDoc)
|
||||||
|
|
||||||
def _getSettings(self):
|
def _getSettings(self):
|
||||||
@@ -219,6 +228,9 @@ class Backend:
|
|||||||
self._getSettings()
|
self._getSettings()
|
||||||
generalSettings = self.general.copy()
|
generalSettings = self.general.copy()
|
||||||
generalSettings = self._migrateSettings(generalSettings)
|
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',
|
defaultProfile = generalSettings.get('startingProfile',
|
||||||
['Default', 'default'])
|
['Default', 'default'])
|
||||||
if profile is None:
|
if profile is None:
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ from gi.repository import Gtk, Gdk, Pango
|
|||||||
from cthulhu.plugin import Plugin, cthulhu_hookimpl
|
from cthulhu.plugin import Plugin, cthulhu_hookimpl
|
||||||
from cthulhu import cthulhu
|
from cthulhu import cthulhu
|
||||||
from cthulhu import debug
|
from cthulhu import debug
|
||||||
from cthulhu import settings_manager
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
_settingsManager = None # Removed - use cthulhu.cthulhuApp.settingsManager
|
|
||||||
|
|
||||||
|
|
||||||
class PluginManager(Plugin):
|
class PluginManager(Plugin):
|
||||||
@@ -473,25 +471,11 @@ class PluginManager(Plugin):
|
|||||||
current_general['activePlugins'] = active_plugins
|
current_general['activePlugins'] = active_plugins
|
||||||
|
|
||||||
cthulhu.cthulhuApp.settingsManager.profile = profile_name
|
cthulhu.cthulhuApp.settingsManager.profile = profile_name
|
||||||
cthulhu.cthulhuApp.settingsManager._setProfileGeneral(current_general)
|
cthulhu.cthulhuApp.settingsManager.saveProfileSettings(current_general)
|
||||||
|
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Settings saved via settings manager (profile {profile_name})", True)
|
||||||
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)
|
|
||||||
|
|
||||||
except Exception as save_error:
|
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)
|
debug.printMessage(debug.LEVEL_INFO, f"PluginManager: Updated active plugins: {active_plugins}", True)
|
||||||
|
|
||||||
|
|||||||
@@ -379,6 +379,18 @@ class SettingsManager(object):
|
|||||||
def getSetting(self, settingName: str) -> Any:
|
def getSetting(self, settingName: str) -> Any:
|
||||||
return getattr(settings, settingName, None)
|
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:
|
def getVoiceLocale(self, voice: str = 'default') -> str:
|
||||||
voices = self.getSetting('voices')
|
voices = self.getSetting('voices')
|
||||||
v = ACSS(voices.get(voice, {}))
|
v = ACSS(voices.get(voice, {}))
|
||||||
@@ -626,6 +638,8 @@ class SettingsManager(object):
|
|||||||
continue
|
continue
|
||||||
elif key == 'profile':
|
elif key == 'profile':
|
||||||
self.profileGeneral[key] = value
|
self.profileGeneral[key] = value
|
||||||
|
elif key in ['activePlugins', 'pluginSources']:
|
||||||
|
self.profileGeneral[key] = copy.deepcopy(value)
|
||||||
elif value != self.defaultGeneral.get(key):
|
elif value != self.defaultGeneral.get(key):
|
||||||
self.profileGeneral[key] = value
|
self.profileGeneral[key] = value
|
||||||
elif self.general.get(key) != value:
|
elif self.general.get(key) != value:
|
||||||
@@ -634,6 +648,46 @@ class SettingsManager(object):
|
|||||||
msg = 'SETTINGS MANAGER: General settings for profile set'
|
msg = 'SETTINGS MANAGER: General settings for profile set'
|
||||||
debug.printMessage(debug.LEVEL_INFO, msg, True)
|
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:
|
def _setProfilePronunciations(self, pronunciations: Dict[str, Any]) -> None:
|
||||||
"""Set the changed pronunciations settings from the defaults' ones
|
"""Set the changed pronunciations settings from the defaults' ones
|
||||||
as the profile's."""
|
as the profile's."""
|
||||||
@@ -664,9 +718,12 @@ class SettingsManager(object):
|
|||||||
if not self._backend:
|
if not self._backend:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
profileScopedKeys = {'activePlugins', 'pluginSources'}
|
||||||
appGeneral = {}
|
appGeneral = {}
|
||||||
profileGeneral = self.getGeneralSettings(self.profile) if self.profile else {}
|
profileGeneral = self.getGeneralSettings(self.profile) if self.profile else {}
|
||||||
for key, value in general.items():
|
for key, value in general.items():
|
||||||
|
if key in profileScopedKeys:
|
||||||
|
continue
|
||||||
if value != profileGeneral.get(key):
|
if value != profileGeneral.get(key):
|
||||||
appGeneral[key] = value
|
appGeneral[key] = value
|
||||||
|
|
||||||
@@ -705,24 +762,17 @@ class SettingsManager(object):
|
|||||||
currentProfile = _profile[1]
|
currentProfile = _profile[1]
|
||||||
|
|
||||||
self.profile = currentProfile
|
self.profile = currentProfile
|
||||||
|
self._ensurePluginPersistenceSettings(general)
|
||||||
|
|
||||||
# Elements that need to stay updated in main configuration.
|
# Elements that need to stay updated in main configuration.
|
||||||
self.defaultGeneral['startingProfile'] = general.get('startingProfile',
|
self.defaultGeneral['startingProfile'] = general.get('startingProfile',
|
||||||
_profile)
|
_profile)
|
||||||
|
|
||||||
self._setProfileGeneral(general)
|
self.saveProfileSettings(general, pronunciations, keybindings)
|
||||||
self._setProfilePronunciations(pronunciations)
|
|
||||||
self._setProfileKeybindings(keybindings)
|
|
||||||
|
|
||||||
tokens = ["SETTINGS MANAGER: Saving for backend", self._backend]
|
tokens = ["SETTINGS MANAGER: Saving for backend", self._backend]
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
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"]
|
tokens = ["SETTINGS MANAGER: Settings for", script, "(app:", script.app, ") saved"]
|
||||||
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
return self._enableAccessibility()
|
return self._enableAccessibility()
|
||||||
|
|||||||
Reference in New Issue
Block a user