enigma2: 4.3.1r16
[enigma2.git] / usr / lib / enigma2 / python / Screens / Screen.py
1 from Tools.Profile import profile
2
3 profile("LOAD:GUISkin")
4 from Components.GUISkin import GUISkin
5 profile("LOAD:Source")
6 from Components.Sources.Source import Source
7 profile("LOAD:GUIComponent")
8 from Components.GUIComponent import GUIComponent
9 profile("LOAD:eRCInput")
10 from enigma import eRCInput
11
12 class Screen(dict, GUISkin):
13
14         False, SUSPEND_STOPS, SUSPEND_PAUSES = range(3)
15         ALLOW_SUSPEND = False
16
17         def __init__(self, session, parent = None, windowTitle=None):
18                 dict.__init__(self)
19                 self.skinName = self.__class__.__name__
20                 self.session = session
21                 self.parent = parent
22
23                 GUISkin.__init__(self, windowTitle=windowTitle)
24
25                 self.onClose = [ ]
26                 self.onFirstExecBegin = [ ]
27                 self.onLayoutFinish.append(self._initAnimations)
28                 self.onExecBegin = [ ]
29                 self.onShown = [ ]
30
31                 self.onShow = [ ]
32                 self.onHide = [ ]
33                 self.onExecEnd = [ ]
34                 self.onHideFinished = [ ]
35
36                 self.execing = False
37                 
38                 self.shown = True
39                 # already shown is false until the screen is really shown (after creation)
40                 self.already_shown = False
41
42                 self.renderer = [ ]
43
44                 # in order to support screens *without* a help,
45                 # we need the list in every screen. how ironic.
46                 self.helpList = [ ]
47
48                 self.close_on_next_exec = None
49
50                 # stand alone screens (for example web screens)
51                 # don't care about having or not having focus.
52                 self.stand_alone = False
53                 self.keyboardMode = None
54
55                 self._hideAnimFinishedConnInternal = None
56                 self._hideAnimFinishedConn = None
57
58         def saveKeyboardMode(self):
59                 self.keyboardMode = eRCInput.getInstance().getKeyboardMode()
60
61         def setKeyboardModeAscii(self):
62                 eRCInput.getInstance().setKeyboardMode(eRCInput.kmAscii)
63
64         def setKeyboardModeNone(self):
65                 eRCInput.getInstance().setKeyboardMode(eRCInput.kmNone)
66
67         def restoreKeyboardMode(self):
68                 if self.keyboardMode is not None:
69                         eRCInput.getInstance().setKeyboardMode(self.keyboardMode)
70
71         def execBegin(self):
72                 self.active_components = [ ]
73
74                 if self.close_on_next_exec is not None:
75                         tmp = self.close_on_next_exec
76                         self.close_on_next_exec = None
77                         self.execing = True
78                         self.close(*tmp)
79                 else:
80                         single = self.onFirstExecBegin
81                         self.onFirstExecBegin = []
82                         for x in self.onExecBegin + single:
83                                 x()
84                                 if not self.stand_alone and self.session.current_dialog != self:
85                                         return
86
87 #                       assert self.session == None, "a screen can only exec once per time"
88 #                       self.session = session
89
90                         for val in self.values() + self.renderer:
91                                 val.execBegin()
92                                 if not self.stand_alone and self.session.current_dialog != self:
93                                         return
94                                 self.active_components.append(val)
95
96                         self.execing = True
97         
98                         for x in self.onShown:
99                                 x()
100
101         def execEnd(self):
102                 active_components = self.active_components
103 #               for (name, val) in self.items():
104                 self.active_components = None
105                 for val in active_components:
106                         val.execEnd()
107 #               assert self.session != None, "execEnd on non-execing screen!"
108 #               self.session = None
109                 self.execing = False
110                 for x in self.onExecEnd:
111                         x()
112
113         def doClose(self, immediate=True):
114                 print "WARNING: NEVER call Screen.doClose directly!!! You have to use Session.deleteDialog(screen)\nThis function is deprecated and will be removed in the future\nPlease report!"
115                 import traceback
116                 traceback.print_stack(limit = 2)
117                 self.session.deleteDialog(self)
118
119         # never call this directly - it will be called from the session!
120         def __doClose(self, immediate=False):
121                 if not self.instance:
122                         immediate = True
123
124                 def __onHideAnimationFinishedInternal():
125                         self._free()
126                 if not immediate:
127                         self._hideAnimFinishedConnInternal = self.instance.hideAnimationFinished.connect(__onHideAnimationFinishedInternal)
128
129                 self.hide()
130                 self.doCloseInternal()
131                 if immediate:
132                         self._free()
133
134         def doCloseInternal(self):
135                 for x in self.onClose:
136                         x()
137                 # fixup circular references
138                 del self.helpList
139                 GUISkin.close(self)
140
141                 # first disconnect all render from their sources.
142                 # we might split this out into a "unskin"-call,
143                 # but currently we destroy the screen afterwards
144                 # anyway.
145                 for val in self.renderer:
146                         val.disconnectAll()  # disconnected converter/sources and probably destroy them. Sources will not be destroyed.
147
148                 # we can have multiple dict entries with different names but same Element
149                 # but we dont can call destroy multiple times
150                 for name in self.keys():
151                         val = self[name]
152                         del self[name] # remove from dict
153                         if val is not None: # is not a duplicate...
154                                 val.destroy()
155                                 for (n, v) in self.items():
156                                         if v == val: # check if it is the same Element
157                                                 self[n] = None # mark as duplicate
158
159                 self.renderer = [ ]
160                 #these are the members that have to survive the __clear__()
161                 session = self.session
162                 onHideFinished = self.onHideFinished
163                 persisted_members = (
164                                 self.instance,
165                                 self._hideAnimFinishedConn,
166                                 self._hideAnimFinishedConnInternal,
167                         )
168                 # really delete all elements now
169                 self.__dict__.clear()
170                 self.session = session
171                 self.onHideFinished = onHideFinished
172                 self.persisted_members = persisted_members
173
174         def _free(self):
175                 self.persisted_members = []
176                 if self in self.session.fading_dialogs:
177                         self.session.fading_dialogs.remove(self)
178
179         def close(self, *retval):
180                 if not self.execing:
181                         self.close_on_next_exec = retval
182                 else:
183                         self.session.close(self, *retval)
184
185         def setFocus(self, o):
186                 self.instance.setFocus(o.instance)
187
188         def show(self):
189                 if not self.instance or (self.shown and self.already_shown and self.instance.isVisible()):
190                         return
191
192                 self.shown = True
193                 self.already_shown = True
194                 self.instance.show()
195                 self.__onShow()
196
197         def __onShow(self):
198                 for x in self.onShow:
199                         x()
200                 for val in self.values() + self.renderer:
201                         if isinstance(val, GUIComponent) or isinstance(val, Source):
202                                 val.onShow()
203
204         def hide(self):
205                 if not self.instance or not (self.shown and self.instance.isVisible()):
206                         self.__onHideFinished()
207                         return
208
209                 self.shown = False
210                 self.instance.hide()
211                 if not self.instance.isFading():
212                         self.__onHideFinished()
213                 if not self.isEnabled(): #already disabled, don't call the callbacks twice
214                         return
215                 self.__onHide()
216
217         def __onHide(self):
218                 for x in self.onHide:
219                         x()
220                 for val in self.values() + self.renderer:
221                         if isinstance(val, GUIComponent) or isinstance(val, Source):
222                                 val.onHide()
223
224         def __onHideFinished(self):
225                 for fnc in self.onHideFinished:
226                         fnc()
227
228         def enable(self, do_show=True):
229                 if self.isEnabled() or not self.instance:
230                         return
231
232                 self.instance.enable()
233                 if self.instance.isVisible():
234                         self.__onShow()
235                 elif do_show:
236                         self.show()
237
238         def disable(self):
239                 if not self.isEnabled() or not self.instance:
240                         return
241                 self.instance.disable()
242                 if not self.instance.isVisible():
243                         return
244                 self.__onHide()
245
246         def isEnabled(self):
247                 return self.instance.isEnabled()
248
249         def __repr__(self):
250                 return str(type(self))
251
252         def getRelatedScreen(self, name):
253                 if name == "session":
254                         return self.session.screen
255                 elif name == "parent":
256                         return self.parent
257                 elif name == "global":
258                         return self.session.screen
259                 else:
260                         return None
261
262         def _initAnimations(self):
263                 if self.instance: #WebScreens (for example) never have an instance
264                         self._hideAnimFinishedConn = self.instance.hideAnimationFinished.connect(self.__onHideFinished)
265
266         def setShowHideAnimation(self, animation_key):
267                 if self.instance:
268                         return self.instance.setShowHideAnimation(animation_key)
269                 return False
270
271         def neverAnimate(self):
272                 if self.instance:
273                         self.instance.neverAnimate()
274                         return True
275                 return False
276
277         def canAnimate(self):
278                 """
279                 True = it can
280                 False = it can NOT
281                 None = we have no instance, we don't know (call in onFirstExecBegin to avoid this)
282                 """
283                 if self.instance:
284                         return self.instance.canAnimate()
285                 return None #We do not know that without an instance
286
287         def ignoreSource(self, name):
288                 return False
289