X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/4c2cba9ccb6f754aac9378e2fc2c7b546e6d589c..ddff18e87301a328b7b8b03d2f68de8e1029120b:/lib/python/Components/config.py diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py index 4ddcabec..1f2975ef 100755 --- a/lib/python/Components/config.py +++ b/lib/python/Components/config.py @@ -28,11 +28,12 @@ import os # class ConfigElement(object): def __init__(self): - object.__init__(self) self.saved_value = None + self.last_value = None self.save_disabled = False self.notifiers = [] + self.notifiers_final = [] self.enabled = True self.callNotifiersOnSaveAndCancel = False @@ -85,10 +86,16 @@ class ConfigElement(object): for x in self.notifiers: x(self) - def addNotifier(self, notifier, initial_call = True): + def changedFinal(self): + for x in self.notifiers_final: + x(self) + + def addNotifier(self, notifier, initial_call = True, immediate_feedback = True): assert callable(notifier), "notifiers must be callable" - self.notifiers.append(notifier) - + if immediate_feedback: + self.notifiers.append(notifier) + else: + self.notifiers_final.append(notifier) # CHECKME: # do we want to call the notifier # - at all when adding it? (yes, though optional) @@ -110,7 +117,9 @@ class ConfigElement(object): pass def onDeselect(self, session): - pass + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value KEY_LEFT = 0 KEY_RIGHT = 1 @@ -130,6 +139,104 @@ def getKeyNumber(key): assert key in KEY_NUMBERS return key - KEY_0 +class choicesList(object): # XXX: we might want a better name for this + LIST_TYPE_LIST = 1 + LIST_TYPE_DICT = 2 + + def __init__(self, choices, type = None): + self.choices = choices + if type is None: + if isinstance(choices, list): + self.type = choicesList.LIST_TYPE_LIST + elif isinstance(choices, dict): + self.type = choicesList.LIST_TYPE_DICT + else: + assert False, "choices must be dict or list!" + else: + self.type = type + + def __list__(self): + if self.type is choicesList.LIST_TYPE_LIST: + ret = [isinstance(x, tuple) and x[0] or x for x in self.choices] + else: + ret = self.choices.keys() + return ret or [""] + + def __iter__(self): + if self.type is choicesList.LIST_TYPE_LIST: + ret = [isinstance(x, tuple) and x[0] or x for x in self.choices] + else: + ret = self.choices + return iter(ret or [""]) + + def __len__(self): + return len(self.choices) or 1 + + def __getitem__(self, index): + if self.type is choicesList.LIST_TYPE_LIST: + ret = self.choices[index] + if isinstance(ret, tuple): + ret = ret[0] + return ret + return self.choices.keys()[index] + + def index(self, value): + return self.__list__().index(value) + + def __setitem__(self, index, value): + if self.type is choicesList.LIST_TYPE_LIST: + if isinstance(self.choices[index], tuple): + self.choices[index] = (value, self.choices[index][1]) + else: + self.choices[index] = value + else: + key = self.choices.keys()[index] + orig = self.choices[key] + del self.choices[key] + self.choices[value] = orig + + def default(self): + if self.type is choicesList.LIST_TYPE_LIST: + default = self.choices[0] + if isinstance(default, tuple): + default = default[0] + else: + default = self.choices.keys()[0] + return default + +class descriptionList(choicesList): # XXX: we might want a better name for this + def __list__(self): + if self.type is choicesList.LIST_TYPE_LIST: + ret = [isinstance(x, tuple) and x[1] or x for x in self.choices] + else: + ret = self.choices.values() + return ret or [""] + + def __iter__(self): + return iter(self.__list__()) + + def __getitem__(self, index): + if self.type is choicesList.LIST_TYPE_LIST: + for x in self.choices: + if isinstance(x, tuple): + if x[0] is index: + return str(x[1]) + elif x is index: + return str(x) + return str(index) # Fallback! + else: + return str(self.choices.get(index, "")) + + def __setitem__(self, index, value): + if self.type is choicesList.LIST_TYPE_LIST: + i = self.index(index) + if isinstance(self.choices[i], tuple): + self.choices[i] = (self.choices[i][0], value) + else: + self.choices[i] = value + else: + self.choices[index] = value + # # ConfigSelection is a "one of.."-type. # it has the "choices", usually a list, which contains @@ -141,51 +248,30 @@ def getKeyNumber(key): class ConfigSelection(ConfigElement): def __init__(self, choices, default = None): ConfigElement.__init__(self) - self._value = None - self.setChoices(choices, default) - def setChoices(self, choices, default = None): - self.choices = [] - self.description = {} - - if isinstance(choices, list): - for x in choices: - if isinstance(x, tuple): - self.choices.append(x[0]) - self.description[x[0]] = x[1] - else: - self.choices.append(x) - self.description[x] = x - elif isinstance(choices, dict): - for (key, val) in choices.items(): - self.choices.append(key) - self.description[key] = val - else: - assert False, "ConfigSelection choices must be dict or list!" - - #assert len(self.choices), "you can't have an empty configselection" - if len(self.choices) == 0: - self.choices = [""] - self.description[""] = "" + # this is an exakt copy of def setChoices.. but we save the call overhead + self.choices = choicesList(choices) if default is None: - default = self.choices[0] + default = self.choices.default() - assert default in self.choices, "default must be in choice list, but " + repr(default) + " is not!" - for x in self.choices: - assert isinstance(x, str), "ConfigSelection choices must be strings" - - self.default = default + self.default = self._value = self.last_value = default + self.changed() - if self.value == None or not self.value in self.choices: - self.value = default + def setChoices(self, choices, default = None): + self.choices = choicesList(choices) + + if default is None: + default = self.choices.default() + + self.default = self._value = self.last_value = default + self.changed() def setValue(self, value): if value in self.choices: self._value = value else: self._value = self.default - self.changed() def tostring(self, val): @@ -196,9 +282,8 @@ class ConfigSelection(ConfigElement): def setCurrentText(self, text): i = self.choices.index(self.value) - del self.description[self.choices[i]] self.choices[i] = text - self.description[text] = text + descriptionList(self.choices.choices, self.choices.type)[text] = text self._value = text value = property(getValue, setValue) @@ -227,13 +312,13 @@ class ConfigSelection(ConfigElement): self.value = self.choices[(i + 1) % nchoices] def getText(self): - descr = self.description[self.value] + descr = descriptionList(self.choices.choices, self.choices.type)[self.value] if len(descr): return _(descr) return descr def getMulti(self, selected): - descr = self.description[self.value] + descr = descriptionList(self.choices.choices, self.choices.type)[self.value] if len(descr): return ("text", _(descr)) return ("text", descr) @@ -242,11 +327,12 @@ class ConfigSelection(ConfigElement): def getHTML(self, id): res = "" for v in self.choices: + descr = descriptionList(self.choices.choices, self.choices.type)[v] if self.value == v: checked = 'checked="checked" ' else: checked = '' - res += '' + self.description[v] + "
\n" + res += '' + descr + "
\n" return res; def unsafeAssign(self, value): @@ -262,7 +348,8 @@ class ConfigBoolean(ConfigElement): def __init__(self, default = False, descriptions = {False: "false", True: "true"}): ConfigElement.__init__(self) self.descriptions = descriptions - self.value = self.default = default + self.value = self.last_value = self.default = default + def handleKey(self, key): if key in [KEY_LEFT, KEY_RIGHT]: self.value = not self.value @@ -309,6 +396,11 @@ class ConfigBoolean(ConfigElement): else: self.value = False + def onDeselect(self, session): + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value + class ConfigYesNo(ConfigBoolean): def __init__(self, default = False): ConfigBoolean.__init__(self, default = default, descriptions = {False: _("no"), True: _("yes")}) @@ -326,7 +418,7 @@ class ConfigDateTime(ConfigElement): ConfigElement.__init__(self) self.increment = increment self.formatstring = formatstring - self.value = self.default = int(default) + self.value = self.last_value = self.default = int(default) def handleKey(self, key): if key == KEY_LEFT: @@ -367,6 +459,7 @@ class ConfigSequence(ConfigElement): self.default = default self.value = copy.copy(default) + self.last_value = copy.copy(default) self.endNotifier = [] @@ -507,6 +600,11 @@ class ConfigSequence(ConfigElement): def fromstring(self, value): return [int(x) for x in value.split(self.seperator)] + def onDeselect(self, session): + if not self.last_value == self._value: + self.changedFinal() + self.last_value = copy.copy(self._value) + class ConfigIP(ConfigSequence): def __init__(self, default, auto_jump = False): ConfigSequence.__init__(self, seperator = ".", limits = [(0,255),(0,255),(0,255),(0,255)], default = default) @@ -604,6 +702,36 @@ class ConfigClock(ConfigSequence): t = time.localtime(default) ConfigSequence.__init__(self, seperator = ":", limits = [(0,23),(0,59)], default = [t.tm_hour, t.tm_min]) + def increment(self): + # Check if Minutes maxed out + if self._value[1] == 59: + # Increment Hour, reset Minutes + if self._value[0] < 23: + self._value[0] += 1 + else: + self._value[0] = 0 + self._value[1] = 0 + else: + # Increment Minutes + self._value[1] += 1 + # Trigger change + self.changed() + + def decrement(self): + # Check if Minutes is minimum + if self._value[1] == 0: + # Decrement Hour, set Minutes to 59 + if self._value[0] > 0: + self._value[0] -= 1 + else: + self._value[0] = 23 + self._value[1] = 59 + else: + # Decrement Minutes + self._value[1] -= 1 + # Trigger change + self.changed() + class ConfigInteger(ConfigSequence): def __init__(self, default, limits = (0, 9999999999)): ConfigSequence.__init__(self, seperator = ":", limits = [limits], default = default) @@ -657,7 +785,7 @@ class ConfigText(ConfigElement, NumericalTextInput): self.offset = 0 self.overwrite = fixed_size self.help_window = None - self.value = self.default = default + self.value = self.last_value = self.default = default def validateMarker(self): if self.fixed_size: @@ -782,12 +910,12 @@ class ConfigText(ConfigElement, NumericalTextInput): def getValue(self): return self.text.encode("utf-8") - + def setValue(self, val): try: self.text = val.decode("utf-8") except UnicodeDecodeError: - self.text = val + self.text = val.decode("utf-8", "ignore") print "Broken UTF8!" value = property(getValue, setValue) @@ -823,6 +951,9 @@ class ConfigText(ConfigElement, NumericalTextInput): if self.help_window: session.deleteDialog(self.help_window) self.help_window = None + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value def getHTML(self, id): return '
\n' @@ -897,12 +1028,40 @@ class ConfigNumber(ConfigText): def onDeselect(self, session): self.marked_pos = 0 self.offset = 0 + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value + +class ConfigSearchText(ConfigText): + def __init__(self, default = "", fixed_size = False, visible_width = False): + ConfigText.__init__(self, default = default, fixed_size = fixed_size, visible_width = visible_width) + NumericalTextInput.__init__(self, nextFunc = self.nextFunc, handleTimeout = False, search = True) + +class ConfigDirectory(ConfigText): + def __init__(self, default="", visible_width=60): + ConfigText.__init__(self, default, fixed_size = True, visible_width = visible_width) + def handleKey(self, key): + pass + def getValue(self): + if self.text == "": + return None + else: + return ConfigText.getValue(self) + def setValue(self, val): + if val == None: + val = "" + ConfigText.setValue(self, val) + def getMulti(self, selected): + if self.text == "": + return ("mtext"[1-selected:], _("List of Storage Devices"), range(0)) + else: + return ConfigText.getMulti(self, selected) # a slider. class ConfigSlider(ConfigElement): def __init__(self, default = 0, increment = 1, limits = (0, 100)): ConfigElement.__init__(self) - self.value = self.default = default + self.value = self.last_value = self.default = default self.min = limits[0] self.max = limits[1] self.increment = increment @@ -954,28 +1113,17 @@ class ConfigSatlist(ConfigSelection): class ConfigSet(ConfigElement): def __init__(self, choices, default = []): ConfigElement.__init__(self) - self.choices = [] - self.description = {} if isinstance(choices, list): choices.sort() - for x in choices: - if isinstance(x, tuple): - self.choices.append(x[0]) - self.description[x[0]] = str(x[1]) - else: - self.choices.append(x) - self.description[x] = str(x) + self.choices = choicesList(choices, choicesList.LIST_TYPE_LIST) else: assert False, "ConfigSet choices must be a list!" - if len(self.choices) == 0: - self.choices = [""] - self.description[""] = "" if default is None: default = [] self.pos = -1 default.sort() - self.default = default - self.value = default+[] + self.last_value = self.default = default + self.value = default[:] def toggleChoice(self, choice): if choice in self.value: @@ -983,6 +1131,7 @@ class ConfigSet(ConfigElement): else: self.value.append(choice) self.value.sort() + self.changed() def handleKey(self, key): if key in KEY_NUMBERS + [KEY_DELETE, KEY_BACKSPACE]: @@ -1001,8 +1150,9 @@ class ConfigSet(ConfigElement): def genString(self, lst): res = "" + description = descriptionList(self.choices.choices, choicesList.LIST_TYPE_LIST) for x in lst: - res += self.description[x]+" " + res += description[x]+" " return res def getText(self): @@ -1012,7 +1162,8 @@ class ConfigSet(ConfigElement): if not selected or self.pos == -1: return ("text", self.genString(self.value)) else: - tmp = self.value+[] + description = descriptionList(self.choices.choices, choicesList.LIST_TYPE_LIST) + tmp = self.value[:] ch = self.choices[self.pos] mem = ch in self.value if not mem: @@ -1022,14 +1173,16 @@ class ConfigSet(ConfigElement): val1 = self.genString(tmp[:ind]) val2 = " "+self.genString(tmp[ind+1:]) if mem: - chstr = " "+self.description[ch]+" " + chstr = " "+description[ch]+" " else: - chstr = "("+self.description[ch]+")" + chstr = "("+description[ch]+")" return ("mtext", val1+chstr+val2, range(len(val1),len(val1)+len(chstr))) def onDeselect(self, session): self.pos = -1 - self.changed() + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value[:] def tostring(self, value): return str(value) @@ -1046,6 +1199,7 @@ class ConfigLocations(ConfigElement): self.locations = [] self.mountpoints = [] harddiskmanager.on_partition_list_change.append(self.mountpointsChanged) + self.value = default+[] def setValue(self, value): loc = [x[0] for x in self.locations if x[3]]