Thread: SF.net SVN: fclient: [577] trunk/fclient/src/fclient/lib/qt4ex/settings.py
Status: Pre-Alpha
Brought to you by:
jurner
From: <jU...@us...> - 2008-07-11 16:34:21
|
Revision: 577 http://fclient.svn.sourceforge.net/fclient/?rev=577&view=rev Author: jUrner Date: 2008-07-11 09:34:31 -0700 (Fri, 11 Jul 2008) Log Message: ----------- deprecate settingsbase use qt4ex.settings instead Added Paths: ----------- trunk/fclient/src/fclient/lib/qt4ex/settings.py Added: trunk/fclient/src/fclient/lib/qt4ex/settings.py =================================================================== --- trunk/fclient/src/fclient/lib/qt4ex/settings.py (rev 0) +++ trunk/fclient/src/fclient/lib/qt4ex/settings.py 2008-07-11 16:34:31 UTC (rev 577) @@ -0,0 +1,368 @@ +"""helpers to work with QSettings +""" +from __future__ import absolute_import +if __name__ == '__main__': # see --> http://bugs.python.org/issue1510172 . works only current dir and below + import os; __path__ = [os.path.dirname(__file__)] + + +import operator +from PyQt4 import QtCore, QtGui + +from . import qtools +#******************************************************************************** +# +#******************************************************************************** +class Setting(object): + __slots__ = ('default', 'type', 'userData', 'value') + def __init__(self, type, value, default, userData=None): + self.default = default + self.type = type + self.userData = userData + self.value = value + +#******************************************************************************** +# +#******************************************************************************** +class SettingsBase(object): + """Base class to deal with reading and writing of settings + + this class tries to take away most of the pain when dealing with QSettings. + + * settings are automatically dumped to disk when they are set + * if a setting can not be read from disk or its type is not ok its default value is taken instead + * settings are always saved and restored in the specified settings order + * any user defined data may be associated to a setting at runtime + + blah more here + + + you should derrive a class from SettingsBase and implement its L{settingsObject} method. + this method is called whenever a settings object is required to read or write a setting. + the subclass must define a '_key_' attribute (key to store the settings to) and a tuple + _settings_. + + blah more here + + + sample usage:: + + class MySettings(settings.SettingsBase): + _key_ = 'MyKey' + _settings_ = ( + ('MySetting-1', 'Bool', True), # name, type, default + ('MySetting-1', 'Bool', True, 0), # or.. name, type, default, userData + ) + + def settingsObject(self): + return QtCore.QSettings() + + s = MySettings() + s.restore() + s.value('MySetting-1') + >> True + + + you may define handlers for custom types as well:: + + class MySettings(settings.SettingsBase): + _key_ = 'MyKey' + _settings_ = ( + ('MySetting-1', 'MyType', True), + ) + + def settingsObject(self): + return QtCore.QSettings() + + def fromMyType(self, settings, name, value): + return QTCore.QVariant(value), True + + def toMyType(self, settings, name, v): + return v.toBool(), True + + + finalisation of the settings object can be handled as well:: + + class MySettings(settings.SettingsBase): + _key_ = 'MyKey' + _settings_ = ( + ('MySetting-1', 'MyType', True), + ) + + def settingsObject(self): + s = QtCore.QSettings() + s.beginGroup('whatever') + return s + + def finalizeSettingsObject(self, settingsObject): + settingsObject.endGroup() + + """ + _settings_ = () # (ValueName, type, DefaultValue, (optional)UserData) + _key_ = '' # + + + def __init__(self, parent=None): + """ + @param parent: (QObject) or None + """ + + self._parent = parent + self._settingsDict = None + self._settingsOrder = None + + self.updateSettingsDict() + + + def finalizeSettingsObject(self, settingsObject): + """called when done with a settings object as returned from L{settingsObject} + @param settingsObject: (QSettings) + @note: default implementation does nothing. overwrite to handle + """ + + + def settingsObject(self): + """should return the QSettings object to store settings to + @return: (QSettings) + @raise NotImplementedError: overrite to handle + """ + raise NotImplementedError() + + ############################################# + ## + ############################################# + def default(self, name): + """returns the default value of a setting + @param name: (str) name of the setting + """ + return self._settingsDict[name].default + + + def parent(self): + """returns the parent of the settings instance""" + return self._parent + + def restore(self): + """restores settings from disk + + @note: values are restored in settings order + @note: the method tries first to find a method to<DesiredType> . if present the method + will be called with three arguments (QSettings,settingName, variant). the method should + convert the variant to the deired value type and return it along with a boolean flag indicating + if the value is ok or not. if it is not ok the settings default value is picked up:: + dumped to disk or not:: + + def toMyType(settings, name, v): + if v.isValid(): + s = v.toString() + if not s.isEmpty(): + return s, True + return None, False + + if no such handler is found it is assumed that the value can be converted directly from the QVariant + by calling QVariant.to<DesiredType>() + + @note: L{finalizeSettingsObject} is called emidiately after the call to allow for clean ups of the settings object + """ + settings = self.settingsObject() + settings.beginGroup(self._key_) + try: + for name in self._settingsOrder: + typeSetting = self.type(name) + if typeSetting is not None: + v = settings.value(name) + # check if we have a conversion method at hand.. + mthd = getattr(self, 'to' + typeSetting, None) + # ..if not definded assert it is a QVariant method + if mthd is None: + mthd = getattr(v, 'to' + typeSetting, None) + if mthd is None: + raise ValueError('%s: no conversion method found for type: %r' % (name, typeSetting)) + obj, ok = qtools.castVariant(v, typeSetting) + else: + obj, ok = getattr(self, 'to' + typeSetting)(settings, name, v) + self._settingsDict[name].value = obj if ok else self.default(name) + finally: + settings.endGroup() + self.finalizeSettingsObject(settings) + + + def restoreDefaults(self, *names): + """restores default values for settings + @param names: names to restore defaults for or no name to restore defaults of all settings + """ + names = names if names else self._settingsOrder + return self.setValues(**dict([(name, self.default(name)) for name in names])) + + + def setDefault(self, name, value): + """sets the default value of a setting + @param name: (str) name of the setting + @param value: default value + """ + self._settingsDict[name].default = value + + + def setType(self, name, value): + """sets the type of a setting + @param name: (str) name of the setting + @param value: desired type + @note: the settings value is not adjusted in the call and it is not dumped to disk. + use L{updateSettingsDict} followed by L{setValues} to do so + """ + self._settingsDict[name].type = value + + + def setUserData(self, name, value): + """associates (any) user defined data to a setting + @param name: (str) name of the setting + """ + self._settingsDict[name].userData = value + + + def setValues(self, **kws): + """sets the value of one or more setting and dumps it to disk + @param kws: name --> value to set + @note: if no kws are specified all settings are dumped to disk + + @note: values are set in settings order + @note: the method tries first to find a method from<DesiredType> . if present the method + will be called with three arguments (QSettings,settingName, settingValue). the method should + convert the value to a QVariant and return it along with a boolean flag indicating if the value should be + dumped to disk or not:: + + def fromMyType(settings, name, value): + v = QtCore.QVariant(value) + if v.isValid(): + return v, True + return None, False + + if no such handler is found it is assumed that the value can be converted directly to a QVariant + + @note: L{finalizeSettingsObject} is called emidiately after the call to allow for clean ups of the settings object + """ + kws = kws if kws else self._settingsDict + + # sort kws by settings order + try: + L = [(self._settingsOrder.index(i[0]), i[0], i[1]) for i in kws.items()] + except ValueError: + raise ValueError('No such setting: %s' % [i for i in kws if i not in self._settingsOrder][0]) + L.sort(key=operator.itemgetter(0)) + + settings = self.settingsObject() + settings.beginGroup(self._key_) + try: + for _, name, value in L: + typeSetting = self.type(name) + self._settingsDict[name].value = value + if typeSetting is not None: + mthd = getattr(self, 'from' + typeSetting, None) + if mthd is None: + v = QtCore.QVariant(value) + ok = True + else: + v, ok = mthd(settings, name, value) + settings.setValue(name, v) if ok else settings.setValue(name, QtCore.QVariant(self.default(name))) + finally: + settings.endGroup() + self.finalizeSettingsObject(settings) + + + def toDict(self): + """Returns a dict containing the current state of the settings object + @return: dict{SettingsName: value} + """ + return dict([(name, setting.value) for (name, setting) in self._settingsDict.items()]) + + + def type(self, name): + """returns the type of a setting + @param name: (str) name of the setting + """ + return self._settingsDict[name].type + + + def updateSettingsDict(self): + """Updates the internal state of the settings object + @note: use this for example if you dynamically add or remove settings + """ + self._settingsDict = {} + self._settingsOrder = [] + for i in self._settings_: + if len(i) == 3: + setting = Setting(i[1], i[2], i[2]) + elif len(i) == 4: + setting = Setting(i[1], i[2], i[2], userData=i[3]) + else: + raise ValueError('setting data should be 2 or three tuple: %r' % name) + name = i[0] + if name in self._settingsOrder: + raise valueError('setting already exists: %r' % name) + self._settingsDict[name] = setting + self._settingsOrder.append(name) + + + def userData(self, name): + """returns the user data associated to a setting + @param name: (str) name of the setting + """ + return self._settingsDict[name].userData + + + def value(self, name): + """returns the value of a setting + @param name: (str) name of the setting + """ + return self._settingsDict[name].value + + ############################################# + ## + ############################################# + def fromQColor(self, settings, name, value): + """default handler to convert a QColor to a QVariant""" + if value is not None: + return QtCore.QVariant(value.name()), True + return QtCore.QVariant(), False + + def toQColor(self, settings, name, v): + """default handler to convert a QVariant to a QColor""" + if v.isValid(): + color = QtGui.QColor(v.toString()) + if color.isValid(): + return color, True + return None, False + + def _fromQPixmap(self, settings, name, value, pixmapFormat): + """helper to convert a QPixmap to a QVariant""" + if value is not None: + arr = QtCore.QByteArray() + p = QtCore.QBuffer(arr) + p.open(QtCore.QIODevice.WriteOnly) + value.save(p, pixmapFormat) + return QtCore.QVariant(arr), True + return None, False + + def _toPixmap(self, settings, name, v): + """helper to convert a QVariant to a QPixmap""" + if v.isValid(): + px = QtGui.QPixmap() + if px.loadFromData(v.toByteArray()): + return px, True + return None, False + + def toQPixmapBmp(self, settings, name, v): return self._toPixmap(settings, name, v) + def fromQPixmapBmp(self, settings, name, value): return self._fromPixmap(settings, name, value, 'BMP') + + def toQPixmapJpg(self, settings, name, v): return self._toPixmap(settings, name, v) + def fromQPixmapJpg(self, settings, name, value): return self._fromPixmap(settings, name, value, 'JPG') + + def toQPixmapPng(self, settings, name, v): return self._toPixmap(settings, name, v) + def fromQPixmapPng(self, settings, name, value): return self._fromPixmap(settings, name, value, 'PNG') + + def toQPixmapXbm(self, settings, name, v): return self._toPixmap(settings, name, v) + def fromQPixmapXbm(self, settings, name, value): return self._fromPixmap(settings, name, value, 'XBM') + + def toQPixmapXpm(self, settings, name, v): return self._toPixmap(settings, name, v) + def fromQPixmapXpm(self, settings, name, value): return self._fromPixmap(settings, name, value, 'XPM') + + \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jU...@us...> - 2008-07-12 20:01:07
|
Revision: 602 http://fclient.svn.sourceforge.net/fclient/?rev=602&view=rev Author: jUrner Date: 2008-07-12 13:01:07 -0700 (Sat, 12 Jul 2008) Log Message: ----------- fix exception Modified Paths: -------------- trunk/fclient/src/fclient/lib/qt4ex/settings.py Modified: trunk/fclient/src/fclient/lib/qt4ex/settings.py =================================================================== --- trunk/fclient/src/fclient/lib/qt4ex/settings.py 2008-07-12 20:00:08 UTC (rev 601) +++ trunk/fclient/src/fclient/lib/qt4ex/settings.py 2008-07-12 20:01:07 UTC (rev 602) @@ -294,7 +294,7 @@ elif len(i) == 4: setting = Setting(i[1], i[2], i[2], userData=i[3]) else: - raise ValueError('setting data should be 2 or three tuple: %r' % name) + raise ValueError('setting data should be 2 or three tuple: %r' % i[0]) name = i[0] if name in self._settingsOrder: raise valueError('setting already exists: %r' % name) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |