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