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