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