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]]