initial commit of my widget system. it is quite alpha, so please dont relay on the...
[enigma2-plugins.git] / widgets / src / plugin.py
1 from Screens.Screen import Screen
2 from Screens.InfoBarGenerics import InfoBarPlugins
3 from Screens.InfoBar import InfoBar
4 from Plugins.Plugin import PluginDescriptor
5 from Components.ActionMap import ActionMap
6 from Components.config import config, ConfigSubsection, ConfigSubDict, ConfigText, ConfigBoolean
7 from Components.Element import cached
8 from enigma import eTimer
9 from Components.Label import Label
10 from Components.MenuList import MenuList
11 from enigma import  getDesktop, eSize,ePoint
12 from skin import applyAllAttributes, dom_skins
13
14                 
15 from Widget import Widget
16 from widgets import importWidgets, importSingleWidget
17                 
18
19
20
21 SIBbase__init__ = None
22 SIB_StartOnlyOneTime = False
23 SIB_TOGGLE_SHOW = InfoBar.toggleShow
24 SIB_SWOFF = InfoBar.hide
25 SIB_STATE = -1
26
27 config.plugins.Widgets = ConfigSubsection()
28 config.plugins.Widgets.show_empty_positions = ConfigBoolean(default = True,descriptions = {False: _("hide"), True: _("show")})
29 config.plugins.Widgets.active_widgets = ConfigSubDict()
30 for x in range(0,16):
31         for y in range(0,16):
32                 config.plugins.Widgets.active_widgets["w%i_%i"%(x,y)] = ConfigText("")
33
34
35 def Plugins(**kwargs):
36         return [PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, fnc = SIBautostart)]
37
38
39
40 class ReplaceInfoBar():
41         def __init__(self):
42                 pass
43         @cached
44         def Replace(self):
45                 return True
46         boolean = property(Replace)
47
48
49
50 def SIBautostart(reason, **kwargs):
51         global SIBbase__init__
52         if "session" in kwargs:
53                 if SIBbase__init__ is None:
54                         SIBbase__init__ = InfoBarPlugins.__init__
55                 InfoBarPlugins.__init__ = InfoBarPlugins__init__
56                 InfoBarPlugins.switch = switch
57                 InfoBarPlugins.swOff = swOff
58
59
60
61 def InfoBarPlugins__init__(self):
62         global SIB_StartOnlyOneTime
63         if not SIB_StartOnlyOneTime: 
64                 SIB_StartOnlyOneTime = True
65                 self["SIBActions"] = ActionMap(["WidgetStartActions"],{"ok_but": self.switch,"exit_but": self.swOff}, -1)
66                 self.SIBtimer = eTimer()
67                 self.SIBtimer.callback.append(self.swOff)
68                 self.SIBtimer.start(4000, True)
69         else:
70                 InfoBarPlugins.__init__ = InfoBarPlugins.__init__
71                 InfoBarPlugins.switch = None
72                 InfoBarPlugins.swOff = None
73         SIBbase__init__(self)
74
75
76
77 def switch(self):
78         if InfoBar and InfoBar.instance and ReplaceInfoBar.Replace:
79                 global SIB_STATE
80                 if (SIB_STATE == 0):
81                         SIB_STATE = 1
82                         idx = config.usage.infobar_timeout.index
83                         if idx:
84                                 self.SIBtimer.start(idx*1000, True)
85                         SIB_TOGGLE_SHOW(InfoBar.instance)
86                 elif (SIB_STATE == 1):
87                         SIB_STATE = 0
88                         self.SIBtimer.stop()
89                         SIB_SWOFF(InfoBar.instance)
90                         self.session.open(WidgetDesktop)
91                 else:
92                         SIB_STATE = 0
93                         self.SIBtimer.stop()
94                         SIB_SWOFF(InfoBar.instance)
95
96
97
98 def swOff(self):
99         if InfoBar and InfoBar.instance and ReplaceInfoBar.Replace:
100                 global SIB_STATE
101                 SIB_STATE = 0
102                 self.SIBtimer.stop()
103                 SIB_SWOFF(InfoBar.instance)
104 ####
105 def lookupScreenSkin(screenname):
106         for skin in dom_skins:
107                 for scr in skin[1].findall("screen"):
108                         if scr.get("name") == screenname:
109                                 return scr
110         return False
111 ####
112 def lookupWidgetConfig():
113         for skin in dom_skins:
114                 for scr in skin[1].findall("widgetconfig"):
115                         if scr.findall("num_widgets"):
116                                 return scr
117         return False
118         
119 def getWidgetForPosition(session,positionname):
120         #print "positionname value",config.plugins.Widgets.active_widgets[positionname].value
121         wpath = config.plugins.Widgets.active_widgets[positionname].value
122         if wpath == "":
123                 return False
124         else:
125                 return importSingleWidget(session,wpath)
126         
127 class WidgetDesktop(Screen):
128         
129         selection_x = 0
130         selection_y = 0
131         
132         def __init__(self, session):
133                 self.num_widgets_x = 3
134                 self.num_widgets_y = 3
135                 self.imported_widgets = []
136                 self.widgets_on_position = {}
137                 self.session = session
138                 Screen.__init__(self, session)
139                 
140                 loadSkinReal("/usr/lib/enigma2/python/Plugins/Extensions/Widgets/skin.xml")
141                 
142
143                 cfg = lookupWidgetConfig()
144                 if cfg is not False:
145                         for config in cfg.getchildren():
146                                 if config.tag == "num_widgets":
147                                         self.num_widgets_x = int(config.get("x"))
148                                         self.num_widgets_y = int(config.get("y"))
149                 print "init screen with",self.num_widgets_x,"x",self.num_widgets_y                      
150                 self.initBackgrounds()
151                 
152                 self.positions = []
153                 for x in range(1,self.num_widgets_x+1):
154                         for y in range(1,self.num_widgets_y+1):
155                                 self.positions.append("w%i_%i"%(x,y))
156                                 
157
158                 
159                 scr = lookupScreenSkin("WidgetDesktop")
160                 if scr is not False:
161                         self.original_screen = scr
162                         self.original_screen_newchilds = []
163                         for wname in self.positions:
164                                 twidget = getWidgetForPosition(session,wname)
165                                 if twidget is not False:
166                                         print "found widget for position",wname,twidget
167                                         twidget[1].setPositionname(wname)
168                                         self.importWidgetElements(twidget, wname)
169                                         self.importWidgetSkin(scr, twidget, wname)
170                                         self.imported_widgets.append(twidget)
171                                         self.widgets_on_position[wname] = twidget
172                                 else:
173                                         print "position is empty",wname
174                                         
175                 self["actions"] = ActionMap(["WidgetDesktopActions"],{
176                                                                                                                           "ok": self.close,
177                                                                                                                           "cancel": self.close,
178                                                                                                                           "up": self.key_up,
179                                                                                                                           "down": self.key_down,
180                                                                                                                           "left": self.key_left,
181                                                                                                                           "right": self.key_right,
182                                                                                                                           "menu": self.key_menu,
183                                                                                                                           "info": self.key_info,
184                                                                                                                           }, -1)
185                 self.onLayoutFinish.append(self.restoreSkin)
186                 self.onLayoutFinish.append(self._onLoadFinished)
187                 self.onClose.append(self._onClose )
188         
189         def importWidgetElements(self,widget,wname):
190                 for elementname in widget[1].elements.keys():
191                         self[wname+"_e_"+elementname] = widget[1].elements[elementname]
192
193         def importWidgetSkin(self,scr,widget,wname):
194                 x,y = self.getPositionOfBackgroundElement(scr,wname)
195                 for screenelement in widget[2].find("desktopwidget").getchildren():
196                         element = self.patchWidgetElementSkinPosition(screenelement,x,y,wname)
197                         self.original_screen_newchilds.append(element)
198                         scr.append(element)
199                 
200         def getPositionOfBackgroundElement(self,screen,elementname):
201                 for w in screen.getchildren():
202                         if w.get("name") == elementname:
203                                 xy = w.get("position").split(",")
204                                 return int(xy[0]),int(xy[1])
205                 return 0,0
206                 
207         def restoreSkin(self):
208                 for old in self.original_screen_newchilds:
209                         self.original_screen.remove(old)
210                 
211                                         
212         def initBackgrounds(self):
213                 for x in range(1,self.num_widgets_x+1):
214                         for y in range(1,self.num_widgets_y+1):
215                                 wname = "w%i_%i"%(x,y)
216                                 self[wname] = Label()
217                                 if not config.plugins.Widgets.show_empty_positions.value:
218                                         self[wname].hide()
219                                 self[wname+"_h"] = Label(_("press menu to edit"))
220                                 self[wname+"_h"].hide()
221                                 
222         def patchWidgetElementSkinPosition(self,element,x1,y1,wname):
223                 pos1= element.get("position").split(",")
224                 x2 = int(pos1[0])+x1
225                 y2 = int(pos1[1])+y1
226                 pos2 = "%i,%i"%(x2,y2)
227                 element.set("position",pos2)
228                 if element.get("name") is not None:
229                         element.set("name",wname+"_e_"+element.get("name"))
230                 return element
231
232         def _onLoadFinished(self):
233                 for w in self.imported_widgets:
234                         try:
235                                 w[1].onLoadFinished(self)
236                         except Exception,e:
237                                 print "Exception in onLoadFinished of widget",w[0],e
238                                 
239         def _onClose(self):
240                 for w in self.imported_widgets:
241                         try:
242                                 # notify the widget that it will be closed
243                                 w[1].onClose()
244                                 
245                                 #deleting the instance of the widget
246                                 #del w                          
247                         except Exception,e:
248                                 print "Exception in onClose of widget",w[0],e
249                                 
250         def key_up(self):
251                 self.selectionHide()
252                 self.selection_x -= 1
253                 if self.selection_x <= 0:
254                         self.selection_x = self.num_widgets_x
255                 self.selectionShow()            
256
257         def key_down(self):
258                 self.selectionHide()
259                 self.selection_x += 1
260                 if self.selection_x>self.num_widgets_x:
261                         self.selection_x = 1            
262                 self.selectionShow()            
263         
264         def key_left(self):
265                 self.selectionHide()
266                 self.selection_y -= 1           
267                 if self.selection_y <= 0:
268                         self.selection_y = self.num_widgets_y
269                 self.selectionShow()            
270
271         def key_right(self):
272                 self.selectionHide()
273                 self.selection_y += 1
274                 if self.selection_y>self.num_widgets_y:
275                         self.selection_y = 1            
276                 self.selectionShow()            
277         
278         def selectionShow(self):
279                 if self.selection_x==0:
280                         self.selection_x=1
281                 if self.selection_y==0:
282                         self.selection_y=1
283                 if self.selection_x in range(1,self.num_widgets_x+1) and self.selection_y in range(1,self.num_widgets_y+1):
284                         self["w%i_%i_h"%(self.selection_x,self.selection_y)].show()
285
286         def selectionHide(self):
287                 if self.selection_x in range(1,self.num_widgets_x+1) and self.selection_y in range(1,self.num_widgets_y+1):
288                         self["w%i_%i_h"%(self.selection_x,self.selection_y)].hide()
289                                 
290         def key_menu(self):
291                 if self.selection_x != 0 and self.selection_y != 0:
292                         print "menukey on position",self.selection_x,self.selection_y
293                         w = self.getWidgetOnPosition(self.selection_x,self.selection_y)
294                         if w is not False:
295                                 self.session.open(WidgetPositionConfigScreen,self.selection_x,self.selection_y,widget=w)
296                         else:
297                                 self.session.open(WidgetPositionConfigScreen,self.selection_x,self.selection_y)
298                                 
299         def key_info(self):
300                 if self.selection_x != 0 and self.selection_y != 0:
301                         w = self.getWidgetOnPosition(self.selection_x,self.selection_y)
302                         if w is not False:
303                                 print "infokey on widget",w[0]
304                                 w[1].onInfo()
305         
306         def getWidgetOnPosition(self,x,y):
307                 try:
308                         return self.widgets_on_position["w%i_%i"%(self.selection_x,self.selection_y)]
309                 except KeyError:
310                         return False
311
312 ###########
313 class WidgetPositionConfigScreen(Screen):
314         def __init__(self, session,x,y,widget=False):
315                 self.session = session
316                 self.position_x = x
317                 self.position_y = y
318                 self.widget = widget
319                 Screen.__init__(self, session)
320                 list = []
321                 
322                 if widget is not False:
323                         list.append((_("clear position"),"remove"))
324                 
325                 for widget in importWidgets(session):
326                         list.append((widget[1].name,widget))
327                 
328                 self["list"] = MenuList(list)
329                 self["preview"] = Label("")
330                 self["description"] = Label("")
331                 self["version"] = Label("")
332                 self["author"] = Label("")
333                 self["homepage"] = Label("")
334                 self["key_green"] = Label(_("ok"))
335                 self["key_red"] = Label(_("cancel"))
336                 
337                 
338                 self["actions"] = ActionMap(["WidgetPositionConfigScreenActions"],{
339                                                                                                                           "ok":      self.ok,
340                                                                                                                           "cancel":  self.close,
341                                                                                                                           "down":        self.down,
342                                                                               "up":      self.up,
343                                                                                           "left":        self.left,
344                                                                                           "right":       self.right,
345                                                                                           }, -1)
346                 
347         def ok(self):
348                 if self["list"].getCurrent() is not None:
349                         self.setValue(self["list"].getCurrent()[1][3])
350
351         def up(self):
352                 self["list"].up()
353                 self.update()
354     
355         def down(self):
356                 self["list"].down()
357                 self.update()
358         
359         def left(self):
360                 self["list"].pageUp()
361                 self.update()
362     
363         def right(self):
364                 self["list"].pageDown()
365                 self.update()
366         
367         def update(self):
368                 if self["list"].getCurrent() is not None:
369                         value = self["list"].getCurrent()[1]
370                         print "update",value
371                         if value == "remove":
372                                 self["description"].setText("remove current widget")
373                                 self["version"].setText("")
374                                 self["author"].setText("")
375                                 self["homepage"].setText("")
376                         else:
377                                 self["description"].setText(value[1].description)
378                                 self["version"].setText(value[1].version)
379                                 self["author"].setText(value[1].author)
380                                 self["homepage"].setText(value[1].homepage)
381                 
382                 
383         
384         def setValue(self,value):
385                 config.plugins.Widgets.active_widgets["w%i_%i"%(self.position_x,self.position_y)].value = value
386                 config.plugins.Widgets.active_widgets["w%i_%i"%(self.position_x,self.position_y)].save()
387                 self.close()
388         
389 ############################################################################
390 #    Copyright (C) 2008 by Volker Christian                                #
391 #    Volker.Christian@fh-hagenberg.at                                      #
392 from skin import loadSkin
393 import os
394
395
396 def loadSkinReal(skinPath):
397     if os.path.exists(skinPath):
398         print "[Widgets] Loading skin ", skinPath
399         for skin in dom_skins:
400                 print "skin",skin
401                         
402                 if skin[0] == skinPath.replace("skin.xml",""):
403                         dom_skins.remove(skin)
404         loadSkin(skinPath)
405
406
407 def loadPluginSkin(pluginPath):
408     pass #loadSkinReal(pluginPath + "/skin.xml")
409                                                                           #
410 ############################################################################
411
412
413