- show NumericalTextInput on text config entries
[enigma2.git] / lib / python / Screens / Wizard.py
1 from Screen import Screen
2
3 import string
4
5 from Screens.HelpMenu import HelpableScreen
6 from Components.config import config, KEY_LEFT, KEY_RIGHT, KEY_DELETE, KEY_BACKSPACE
7 from Components.Label import Label
8 from Components.Slider import Slider
9 from Components.ActionMap import NumberActionMap
10 from Components.MenuList import MenuList
11 from Components.ConfigList import ConfigList
12 from Components.Sources.List import List
13
14 from enigma import eTimer
15
16 from xml.sax import make_parser
17 from xml.sax.handler import ContentHandler
18
19 class WizardSummary(Screen):
20         skin = """
21         <screen position="0,0" size="132,64">
22                 <widget name="text" position="6,4" size="120,42" font="Regular;14" transparent="1" />
23                 <widget source="parent.list" render="Label" position="6,25" size="120,21" font="Regular;16">
24                         <convert type="StringListSelection" />
25                 </widget>
26         </screen>"""
27         
28         def __init__(self, session, parent):
29                 Screen.__init__(self, session, parent)
30                 
31                 #names = parent.skinName
32                 #if not isinstance(names, list):
33                         #names = [names]
34 #                       
35                 #self.skinName = [x + "_summary" for x in names ]
36                 #self.skinName.append("Wizard")
37                 #print "*************+++++++++++++++++****************++++++++++******************* WizardSummary", self.skinName
38                         #
39                 self["text"] = Label("")
40                 self.onShow.append(self.setCallback)
41                 
42         def setCallback(self):
43                 self.parent.setLCDTextCallback(self.setText)
44                 
45         def setText(self, text):
46                 self["text"].setText(text)
47
48 class Wizard(Screen):
49         def createSummary(self):
50                         print "WizardCreateSummary"
51                         return WizardSummary
52
53         class parseWizard(ContentHandler):
54                 def __init__(self, wizard):
55                         self.isPointsElement, self.isReboundsElement = 0, 0
56                         self.wizard = wizard
57                         self.currContent = ""
58                         self.lastStep = 0       
59
60                 def startElement(self, name, attrs):
61                         #print "startElement", name
62                         self.currContent = name
63                         if (name == "step"):
64                                 self.lastStep += 1
65                                 if attrs.has_key('id'):
66                                         id = str(attrs.get('id'))
67                                 else:
68                                         id = ""
69                                 #print "id:", id
70                                 if attrs.has_key('nextstep'):
71                                         nextstep = str(attrs.get('nextstep'))
72                                 else:
73                                         nextstep = None
74                                 if attrs.has_key('timeout'):
75                                         timeout = int(attrs.get('timeout'))
76                                 else:
77                                         timeout = None
78                                 if attrs.has_key('timeoutaction'):
79                                         timeoutaction = str(attrs.get('timeoutaction'))
80                                 else:
81                                         timeoutaction = 'nextpage'
82
83                                 if attrs.has_key('timeoutstep'):
84                                         timeoutstep = str(attrs.get('timeoutstep'))
85                                 else:
86                                         timeoutstep = ''
87                                 self.wizard[self.lastStep] = {"id": id, "condition": "", "text": "", "timeout": timeout, "timeoutaction": timeoutaction, "timeoutstep": timeoutstep, "list": [], "config": {"screen": None, "args": None, "type": "" }, "code": "", "codeafter": "", "nextstep": nextstep}
88                         elif (name == "text"):
89                                 self.wizard[self.lastStep]["text"] = string.replace(str(attrs.get('value')), "\\n", "\n")
90                         elif (name == "displaytext"):
91                                 self.wizard[self.lastStep]["displaytext"] = string.replace(str(attrs.get('value')), "\\n", "\n")
92                         elif (name == "list"):
93                                 if (attrs.has_key('type')):
94                                         if attrs["type"] == "dynamic":
95                                                 self.wizard[self.lastStep]["dynamiclist"] = attrs.get("source")
96                                         #self.wizard[self.lastStep]["list"].append(("Hallo", "test"))
97                                 if (attrs.has_key("evaluation")):
98                                         #print "evaluation"
99                                         self.wizard[self.lastStep]["listevaluation"] = attrs.get("evaluation")
100                                 if (attrs.has_key("onselect")):
101                                         self.wizard[self.lastStep]["onselect"] = attrs.get("onselect")                  
102                         elif (name == "listentry"):
103                                 self.wizard[self.lastStep]["list"].append((str(attrs.get('caption')), str(attrs.get('step'))))
104                         elif (name == "config"):
105                                 type = str(attrs.get('type'))
106                                 self.wizard[self.lastStep]["config"]["type"] = type
107                                 if type == "ConfigList" or type == "standalone":
108                                         try:
109                                                 exec "from Screens." + str(attrs.get('module')) + " import *"
110                                         except:
111                                                 exec "from " + str(attrs.get('module')) + " import *"
112                                 
113                                         self.wizard[self.lastStep]["config"]["screen"] = eval(str(attrs.get('screen')))
114                                         if (attrs.has_key('args')):
115                                                 #print "has args"
116                                                 self.wizard[self.lastStep]["config"]["args"] = str(attrs.get('args'))
117                                 elif type == "dynamic":
118                                         self.wizard[self.lastStep]["config"]["source"] = str(attrs.get('source'))
119                                         if (attrs.has_key('evaluation')):
120                                                 self.wizard[self.lastStep]["config"]["evaluation"] = str(attrs.get('evaluation'))
121                         elif (name == "code"):
122                                 if attrs.has_key('pos') and str(attrs.get('pos')) == "after":
123                                         self.codeafter = True
124                                 else:
125                                         self.codeafter = False
126                         elif (name == "condition"):
127                                 pass
128                         
129                 def endElement(self, name):
130                         self.currContent = ""
131                         if name == 'code':
132                                 if self.codeafter:
133                                         self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"].strip()
134                                 else:
135                                         self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"].strip()
136                         elif name == 'condition':
137                                 self.wizard[self.lastStep]["condition"] = self.wizard[self.lastStep]["condition"].strip()
138                         elif name == 'step':
139                                 #print "Step number", self.lastStep, ":", self.wizard[self.lastStep]
140                                 pass
141                                                                 
142                 def characters(self, ch):
143                         if self.currContent == "code":
144                                 if self.codeafter:
145                                         self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"] + ch
146                                 else:
147                                         self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"] + ch
148                         elif self.currContent == "condition":
149                                  self.wizard[self.lastStep]["condition"] = self.wizard[self.lastStep]["condition"] + ch
150
151         def __init__(self, session, showSteps = True, showStepSlider = True, showList = True, showConfig = True):
152                 Screen.__init__(self, session)
153
154                 self.stepHistory = []
155
156                 self.wizard = {}
157                 parser = make_parser()
158                 if not isinstance(self.xmlfile, list):
159                         self.xmlfile = [self.xmlfile]
160                 print "Reading ", self.xmlfile
161                 wizardHandler = self.parseWizard(self.wizard)
162                 parser.setContentHandler(wizardHandler)
163                 for xmlfile in self.xmlfile:
164                         if xmlfile[0] != '/':
165                                 parser.parse('/usr/share/enigma2/' + xmlfile)
166                         else:
167                                 parser.parse(xmlfile)
168
169                 self.showSteps = showSteps
170                 self.showStepSlider = showStepSlider
171                 self.showList = showList
172                 self.showConfig = showConfig
173
174                 self.numSteps = len(self.wizard)
175                 self.currStep = self.getStepWithID("start") + 1
176                 
177                 self.timeoutTimer = eTimer()
178                 self.timeoutTimer.callback.append(self.timeoutCounterFired)
179
180                 self["text"] = Label()
181
182                 if showConfig:
183                         self["config"] = ConfigList([], session = session)
184
185                 if self.showSteps:
186                         self["step"] = Label()
187                 
188                 if self.showStepSlider:
189                         self["stepslider"] = Slider(1, self.numSteps)
190                 
191                 if self.showList:
192                         self.list = []
193                         self["list"] = List(self.list, enableWrapAround = True)
194                         self["list"].onSelectionChanged.append(self.selChanged)
195                         #self["list"] = MenuList(self.list, enableWrapAround = True)
196
197                 self.onShown.append(self.updateValues)
198
199                 self.configInstance = None
200                 
201                 self.lcdCallbacks = []
202                 
203                 self.disableKeys = False
204                 
205                 self["actions"] = NumberActionMap(["WizardActions", "NumberActions", "ColorActions", "SetupActions"],
206                 {
207                         "ok": self.ok,
208                         "back": self.back,
209                         "left": self.left,
210                         "right": self.right,
211                         "up": self.up,
212                         "down": self.down,
213                         "red": self.red,
214                         "green": self.green,
215                         "yellow": self.yellow,
216                         "blue":self.blue,
217                         "deleteBackward": self.deleteBackward,
218                         "deleteForward": self.deleteForward,
219                         "1": self.keyNumberGlobal,
220                         "2": self.keyNumberGlobal,
221                         "3": self.keyNumberGlobal,
222                         "4": self.keyNumberGlobal,
223                         "5": self.keyNumberGlobal,
224                         "6": self.keyNumberGlobal,
225                         "7": self.keyNumberGlobal,
226                         "8": self.keyNumberGlobal,
227                         "9": self.keyNumberGlobal,
228                         "0": self.keyNumberGlobal
229                 }, -1)
230                 
231         def red(self):
232                 print "red"
233                 pass
234
235         def green(self):
236                 print "green"
237                 pass
238         
239         def yellow(self):
240                 print "yellow"
241                 pass
242         
243         def blue(self):
244                 print "blue"
245                 pass
246         
247         def deleteForward(self):
248                 self.resetCounter()
249                 if (self.wizard[self.currStep]["config"]["screen"] != None):
250                         self.configInstance.keyDelete()
251                 elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
252                         self["config"].handleKey(KEY_DELETE)
253                 print "deleteForward"
254
255         def deleteBackward(self):
256                 self.resetCounter()
257                 if (self.wizard[self.currStep]["config"]["screen"] != None):
258                         self.configInstance.keyBackspace()
259                 elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
260                         self["config"].handleKey(KEY_BACKSPACE)
261                 print "deleteBackward"
262         
263         def setLCDTextCallback(self, callback):
264                 self.lcdCallbacks.append(callback)
265
266         def back(self):
267                 if self.disableKeys:
268                         return
269                 print "getting back..."
270                 print "stepHistory:", self.stepHistory
271                 if len(self.stepHistory) > 1:
272                         self.currStep = self.stepHistory[-2]
273                         self.stepHistory = self.stepHistory[:-2]
274                 if self.currStep < 1:
275                         self.currStep = 1
276                 print "currStep:", self.currStep
277                 print "new stepHistory:", self.stepHistory
278                 self.updateValues()
279                 print "after updateValues stepHistory:", self.stepHistory
280                 
281         def markDone(self):
282                 pass
283         
284         def getStepWithID(self, id):
285                 print "getStepWithID:", id
286                 count = 0
287                 for x in self.wizard.keys():
288                         if self.wizard[x]["id"] == id:
289                                 print "result:", count
290                                 return count
291                         count += 1
292                 print "result: nothing"
293                 return 0
294
295         def finished(self, gotoStep = None, *args, **kwargs):
296                 print "finished"
297                 currStep = self.currStep
298
299                 if self.updateValues not in self.onShown:
300                         self.onShown.append(self.updateValues)
301                         
302                 if self.showConfig:
303                         if self.wizard[currStep]["config"]["type"] == "dynamic":
304                                 eval("self." + self.wizard[currStep]["config"]["evaluation"])()
305                         
306                 if self.showList:
307                         if (len(self.wizard[currStep]["evaluatedlist"]) > 0):
308                                 print "current:", self["list"].current
309                                 nextStep = self["list"].current[1]
310                                 if (self.wizard[currStep].has_key("listevaluation")):
311                                         exec("self." + self.wizard[self.currStep]["listevaluation"] + "('" + nextStep + "')")
312                                 else:
313                                         self.currStep = self.getStepWithID(nextStep)
314
315                 if ((currStep == self.numSteps and self.wizard[currStep]["nextstep"] is None) or self.wizard[currStep]["id"] == "end"): # wizard finished
316                         print "wizard finished"
317                         self.markDone()
318                         self.close()
319                 else:
320                         self.runCode(self.wizard[currStep]["codeafter"])
321                         if self.wizard[currStep]["nextstep"] is not None:
322                                 self.currStep = self.getStepWithID(self.wizard[currStep]["nextstep"])
323                         if gotoStep is not None:
324                                 self.currStep = self.getStepWithID(gotoStep)
325                         self.currStep += 1
326                         self.updateValues()
327
328                 print "Now: " + str(self.currStep)
329
330
331         def ok(self):
332                 print "OK"
333                 if self.disableKeys:
334                         return
335                 currStep = self.currStep
336                 
337                 if self.showConfig:
338                         if (self.wizard[currStep]["config"]["screen"] != None):
339                                 # TODO: don't die, if no run() is available
340                                 # there was a try/except here, but i can't see a reason
341                                 # for this. If there is one, please do a more specific check
342                                 # and/or a comment in which situation there is no run()
343                                 if callable(getattr(self.configInstance, "runAsync", None)):
344                                         self.onShown.remove(self.updateValues)
345                                         self.configInstance.runAsync(self.finished)
346                                         return
347                                 else:
348                                         self.configInstance.run()
349                 self.finished()
350
351         def keyNumberGlobal(self, number):
352                 if (self.wizard[self.currStep]["config"]["screen"] != None):
353                         self.configInstance.keyNumberGlobal(number)
354                 
355         def left(self):
356                 self.resetCounter()
357                 if (self.wizard[self.currStep]["config"]["screen"] != None):
358                         self.configInstance.keyLeft()
359                 elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
360                         self["config"].handleKey(KEY_LEFT)
361                 print "left"
362         
363         def right(self):
364                 self.resetCounter()
365                 if (self.wizard[self.currStep]["config"]["screen"] != None):
366                         self.configInstance.keyRight()
367                 elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
368                         self["config"].handleKey(KEY_RIGHT)     
369                 print "right"
370
371         def up(self):
372                 self.resetCounter()
373                 if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None  or self.wizard[self.currStep]["config"]["type"] == "dynamic"):
374                                 self["config"].instance.moveSelection(self["config"].instance.moveUp)
375                 elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0):
376                         self["list"].selectPrevious()
377                         if self.wizard[self.currStep].has_key("onselect"):
378                                 print "current:", self["list"].current
379                                 self.selection = self["list"].current[-1]
380                                 #self.selection = self.wizard[self.currStep]["evaluatedlist"][self["list"].l.getCurrentSelectionIndex()][1]
381                                 exec("self." + self.wizard[self.currStep]["onselect"] + "()")
382                 print "up"
383                 
384         def down(self):
385                 self.resetCounter()
386                 if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None  or self.wizard[self.currStep]["config"]["type"] == "dynamic"):
387                         self["config"].instance.moveSelection(self["config"].instance.moveDown)
388                 elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0):
389                         #self["list"].instance.moveSelection(self["list"].instance.moveDown)
390                         self["list"].selectNext()
391                         if self.wizard[self.currStep].has_key("onselect"):
392                                 print "current:", self["list"].current
393                                 #self.selection = self.wizard[self.currStep]["evaluatedlist"][self["list"].l.getCurrentSelectionIndex()][1]
394                                 #exec("self." + self.wizard[self.currStep]["onselect"] + "()")
395                                 self.selection = self["list"].current[-1]
396                                 #self.selection = self.wizard[self.currStep]["evaluatedlist"][self["list"].l.getCurrentSelectionIndex()][1]
397                                 exec("self." + self.wizard[self.currStep]["onselect"] + "()")
398                 print "down"
399                 
400         def selChanged(self):
401                 self.resetCounter()
402                 
403                 if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None):
404                                 self["config"].instance.moveSelection(self["config"].instance.moveUp)
405                 elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0):
406                         if self.wizard[self.currStep].has_key("onselect"):
407                                 self.selection = self["list"].current[-1]
408                                 print "self.selection:", self.selection
409                                 exec("self." + self.wizard[self.currStep]["onselect"] + "()")
410                 
411         def resetCounter(self):
412                 self.timeoutCounter = self.wizard[self.currStep]["timeout"]
413                 
414         def runCode(self, code):
415                 if code != "":
416                         print "code", code
417                         exec(code)
418                         
419         def getTranslation(self, text):
420                 return _(text)
421                         
422         def updateText(self, firstset = False):
423                 text = self.getTranslation(self.wizard[self.currStep]["text"])
424                 if text.find("[timeout]") != -1:
425                         text = text.replace("[timeout]", str(self.timeoutCounter))
426                         self["text"].setText(text)
427                 else:
428                         if firstset:
429                                 self["text"].setText(text)
430                 
431         def updateValues(self):
432                 print "Updating values in step " + str(self.currStep)
433                 # calling a step which doesn't exist can only happen if the condition in the last step is not fulfilled
434                 # if a non-existing step is called, end the wizard 
435                 if self.currStep > len(self.wizard):
436                         self.markDone()
437                         self.close()
438                         return
439
440                 self.timeoutTimer.stop()
441                 
442                 if self.configInstance is not None:
443                         del self.configInstance["config"]
444                         self.configInstance.doClose()
445                         self.configInstance = None
446                 
447                 self.condition = True
448                 exec (self.wizard[self.currStep]["condition"])
449                 if self.condition:
450                         if len(self.stepHistory) == 0 or self.stepHistory[-1] != self.currStep:
451                                 self.stepHistory.append(self.currStep)
452                         print "wizard step:", self.wizard[self.currStep]
453                         
454                         if self.showSteps:
455                                 self["step"].setText(self.getTranslation("Step ") + str(self.currStep) + "/" + str(self.numSteps))
456                         if self.showStepSlider:
457                                 self["stepslider"].setValue(self.currStep)
458                 
459                         if self.wizard[self.currStep]["timeout"] is not None:
460                                 self.resetCounter() 
461                                 self.timeoutTimer.start(1000)
462                         
463                         print "wizard text", self.getTranslation(self.wizard[self.currStep]["text"])
464                         self.updateText(firstset = True)
465                         if self.wizard[self.currStep].has_key("displaytext"):
466                                 displaytext = self.wizard[self.currStep]["displaytext"]
467                                 print "set LCD text"
468                                 for x in self.lcdCallbacks:
469                                         x(displaytext)
470                                 
471                         self.runCode(self.wizard[self.currStep]["code"])
472                         
473                         if self.showList:
474                                 print "showing list,", self.currStep
475                                 for renderer in self.renderer:
476                                         rootrenderer = renderer
477                                         while renderer.source is not None:
478                                                 print "self.list:", self["list"]
479                                                 if renderer.source is self["list"]:
480                                                         print "setZPosition"
481                                                         rootrenderer.instance.setZPosition(1)
482                                                 renderer = renderer.source
483                                                 
484                                 #self["list"].instance.setZPosition(1)
485                                 self.list = []
486                                 if (self.wizard[self.currStep].has_key("dynamiclist")):
487                                         print "dynamic list, calling",  self.wizard[self.currStep]["dynamiclist"]
488                                         newlist = eval("self." + self.wizard[self.currStep]["dynamiclist"] + "()")
489                                         #self.wizard[self.currStep]["evaluatedlist"] = []
490                                         for entry in newlist:
491                                                 #self.wizard[self.currStep]["evaluatedlist"].append(entry)
492                                                 self.list.append(entry)
493                                         #del self.wizard[self.currStep]["dynamiclist"]
494                                 if (len(self.wizard[self.currStep]["list"]) > 0):
495                                         #self["list"].instance.setZPosition(2)
496                                         for x in self.wizard[self.currStep]["list"]:
497                                                 self.list.append((self.getTranslation(x[0]), x[1]))
498                                 self.wizard[self.currStep]["evaluatedlist"] = self.list
499                                 self["list"].list = self.list
500                                 self["list"].index = 0
501                         else:
502                                 self["list"].hide()
503         
504                         if self.showConfig:
505                                 print "showing config"
506                                 self["config"].instance.setZPosition(1)
507                                 if self.wizard[self.currStep]["config"]["type"] == "dynamic":
508                                                 print "config type is dynamic"
509                                                 self["config"].instance.setZPosition(2)
510                                                 self["config"].l.setList(eval("self." + self.wizard[self.currStep]["config"]["source"])())
511                                 elif (self.wizard[self.currStep]["config"]["screen"] != None):
512                                         if self.wizard[self.currStep]["config"]["type"] == "standalone":
513                                                 print "Type is standalone"
514                                                 self.session.openWithCallback(self.ok, self.wizard[self.currStep]["config"]["screen"])
515                                         else:
516                                                 self["config"].instance.setZPosition(2)
517                                                 print "wizard screen", self.wizard[self.currStep]["config"]["screen"]
518                                                 if self.wizard[self.currStep]["config"]["args"] == None:
519                                                         self.configInstance = self.session.instantiateDialog(self.wizard[self.currStep]["config"]["screen"])
520                                                 else:
521                                                         self.configInstance = self.session.instantiateDialog(self.wizard[self.currStep]["config"]["screen"], eval(self.wizard[self.currStep]["config"]["args"]))
522                                                 self["config"].l.setList(self.configInstance["config"].list)
523                                                 self.configInstance["config"].destroy()
524                                                 self.configInstance["config"] = self["config"]
525                                 else:
526                                         self["config"].l.setList([])
527                         else:
528                                 if self.has_key("config"):
529                                         self["config"].hide()
530                 else: # condition false
531                                 self.currStep += 1
532                                 self.updateValues()
533                                 
534         def timeoutCounterFired(self):
535                 self.timeoutCounter -= 1
536                 print "timeoutCounter:", self.timeoutCounter
537                 if self.timeoutCounter == 0:
538                         if self.wizard[self.currStep]["timeoutaction"] == "selectnext":
539                                 print "selection next item"
540                                 self.down()
541                         else:
542                                 if self.wizard[self.currStep]["timeoutaction"] == "changestep":
543                                         self.finished(gotoStep = self.wizard[self.currStep]["timeoutstep"])
544                 self.updateText()
545
546 class WizardManager:
547         def __init__(self):
548                 self.wizards = []
549         
550         def registerWizard(self, wizard, precondition, priority = 0):
551                 self.wizards.append((wizard, precondition, priority))
552         
553         def getWizards(self):
554                 list = []
555                 for x in self.wizards:
556                         if x[1] == 1: # precondition
557                                 list.append((x[2], x[0]))
558                 return list
559
560 wizardManager = WizardManager()