GNOME Bugzilla – Bug 570650
Refactor settings to make settings a script object versus a global
Last modified: 2018-02-08 12:55:49 UTC
The current way that global settings and app-specific settings are handled is a bit touchy/brittle. The main reason for this is that the original design never accounted for app-specific settings and we ended up kind of hacking to retrofit the code for app-specific settings. This causes a number of issues that could be resolved if we refactored settings to be a script object instead of a global.
Hi Will, 1. Is it just the user customizable settings that need to be made into per script basis, or all of the settings. 2. is it ok to use yaml (saves a lot of code for us that just ensures things are in the right format, we can just read in the yaml document, and the settings are all there, in a dictionary. I have a little example of this if you wish to see it in action. The settings.yaml file would look like this: --cut--- brailleContractionTable: '' brailleEOLIndicator: ' $l' brailleLinkIndicator: BRAILLE_LINK_BOTH brailleRequiredStateString: required brailleRolenameStyle: BRAILLE_ROLENAME_STYLE_LONG brailleSelectorIndicator: BRAILLE_SEL_BOTH brailleVerbosityLevel: VERBOSITY_LEVEL_VERBOSE disableBrailleEOL: false enableActionKeys: true enableBraille: true enableBrailleContext: true enableBrailleGrouping: false enabledBrailledTextAttributes: size:; family-name:; weight:400; indent:0; underline:none; strikethrough:false; justification:left; style:normal; orcaModifierKeys: DESKTOP_MODIFIER_KEYS ---cut--- Just a few examples. Then On the creation of a new script, we see if the user has a scriptname.yaml in their orcaPrefsDir, and if so load the settings defined within. In that file, only the things that needs to be changed from the default is stored. Then whenever a script asks for a setting, it asks its internal settings instance for the key, and if the key is not found, the settings instance will automatically follow the inheritence to see in which scope the key is defined. If it has treversed up to the default settings, and the key is still not found, then we return None.
Hey Jon! (In reply to comment #1) > 1. Is it just the user customizable settings that need to be made into per > script basis, or all of the settings. It would be best if all the the settings were handled as an object instance in the script with fallbacks for "unset" settings going back to the settings in the default script. > 2. is it ok to use yaml (saves a lot of code for us that just ensures things > are in the right format, we can just read in the yaml document, and the > settings are all there, in a dictionary. From the example, I'm not sure I understand the code savings. In addition, because it removes Python from the picture, it seems to prevent us from being able to define methods that can be used as handlers and such. HOWEVER... > Then whenever a script asks for a setting, it asks its internal settings > instance for the key, and if the key is not found, the settings instance will > automatically follow the inheritence to see in which scope the key is defined. Does YAML provide this automatically for us? If so, does it allow one to make changes to the parents in the inheritance hierarchy and have the children automatically pick them up?
This is how i see it, Will, is this reasonable? questions, considerations/concerns I will explain yaml at the bottom. design: settings.py: --- isAccessibilityEnabled(): isGKSUGrabDisabled() class Settings __init__(self) getValue(self, keyName) insert(self, key, value, pushToRoot=False) save(self, filename=None) loadUserSettings(self, filename, purgeExisting=False) loadUserDefaults(self) --- orca.py, on startup, creates a default settings object, and this is stored in orca_state. This default settings object contains all our initial settings, as we currently have them in settings.py. A little further down in the main() function, we know where to expect the user settings, so we try to load them from the userPrefsDir. If they are not there, no deal, our defaultSettings object already has our defaults as we intended them. However, if the settings are there, then we load them and the defined settings in the file will overwrite some of the settings in the defaultSettings object. Now we know what the settings are, we kick orca to bring up main/prefs window, or whatever the user wanted. ... orca is running fine, we load an app We load a script, for a particular app. script.py.__init__() script.py, creates a new settings object, giving the defaultSettings object as a parent. This new object is our localSettings. Now we go again to userPrefsDir, and see if we can load a settings file given the appname. If we can, then store the results into the localSettings, if not, we do nothing. ....working as expected ... someone asks for a setting: they ask the active script for its localSettings obj. localSettings.getValue('setting') the getValue method looks in the local dict (internal), and if key is not defined, then it asks its parent to look for the key, and so on. Once we reach the root (defaultSettings), then either key is found so return it, or else return None. This should naturally extend to address bug #524710 (Implement document-specific settings/preferences) root --> parent --> child defaultSettings --> localAppSettings1 --> documentSettings --> localAppSettings2 As expected: * if app2 cant find a value in its local settings, it asks its parent. * If app1 redefines a setting, it will shaddow out the defaultSetting definition. * if a setting is updated in defaultSettings, and it is not overshaddowed by its children, then it becomes immediately visible to the children. Does this sound like what we want? What does yaml do for us? it seems that it makes it easy to load/dump to text files, human readable pyckle, saving us from having orca_prefs.py re Handlers in comment above, currently i would have them live outside the settings class, but still within the settings module. Then when we want to assign it to a settings variable in yaml: myfunc: funcname and getValue() will find the implementation at runtime. Thank you
Thanks Jon! This discussion has made me remember that Orca is not a good participant in the GNOME settings space. That is, Orca currently uses its own settings files rather than using the existing gconf system provided by GNOME. I had a chat with Ray Strode and GNOME Boston 2008, and the general feeling is that Orca should use the settings facility provided by GNOME. At the time, it was gconf, but I think things are moving to GSettings and dconf for GNOME 3.0 (see http://live.gnome.org/RoadMap). While it might be a bit more complex than what we have now, there are many advantages of using the GNOME settings system. One example is that the configuration UI can be a completely separate application from Orca. Another example is that it provides events to let you know when a value changes -- this can be helpful, for example, in allowing Orca to react immediately to settings changes. Another example is more political, but it is that the GNOME community would view Orca as a better GNOME citizen. :-) A couple reasons I had resisted the gconf route was the expressiveness allowed by user-settings.py -- it was in Python and you could easily do very Pythonic things to modify the behavior of Orca. Because we tend to overwrite it all the time, however, user-settings.py tends to be more of a key/value thing and we can rely upon orca-customizations.py to do the meatier stuff. So... If we're going to go down the route of completely redoing things, I would prefer we use the settings facility provided by GNOME instead of introducing a new one.
Moving to FUTURE until the dconf thing is figured out.
bug 617420 is another instance where this would be useful.
Planning spam. Sorry!
(Part of the settings picture, so 3.0!ing it)