add getTranslation method to wizard baseclass to allow overwriting this method for...
[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
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, HelpableScreen):
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                                         exec "from Screens." + str(attrs.get('module')) + " import *"
109                                 
110                                         self.wizard[self.lastStep]["config"]["screen"] = eval(str(attrs.get('screen')))
111                                         if (attrs.has_key('args')):
112                                                 #print "has args"
113                                                 self.wizard[self.lastStep]["config"]["args"] = str(attrs.get('args'))
114                                 elif type == "dynamic":
115                                         self.wizard[self.lastStep]["config"]["source"] = str(attrs.get('source'))
116                                         if (attrs.has_key('evaluation')):
117                                                 self.wizard[self.lastStep]["config"]["evaluation"] = str(attrs.get('evaluation'))
118                         elif (name == "code"):
119                                 if attrs.has_key('pos') and str(attrs.get('pos')) == "after":
120                                         self.codeafter = True
121                                 else:
122                                         self.codeafter = False
123                         elif (name == "condition"):
124                                 pass
125                         
126                 def endElement(self, name):
127                         self.currContent = ""
128                         if name == 'code':
129                                 if self.codeafter:
130                                         self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"].strip()
131                                 else:
132                                         self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"].strip()
133                         elif name == 'condition':
134                                 self.wizard[self.lastStep]["condition"] = self.wizard[self.lastStep]["condition"].strip()
135                         elif name == 'step':
136                                 #print "Step number", self.lastStep, ":", self.wizard[self.lastStep]
137                                 pass
138                                                                 
139                 def characters(self, ch):
140                         if self.currContent == "code":
141                                 if self.codeafter:
142                                         self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"] + ch
143                                 else:
144                                         self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"] + ch
145                         elif self.currContent == "condition":
146                                  self.wizard[self.lastStep]["condition"] = self.wizard[self.lastStep]["condition"] + ch
147
148         def __init__(self, session, showSteps = True, showStepSlider = True, showList = True, showConfig = True):
149                 Screen.__init__(self, session)
150                 HelpableScreen.__init__(self)
151
152                 self.stepHistory = []
153
154                 self.wizard = {}
155                 parser = make_parser()
156                 if not isinstance(self.xmlfile, list):
157                         self.xmlfile = [self.xmlfile]
158                 print "Reading ", self.xmlfile
159                 wizardHandler = self.parseWizard(self.wizard)
160                 parser.setContentHandler(wizardHandler)
161                 for xmlfile in self.xmlfile:
162                         if xmlfile[0] != '/':
163                                 parser.parse('/usr/share/enigma2/' + xmlfile)
164                         else:
165                                 parser.parse(xmlfile)
166
167                 self.showSteps = showSteps
168                 self.showStepSlider = showStepSlider
169                 self.showList = showList
170                 self.showConfig = showConfig
171
172                 self.numSteps = len(self.wizard)
173                 self.currStep = self.getStepWithID("start") + 1
174                 
175                 self.timeoutTimer = eTimer()
176                 self.timeoutTimer.callback.append(self.timeoutCounterFired)
177
178                 self["text"] = Label()
179
180                 if showConfig:
181                         self["config"] = ConfigList([])
182
183                 if self.showSteps:
184                         self["step"] = Label()
185                 
186                 if self.showStepSlider:
187                         self["stepslider"] = Slider(1, self.numSteps)
188                 
189                 if self.showList:
190                         self.list = []
191                         self["list"] = List(self.list, enableWrapAround = True)
192                         self["list"].onSelectionChanged.append(self.selChanged)
193                         #self["list"] = MenuList(self.list, enableWrapAround = True)
194
195                 self.onShown.append(self.updateValues)
196
197                 self.configInstance = None
198                 
199                 self.lcdCallbacks = []
200                 
201                 self.disableKeys = False
202                 
203                 self["actions"] = NumberActionMap(["WizardActions", "NumberActions", "ColorActions"],
204                 {
205                         "ok": self.ok,
206                         "back": self.back,
207                         "left": self.left,
208                         "right": self.right,
209                         "up": self.up,
210                         "down": self.down,
211                         "red": self.red,
212                         "green": self.green,
213                         "yellow": self.yellow,
214                         "blue":self.blue,
215                         "1": self.keyNumberGlobal,
216                         "2": self.keyNumberGlobal,
217                         "3": self.keyNumberGlobal,
218                         "4": self.keyNumberGlobal,
219                         "5": self.keyNumberGlobal,
220                         "6": self.keyNumberGlobal,
221                         "7": self.keyNumberGlobal,
222                         "8": self.keyNumberGlobal,
223                         "9": self.keyNumberGlobal,
224                         "0": self.keyNumberGlobal
225                 }, -1)
226                 
227         def red(self):
228                 print "red"
229                 pass
230
231         def green(self):
232                 print "green"
233                 pass
234         
235         def yellow(self):
236                 print "yellow"
237                 pass
238         
239         def blue(self):
240                 print "blue"
241                 pass
242         
243         def setLCDTextCallback(self, callback):
244                 self.lcdCallbacks.append(callback)
245
246         def back(self):
247                 if self.disableKeys:
248                         return
249                 print "getting back..."
250                 print "stepHistory:", self.stepHistory
251                 if len(self.stepHistory) > 1:
252                         self.currStep = self.stepHistory[-2]
253                         self.stepHistory = self.stepHistory[:-2]
254                 if self.currStep < 1:
255                         self.currStep = 1
256                 print "currStep:", self.currStep
257                 print "new stepHistory:", self.stepHistory
258                 self.updateValues()
259                 print "after updateValues stepHistory:", self.stepHistory
260                 
261         def markDone(self):
262                 pass
263         
264         def getStepWithID(self, id):
265                 print "getStepWithID:", id
266                 count = 0
267                 for x in self.wizard.keys():
268                         if self.wizard[x]["id"] == id:
269                                 print "result:", count
270                                 return count
271                         count += 1
272                 print "result: nothing"
273                 return 0
274
275         def finished(self, gotoStep = None, *args, **kwargs):
276                 print "finished"
277                 currStep = self.currStep
278
279                 if self.updateValues not in self.onShown:
280                         self.onShown.append(self.updateValues)
281                         
282                 if self.showConfig:
283                         if self.wizard[currStep]["config"]["type"] == "dynamic":
284                                 eval("self." + self.wizard[currStep]["config"]["evaluation"])()
285                         
286                 if self.showList:
287                         if (len(self.wizard[currStep]["evaluatedlist"]) > 0):
288                                 print "current:", self["list"].current
289                                 nextStep = self["list"].current[1]
290                                 if (self.wizard[currStep].has_key("listevaluation")):
291                                         exec("self." + self.wizard[self.currStep]["listevaluation"] + "('" + nextStep + "')")
292                                 else:
293                                         self.currStep = self.getStepWithID(nextStep)
294
295                 if ((currStep == self.numSteps and self.wizard[currStep]["nextstep"] is None) or self.wizard[currStep]["id"] == "end"): # wizard finished
296                         print "wizard finished"
297                         self.markDone()
298                         self.close()
299                 else:
300                         self.runCode(self.wizard[currStep]["codeafter"])
301                         if self.wizard[currStep]["nextstep"] is not None:
302                                 self.currStep = self.getStepWithID(self.wizard[currStep]["nextstep"])
303                         if gotoStep is not None:
304                                 self.currStep = self.getStepWithID(gotoStep)
305                         self.currStep += 1
306                         self.updateValues()
307
308                 print "Now: " + str(self.currStep)
309
310
311         def ok(self):
312                 print "OK"
313                 if self.disableKeys:
314                         return
315                 currStep = self.currStep
316                 
317                 if self.showConfig:
318                         if (self.wizard[currStep]["config"]["screen"] != None):
319                                 # TODO: don't die, if no run() is available
320                                 # there was a try/except here, but i can't see a reason
321                                 # for this. If there is one, please do a more specific check
322                                 # and/or a comment in which situation there is no run()
323                                 if callable(getattr(self.configInstance, "runAsync", None)):
324                                         self.onShown.remove(self.updateValues)
325                                         self.configInstance.runAsync(self.finished)
326                                         return
327                                 else:
328                                         self.configInstance.run()
329                 self.finished()
330
331         def keyNumberGlobal(self, number):
332                 if (self.wizard[self.currStep]["config"]["screen"] != None):
333                         self.configInstance.keyNumberGlobal(number)
334                 
335         def left(self):
336                 self.resetCounter()
337                 if (self.wizard[self.currStep]["config"]["screen"] != None):
338                         self.configInstance.keyLeft()
339                 elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
340                         self["config"].handleKey(KEY_LEFT)
341                 print "left"
342         
343         def right(self):
344                 self.resetCounter()
345                 if (self.wizard[self.currStep]["config"]["screen"] != None):
346                         self.configInstance.keyRight()
347                 elif (self.wizard[self.currStep]["config"]["type"] == "dynamic"):
348                         self["config"].handleKey(KEY_RIGHT)     
349                 print "right"
350
351         def up(self):
352                 self.resetCounter()
353                 if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None  or self.wizard[self.currStep]["config"]["type"] == "dynamic"):
354                                 self["config"].instance.moveSelection(self["config"].instance.moveUp)
355                 elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0):
356                         self["list"].selectPrevious()
357                         if self.wizard[self.currStep].has_key("onselect"):
358                                 print "current:", self["list"].current
359                                 self.selection = self["list"].current[-1]
360                                 #self.selection = self.wizard[self.currStep]["evaluatedlist"][self["list"].l.getCurrentSelectionIndex()][1]
361                                 exec("self." + self.wizard[self.currStep]["onselect"] + "()")
362                 print "up"
363                 
364         def down(self):
365                 self.resetCounter()
366                 if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None  or self.wizard[self.currStep]["config"]["type"] == "dynamic"):
367                         self["config"].instance.moveSelection(self["config"].instance.moveDown)
368                 elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0):
369                         #self["list"].instance.moveSelection(self["list"].instance.moveDown)
370                         self["list"].selectNext()
371                         if self.wizard[self.currStep].has_key("onselect"):
372                                 print "current:", self["list"].current
373                                 #self.selection = self.wizard[self.currStep]["evaluatedlist"][self["list"].l.getCurrentSelectionIndex()][1]
374                                 #exec("self." + self.wizard[self.currStep]["onselect"] + "()")
375                                 self.selection = self["list"].current[-1]
376                                 #self.selection = self.wizard[self.currStep]["evaluatedlist"][self["list"].l.getCurrentSelectionIndex()][1]
377                                 exec("self." + self.wizard[self.currStep]["onselect"] + "()")
378                 print "down"
379                 
380         def selChanged(self):
381                 self.resetCounter()
382                 
383                 if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None):
384                                 self["config"].instance.moveSelection(self["config"].instance.moveUp)
385                 elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0):
386                         if self.wizard[self.currStep].has_key("onselect"):
387                                 self.selection = self["list"].current[-1]
388                                 print "self.selection:", self.selection
389                                 exec("self." + self.wizard[self.currStep]["onselect"] + "()")
390                 
391         def resetCounter(self):
392                 self.timeoutCounter = self.wizard[self.currStep]["timeout"]
393                 
394         def runCode(self, code):
395                 if code != "":
396                         print "code", code
397                         exec(code)
398                         
399         def getTranslation(self, text):
400                 return _(text)
401                         
402         def updateText(self, firstset = False):
403                 text = self.getTranslation(self.wizard[self.currStep]["text"])
404                 if text.find("[timeout]") != -1:
405                         text = text.replace("[timeout]", str(self.timeoutCounter))
406                         self["text"].setText(text)
407                 else:
408                         if firstset:
409                                 self["text"].setText(text)
410                 
411         def updateValues(self):
412                 print "Updating values in step " + str(self.currStep)
413                 # calling a step which doesn't exist can only happen if the condition in the last step is not fulfilled
414                 # if a non-existing step is called, end the wizard 
415                 if self.currStep > len(self.wizard):
416                         self.markDone()
417                         self.close()
418                         return
419
420                 self.timeoutTimer.stop()
421                 
422                 if self.configInstance is not None:
423                         del self.configInstance["config"]
424                         self.configInstance.doClose()
425                         self.configInstance = None
426                 
427                 self.condition = True
428                 exec (self.wizard[self.currStep]["condition"])
429                 if self.condition:
430                         if len(self.stepHistory) == 0 or self.stepHistory[-1] != self.currStep:
431                                 self.stepHistory.append(self.currStep)
432                         print "wizard step:", self.wizard[self.currStep]
433                         
434                         if self.showSteps:
435                                 self["step"].setText(self.getTranslation("Step ") + str(self.currStep) + "/" + str(self.numSteps))
436                         if self.showStepSlider:
437                                 self["stepslider"].setValue(self.currStep)
438                 
439                         if self.wizard[self.currStep]["timeout"] is not None:
440                                 self.resetCounter() 
441                                 self.timeoutTimer.start(1000)
442                         
443                         print "wizard text", self.getTranslation(self.wizard[self.currStep]["text"])
444                         self.updateText(firstset = True)
445                         if self.wizard[self.currStep].has_key("displaytext"):
446                                 displaytext = self.wizard[self.currStep]["displaytext"]
447                                 print "set LCD text"
448                                 for x in self.lcdCallbacks:
449                                         x(displaytext)
450                                 
451                         self.runCode(self.wizard[self.currStep]["code"])
452                         
453                         if self.showList:
454                                 print "showing list,", self.currStep
455                                 for renderer in self.renderer:
456                                         rootrenderer = renderer
457                                         while renderer.source is not None:
458                                                 print "self.list:", self["list"]
459                                                 if renderer.source is self["list"]:
460                                                         print "setZPosition"
461                                                         rootrenderer.instance.setZPosition(1)
462                                                 renderer = renderer.source
463                                                 
464                                 #self["list"].instance.setZPosition(1)
465                                 self.list = []
466                                 if (self.wizard[self.currStep].has_key("dynamiclist")):
467                                         print "dynamic list, calling",  self.wizard[self.currStep]["dynamiclist"]
468                                         newlist = eval("self." + self.wizard[self.currStep]["dynamiclist"] + "()")
469                                         #self.wizard[self.currStep]["evaluatedlist"] = []
470                                         for entry in newlist:
471                                                 #self.wizard[self.currStep]["evaluatedlist"].append(entry)
472                                                 self.list.append(entry)
473                                         #del self.wizard[self.currStep]["dynamiclist"]
474                                 if (len(self.wizard[self.currStep]["list"]) > 0):
475                                         #self["list"].instance.setZPosition(2)
476                                         for x in self.wizard[self.currStep]["list"]:
477                                                 self.list.append((self.getTranslation(x[0]), x[1]))
478                                 self.wizard[self.currStep]["evaluatedlist"] = self.list
479                                 self["list"].list = self.list
480                                 self["list"].index = 0
481                         else:
482                                 self["list"].hide()
483         
484                         if self.showConfig:
485                                 print "showing config"
486                                 self["config"].instance.setZPosition(1)
487                                 if self.wizard[self.currStep]["config"]["type"] == "dynamic":
488                                                 print "config type is dynamic"
489                                                 self["config"].instance.setZPosition(2)
490                                                 self["config"].l.setList(eval("self." + self.wizard[self.currStep]["config"]["source"])())
491                                 elif (self.wizard[self.currStep]["config"]["screen"] != None):
492                                         if self.wizard[self.currStep]["config"]["type"] == "standalone":
493                                                 print "Type is standalone"
494                                                 self.session.openWithCallback(self.ok, self.wizard[self.currStep]["config"]["screen"])
495                                         else:
496                                                 self["config"].instance.setZPosition(2)
497                                                 print "wizard screen", self.wizard[self.currStep]["config"]["screen"]
498                                                 if self.wizard[self.currStep]["config"]["args"] == None:
499                                                         self.configInstance = self.session.instantiateDialog(self.wizard[self.currStep]["config"]["screen"])
500                                                 else:
501                                                         self.configInstance = self.session.instantiateDialog(self.wizard[self.currStep]["config"]["screen"], eval(self.wizard[self.currStep]["config"]["args"]))
502                                                 self["config"].l.setList(self.configInstance["config"].list)
503                                                 self.configInstance["config"].destroy()
504                                                 self.configInstance["config"] = self["config"]
505                                 else:
506                                         self["config"].l.setList([])
507                         else:
508                                 if self.has_key("config"):
509                                         self["config"].hide()
510                 else: # condition false
511                                 self.currStep += 1
512                                 self.updateValues()
513                                 
514         def timeoutCounterFired(self):
515                 self.timeoutCounter -= 1
516                 print "timeoutCounter:", self.timeoutCounter
517                 if self.timeoutCounter == 0:
518                         if self.wizard[self.currStep]["timeoutaction"] == "selectnext":
519                                 print "selection next item"
520                                 self.down()
521                         else:
522                                 if self.wizard[self.currStep]["timeoutaction"] == "changestep":
523                                         self.finished(gotoStep = self.wizard[self.currStep]["timeoutstep"])
524                 self.updateText()
525
526 class WizardManager:
527         def __init__(self):
528                 self.wizards = []
529         
530         def registerWizard(self, wizard, precondition, priority = 0):
531                 self.wizards.append((wizard, precondition, priority))
532         
533         def getWizards(self):
534                 list = []
535                 for x in self.wizards:
536                         if x[1] == 1: # precondition
537                                 list.append((x[2], x[0]))
538                 return list
539
540 wizardManager = WizardManager()