5 # some helper classes first:
13 def __init__(self, order):
16 def produceHTML(self):
18 for name in self.order:
19 res += self[name].produceHTML()
27 def createGUIScreen(self, parent):
28 for (name, val) in self.items():
30 if isinstance(val, GUIComponent):
31 val.GUIcreate(self.data[name], parent, None)
33 def deleteGUIScreen(self):
34 for (name, val) in self.items():
35 if isinstance(val, GUIComponent):
36 w = self.data[name]["instance"]
37 val.GUIdelete(self.data[name])
44 # note: you'll probably run into this assert. if this happens, don't panic!
45 # yes, it's evil. I told you that programming in python is just fun, and
46 # suddently, you have to care about things you don't even know.
48 # but calm down, the solution is easy, at least on paper:
50 # Each Component, which is a GUIComponent, owns references to each
51 # instantiated eWidget (namely in screen.data[name]["instance"], in case
53 # on deleteGUIscreen, all eWidget *must* (!) be deleted (otherwise,
54 # well, problems appear. I don't want to go into details too much,
55 # but this would be a memory leak anyway.)
56 # The assert beyond checks for that. It asserts that the corresponding
57 # eWidget is about to be removed (i.e., that the refcount becomes 0 after
58 # running deleteGUIscreen).
59 # (You might wonder why the refcount is checked for 2 and not for 1 or 0 -
60 # one reference is still hold by the local variable 'w', another one is
61 # hold be the function argument to sys.getrefcount itself. So only if it's
62 # 2 at this point, the object will be destroyed after leaving deleteGUIscreen.)
64 # Now, how to fix this problem? You're holding a reference somewhere. (References
65 # can only be hold from Python, as eWidget itself isn't related to the c++
66 # way of having refcounted objects. So it must be in python.)
68 # It could be possible that you're calling deleteGUIscreen trough a call of
69 # a PSignal. For example, you could try to call screen.doClose() in response
70 # to a Button::click. This will fail. (It wouldn't work anyway, as you would
71 # remove a dialog while running it. It never worked - enigma1 just set a
72 # per-mainloop variable on eWidget::close() to leave the exec()...)
73 # That's why Session supports delayed closes. Just call Session.close() and
76 # Another reason is that you just stored the data["instance"] somewhere. or
77 # added it into a notifier list and didn't removed it.
79 # If you can't help yourself, just ask me. I'll be glad to help you out.
80 # Sorry for not keeping this code foolproof. I really wanted to archive
81 # that, but here I failed miserably. All I could do was to add this assert.
82 assert sys.getrefcount(w) == 2, "too many refs hold to " + str(w)
85 self.deleteGUIScreen()
88 # note: components can be used in multiple screens, so we have kind of
89 # two contexts: first the per-component one (self), then the per-screen (i.e.:
90 # per eWidget one), called "priv". In "priv", for example, the instance
91 # of the eWidget is stored.
94 # GUI components have a "notifier list" of associated eWidgets to one component
95 # (as said - one component instance can be used at multiple screens)
102 def GUIcreate(self, priv, parent, skindata):
103 i = self.GUIcreateInstance(self, parent, skindata)
105 self.notifier.append(i)
107 self.notifierAdded(i)
111 # GUIdelete must delete *all* references to the current component!
112 def GUIdelete(self, priv):
114 self.notifier.remove(g)
115 self.GUIdeleteInstance(g)
118 def GUIdeleteInstance(self, priv):
122 """VariableText can be used for components which have a variable text, based on any widget with setText call"""
127 def notifierAdded(self, notifier):
128 notifier.setText(self.message)
130 def setText(self, text):
131 if self.message != text:
133 for x in self.notifier:
134 x.setText(self.message)
140 """VariableValue can be used for components which have a variable value (like eSlider), based on any widget with setValue call"""
145 def notifierAdded(self, notifier):
146 notifier.setValue(self.value)
148 def setValue(self, value):
149 if self.value != value:
151 for x in self.notifier:
152 x.setValue(self.value)
157 # now some "real" components:
159 class Clock(HTMLComponent, GUIComponent, VariableText):
161 VariableText.__init__(self)
162 GUIComponent.__init__(self)
165 self.clockTimer = eTimer()
166 self.clockTimer.timeout.get().append(self.doClock)
167 self.clockTimer.start(1000)
171 self.setText("clock: " + time.asctime())
173 # realisierung als GUI
174 def GUIcreateInstance(self, priv, parent, skindata):
179 def produceHTML(self):
180 return self.getText()
182 class Button(HTMLComponent, GUIComponent, VariableText):
183 def __init__(self, text="", onClick = [ ]):
184 GUIComponent.__init__(self)
185 VariableText.__init__(self)
187 self.onClick = onClick
190 for x in self.onClick:
201 def produceHTML(self):
202 return "<input type=\"submit\" text=\"" + self.getText() + "\">\n"
205 def GUIcreateInstance(self, priv, parent, skindata):
207 g.selected.get().append(self.push)
210 def GUIdeleteInstance(self, g):
211 g.selected.get().remove(self.push)
213 class Label(HTMLComponent, GUIComponent, VariableText):
214 def __init__(self, text=""):
215 GUIComponent.__init__(self)
216 VariableText.__init__(self)
220 def produceHTML(self):
221 return self.getText()
224 def GUIcreateInstance(self, priv, parent, skindata):
228 class Header(HTMLComponent, GUIComponent, VariableText):
230 def __init__(self, message):
231 GUIComponent.__init__(self)
232 VariableText.__init__(self)
233 self.setText(message)
235 def produceHTML(self):
236 return "<h2>" + self.getText() + "</h2>\n"
238 def GUIcreateInstance(self, priv, parent, skindata):
240 g.setText(self.message)
243 class VolumeBar(HTMLComponent, GUIComponent, VariableValue):
246 GUIComponent.__init__(self)
247 VariableValue.__init__(self)
249 def GUIcreateInstance(self, priv, parent, skindata):
254 # a general purpose progress bar
255 class ProgressBar(HTMLComponent, GUIComponent, VariableValue):
257 GUIComponent.__init__(self)
258 VariableValue.__init__(self)
260 def GUIcreateInstance(self, priv, parent, skindata):
265 class MenuList(HTMLComponent, GUIComponent):
266 def __init__(self, list):
267 GUIComponent.__init__(self)
268 self.l = eListboxPythonStringContent()
271 def getCurrent(self):
272 return self.l.getCurrentSelection()
274 def GUIcreateInstance(self, priv, parent, skindata):
279 def GUIdeleteInstance(self, g):
282 class ServiceList(HTMLComponent, GUIComponent):
284 GUIComponent.__init__(self)
285 self.l = eListboxServiceContent()
287 def GUIcreateInstance(self, priv, parent, skindata):
292 def GUIdeleteInstance(self, g):
295 def setRoot(self, root):
305 def scanStatusChanged(self):
306 if self.state == self.Running:
307 self.progressbar.setValue(self.scan.getProgress())
308 if self.scan.isDone():
309 self.state = self.Done
311 self.text.setText("scan in progress - %d %% done!\n%d services found!" % (self.scan.getProgress(), self.scan.getNumServices()))
313 if self.state == self.Done:
314 self.text.setText("scan done!")
316 if self.state == self.Error:
317 self.text.setText("ERROR - failed to scan!")
319 def __init__(self, progressbar, text):
320 self.progressbar = progressbar
322 self.scan = eComponentScan()
323 if self.scan.start():
324 self.state = self.Error
326 self.state = self.Running
327 self.scan.statusChanged.get().append(self.scanStatusChanged)
328 self.scanStatusChanged()
331 return self.state == self.Done
334 self.scan.statusChanged.get().remove(self.scanStatusChanged)