mirror of
https://github.com/jtgans/g13gui.git
synced 2025-06-20 00:14:09 -04:00
g13gui: Define a Preferences class
This centralizes the data we manage into a single model that can manage the serialization to/from JSON before it hits disk more effectively.
This commit is contained in:
parent
577865c69e
commit
91e62addb7
110
g13gui/g13gui/prefs.py
Normal file
110
g13gui/g13gui/prefs.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from common import VERSION
|
||||||
|
from bindingprofile import BindingProfile
|
||||||
|
from observer import Subject
|
||||||
|
from observer import ChangeType
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_PROFILE_NAME = 'Default Profile'
|
||||||
|
|
||||||
|
|
||||||
|
class Preferences(Subject):
|
||||||
|
def __init__(self, dict=None):
|
||||||
|
self._profiles = {}
|
||||||
|
self._selectedProfile = None
|
||||||
|
|
||||||
|
if dict:
|
||||||
|
self.loadFromDict(dict)
|
||||||
|
else:
|
||||||
|
self.initDefaultProfile()
|
||||||
|
|
||||||
|
def profiles(self):
|
||||||
|
return self._profiles
|
||||||
|
|
||||||
|
def profileNames(self):
|
||||||
|
return sorted(self._profiles.keys())
|
||||||
|
|
||||||
|
def selectedProfile(self):
|
||||||
|
return self._profiles[self._selectedProfile]
|
||||||
|
|
||||||
|
def selectedProfileName(self):
|
||||||
|
return self._selectedProfile
|
||||||
|
|
||||||
|
def initDefaultProfile(self):
|
||||||
|
self._initDefaultProfile()
|
||||||
|
self.notifyChanged()
|
||||||
|
|
||||||
|
def addProfile(self, name, profile):
|
||||||
|
self._addProfile(name, profile)
|
||||||
|
self.notifyChanged()
|
||||||
|
|
||||||
|
def removeProfile(self, name):
|
||||||
|
self._removeProfile(name)
|
||||||
|
self.notifyChanged()
|
||||||
|
|
||||||
|
def setSelectedProfile(self, name):
|
||||||
|
self._setSelectedProfile(name)
|
||||||
|
self.notifyChanged()
|
||||||
|
|
||||||
|
def _initDefaultProfile(self):
|
||||||
|
default_profile = BindingProfile()
|
||||||
|
self._profiles = {DEFAULT_PROFILE_NAME: default_profile}
|
||||||
|
self._selectedProfile = DEFAULT_PROFILE_NAME
|
||||||
|
|
||||||
|
self.addChange(ChangeType.ADD, 'profile', {self.selectedProfileName(): self.selectedProfile()}),
|
||||||
|
self.addChange(ChangeType.MODIFY, 'selectedProfile', self._selectedProfile)
|
||||||
|
|
||||||
|
def _addProfile(self, name, profile):
|
||||||
|
if name in self._profiles.keys():
|
||||||
|
raise KeyError('Profile by name %s is already present' % name)
|
||||||
|
self._profiles[name] = profile
|
||||||
|
self.addChange(ChangeType.ADD, 'profile', {name: profile})
|
||||||
|
|
||||||
|
def _removeProfile(self, name):
|
||||||
|
del(self._profiles[name])
|
||||||
|
self.addChange(ChangeType.REMOVE, 'profile', name)
|
||||||
|
|
||||||
|
if len(self._profiles) == 0:
|
||||||
|
self.initDefaultProfile()
|
||||||
|
else:
|
||||||
|
if self._selectedProfile == name:
|
||||||
|
self.setSelectedProfile(sorted(self._profiles.keys())[0])
|
||||||
|
|
||||||
|
def _setSelectedProfile(self, name):
|
||||||
|
if name not in self._profiles.keys():
|
||||||
|
raise KeyError('No profile by name %s present' % name)
|
||||||
|
self._selectedProfile = name
|
||||||
|
self.addChange(ChangeType.MODIFY, 'selectedProfile',
|
||||||
|
self._selectedProfile)
|
||||||
|
|
||||||
|
def saveToDict(self):
|
||||||
|
return {
|
||||||
|
'version': VERSION,
|
||||||
|
'profiles': dict([(name, profile.toDict()) for name, profile in self._profiles.items()]),
|
||||||
|
'selectedProfile': self._selectedProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
def loadFromDict(self, dict):
|
||||||
|
if dict['version'] != VERSION:
|
||||||
|
print('WARNING: This profile config is from a different version '
|
||||||
|
'(wanted %s got %s)!' % (VERSION, dict['version']))
|
||||||
|
print('This configuration may not load properly!')
|
||||||
|
|
||||||
|
try:
|
||||||
|
for name, profile in dict['profiles'].items():
|
||||||
|
self._addProfile(name, BindingProfile(profile))
|
||||||
|
|
||||||
|
self._setSelectedProfile(dict['selectedProfile'])
|
||||||
|
|
||||||
|
except (Exception) as err:
|
||||||
|
print('Unable to initialize from dict: %s' % err)
|
||||||
|
print('Continuing with defaults.')
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
self.initDefaultProfile()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self.clearChanges()
|
105
g13gui/g13gui/prefs_tests.py
Normal file
105
g13gui/g13gui/prefs_tests.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import prefs
|
||||||
|
|
||||||
|
from common import VERSION
|
||||||
|
from observer import ChangeType
|
||||||
|
from observer import ObserverTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class PrefsTestCase(ObserverTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.prefs = prefs.Preferences()
|
||||||
|
self.prefs.registerObserver(self)
|
||||||
|
|
||||||
|
def testInitialSetup(self):
|
||||||
|
self.assertEqual(len(self.prefs.profiles()), 1)
|
||||||
|
self.assertEqual(len(self.prefs.profileNames()), 1)
|
||||||
|
self.assertEqual(self.prefs.selectedProfile(),
|
||||||
|
self.prefs.profiles()[prefs.DEFAULT_PROFILE_NAME])
|
||||||
|
self.assertEqual(self.prefs.selectedProfileName(),
|
||||||
|
self.prefs.profileNames()[0])
|
||||||
|
|
||||||
|
def testInitialDefaultProfile(self):
|
||||||
|
self.prefs.initDefaultProfile()
|
||||||
|
self.assertChangeCount(2)
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.ADD, 'profile')
|
||||||
|
self.nextChange()
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.MODIFY,
|
||||||
|
'selectedProfile')
|
||||||
|
self.nextChange()
|
||||||
|
|
||||||
|
def testAddRemoveProfile(self):
|
||||||
|
self.prefs.addProfile('test', {})
|
||||||
|
self.assertChangeCount(1)
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.ADD, 'profile')
|
||||||
|
self.assertChangeDataEquals({'test': {}})
|
||||||
|
self.nextChange()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.prefs.addProfile('test', {})
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail('Expected duplicate names to throw KeyError on add.')
|
||||||
|
|
||||||
|
self.prefs.removeProfile('test')
|
||||||
|
self.assertChangeCount(1)
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.REMOVE, 'profile')
|
||||||
|
self.assertChangeDataEquals('test')
|
||||||
|
self.nextChange()
|
||||||
|
|
||||||
|
self.prefs.removeProfile(prefs.DEFAULT_PROFILE_NAME)
|
||||||
|
self.assertChangeCount(3)
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.REMOVE, 'profile')
|
||||||
|
self.assertIsNotNone(self.getChangeData())
|
||||||
|
self.nextChange()
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.ADD, 'profile')
|
||||||
|
self.assertIsNotNone(self.getChangeData())
|
||||||
|
self.nextChange()
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.MODIFY,
|
||||||
|
'selectedProfile')
|
||||||
|
self.assertChangeDataEquals(prefs.DEFAULT_PROFILE_NAME)
|
||||||
|
self.nextChange()
|
||||||
|
|
||||||
|
self.assertEqual(len(self.prefs.profiles()), 1)
|
||||||
|
self.assertEqual(self.prefs.profileNames()[0],
|
||||||
|
prefs.DEFAULT_PROFILE_NAME)
|
||||||
|
|
||||||
|
def testSetSelectedProfile(self):
|
||||||
|
self.prefs.addProfile('test', {})
|
||||||
|
self.skipChange()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.prefs.setSelectedProfile('doesntexist')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail('Expected setSelectedProfile with a bad profile '
|
||||||
|
'name to raise KeyError')
|
||||||
|
|
||||||
|
self.prefs.setSelectedProfile('test')
|
||||||
|
self.assertChangeCount(1)
|
||||||
|
self.assertChangeNotified(self.prefs, ChangeType.MODIFY,
|
||||||
|
'selectedProfile')
|
||||||
|
self.assertChangeDataEquals('test')
|
||||||
|
self.assertEqual(self.prefs.selectedProfileName(), 'test')
|
||||||
|
self.assertEqual(self.prefs.selectedProfile(), {})
|
||||||
|
|
||||||
|
def testSaveLoad(self):
|
||||||
|
p = prefs.Preferences()
|
||||||
|
initial_d = p.saveToDict()
|
||||||
|
self.assertIsNotNone(initial_d)
|
||||||
|
self.assertEqual(initial_d['version'], VERSION)
|
||||||
|
self.assertIn('profiles', initial_d)
|
||||||
|
self.assertIn('selectedProfile', initial_d)
|
||||||
|
|
||||||
|
p = prefs.Preferences(initial_d)
|
||||||
|
new_d = p.saveToDict()
|
||||||
|
self.assertEqual(initial_d, new_d)
|
||||||
|
self.assertChangeCount(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user