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