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