+ for x in self.values():
+ x.save()
+
+ def load(self):
+ for x in self.values():
+ x.load()
+
+ def getSavedValue(self):
+ res = {}
+ for (key, val) in self.items():
+ sv = val.saved_value
+ if sv is not None:
+ res[str(key)] = sv
+ return res
+
+ def setSavedValue(self, values):
+ self.stored_values = dict(values)
+ for (key, val) in self.items():
+ if str(key) in self.stored_values:
+ val.saved_value = self.stored_values[str(key)]
+
+ saved_value = property(getSavedValue, setSavedValue)
+
+ def __setitem__(self, key, item):
+ dict.__setitem__(self, key, item)
+ if str(key) in self.stored_values:
+ item.saved_value = self.stored_values[str(key)]
+ item.load()
+
+ def dict(self):
+ return self
+
+# Like the classes above, just with a more "native"
+# syntax.
+#
+# some evil stuff must be done to allow instant
+# loading of added elements. this is why this class
+# is so complex.
+#
+# we need the 'content' because we overwrite
+# __setattr__.
+# If you don't understand this, try adding
+# __setattr__ to a usual exisiting class and you will.
+class ConfigSubsection(object):
+ def __init__(self):
+ self.__dict__["content"] = ConfigSubsectionContent()
+ self.content.items = { }
+ self.content.stored_values = { }
+
+ def __setattr__(self, name, value):
+ if name == "saved_value":
+ return self.setSavedValue(value)
+ assert isinstance(value, (ConfigSubsection, ConfigElement, ConfigSubList, ConfigSubDict)), "ConfigSubsections can only store ConfigSubsections, ConfigSubLists, ConfigSubDicts or ConfigElements"
+ content = self.content
+ content.items[name] = value
+ x = content.stored_values.get(name, None)
+ if x is not None:
+ #print "ok, now we have a new item,", name, "and have the following value for it:", x
+ value.saved_value = x
+ value.load()
+
+ def __getattr__(self, name):
+ return self.content.items[name]
+
+ def getSavedValue(self):
+ res = self.content.stored_values
+ for (key, val) in self.content.items.items():
+ sv = val.saved_value
+ if sv is not None:
+ res[key] = sv
+ elif key in res:
+ del res[key]
+ return res
+
+ def setSavedValue(self, values):
+ values = dict(values)
+ self.content.stored_values = values
+ for (key, val) in self.content.items.items():
+ value = values.get(key, None)
+ if value is not None:
+ val.saved_value = value
+
+ saved_value = property(getSavedValue, setSavedValue)
+
+ def save(self):
+ for x in self.content.items.values():
+ x.save()
+
+ def load(self):
+ for x in self.content.items.values():
+ x.load()
+
+ def dict(self):
+ return self.content.items
+
+# the root config object, which also can "pickle" (=serialize)
+# down the whole config tree.
+#
+# we try to keep non-existing config entries, to apply them whenever
+# a new config entry is added to a subsection
+# also, non-existing config entries will be saved, so they won't be
+# lost when a config entry disappears.
+class Config(ConfigSubsection):
+ def __init__(self):
+ ConfigSubsection.__init__(self)
+
+ def pickle_this(self, prefix, topickle, result):
+ for (key, val) in topickle.items():
+ name = '.'.join((prefix, key))
+ if isinstance(val, dict):
+ self.pickle_this(name, val, result)
+ elif isinstance(val, tuple):
+ result += [name, '=', val[0], '\n']
+ else:
+ result += [name, '=', val, '\n']
+
+ def pickle(self):
+ result = []
+ self.pickle_this("config", self.saved_value, result)
+ return ''.join(result)
+
+ def unpickle(self, lines):
+ tree = { }
+ for l in lines:
+ if not l or l[0] == '#':
+ continue
+
+ n = l.find('=')
+ val = l[n+1:].strip()
+
+ names = l[:n].split('.')
+# if val.find(' ') != -1:
+# val = val[:val.find(' ')]
+
+ base = tree
+
+ for n in names[:-1]:
+ base = base.setdefault(n, {})
+
+ base[names[-1]] = val
+
+ # we inherit from ConfigSubsection, so ...
+ #object.__setattr__(self, "saved_value", tree["config"])
+ if "config" in tree:
+ self.setSavedValue(tree["config"])
+
+ def saveToFile(self, filename):
+ text = self.pickle()
+ f = open(filename, "w")
+ f.write(text)
+ f.close()
+
+ def loadFromFile(self, filename):
+ f = open(filename, "r")
+ self.unpickle(f.readlines())
+ f.close()
+
+config = Config()
+config.misc = ConfigSubsection()
+
+class ConfigFile:
+ CONFIG_FILE = resolveFilename(SCOPE_CONFIG, "settings")
+
+ def load(self):
+ try:
+ config.loadFromFile(self.CONFIG_FILE)
+ except IOError, e:
+ print "unable to load config (%s), assuming defaults..." % str(e)
+
+ def save(self):
+# config.save()
+ config.saveToFile(self.CONFIG_FILE)
+
+ def __resolveValue(self, pickles, cmap):
+ key = pickles[0]
+ if cmap.has_key(key):
+ if len(pickles) > 1:
+ return self.__resolveValue(pickles[1:], cmap[key].dict())
+ else:
+ return str(cmap[key].value)
+ return None
+
+ def getResolvedKey(self, key):
+ names = key.split('.')
+ if len(names) > 1:
+ if names[0] == "config":
+ ret=self.__resolveValue(names[1:], config.content.items)
+ if ret and len(ret):
+ return ret
+ print "getResolvedKey", key, "failed !! (Typo??)"
+ return ""
+
+def NoSave(element):
+ element.disableSave()
+ return element
+
+configfile = ConfigFile()
+
+configfile.load()
+
+def getConfigListEntry(*args):
+ assert len(args) > 1, "getConfigListEntry needs a minimum of two arguments (descr, configElement)"
+ return args
+
+def updateConfigElement(element, newelement):
+ newelement.value = element.value
+ return newelement
+
+#def _(x):
+# return x
+#
+#config.bla = ConfigSubsection()
+#config.bla.test = ConfigYesNo()
+#config.nim = ConfigSubList()
+#config.nim.append(ConfigSubsection())
+#config.nim[0].bla = ConfigYesNo()
+#config.nim.append(ConfigSubsection())
+#config.nim[1].bla = ConfigYesNo()
+#config.nim[1].blub = ConfigYesNo()
+#config.arg = ConfigSubDict()
+#config.arg["Hello"] = ConfigYesNo()
+#
+#config.arg["Hello"].handleKey(KEY_RIGHT)
+#config.arg["Hello"].handleKey(KEY_RIGHT)
+#
+##config.saved_value
+#
+##configfile.save()
+#config.save()
+#print config.pickle()