[ShowClock]Initial checkin
[enigma2-plugins.git] / showclock / src / plugin.py
1 # -*- coding: utf-8 -*-
2 #
3 #  Show Clock E2
4 #
5 #  $Id$
6 #
7 #  Coded by JuSt611  2011
8 #  Derived from Permanent Clock plugin written by AliAbdul
9 #  and placed in the public domain. He has my thanks.
10 #  Support: http://www.i-have-a-dreambox.com/wbb2/thread.php?threadid=???
11 #
12 #  Provided with no warranties of any sort.
13 #
14 #  This plugin is licensed under the Creative Commons 
15 #  Attribution-NonCommercial-ShareAlike 3.0 Unported 
16 #  License. To view a copy of this license, visit
17 #  http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
18 #  Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
19 #
20 #  Alternatively, this plugin may be distributed and executed on hardware which
21 #  is licensed by Dream Multimedia GmbH.
22
23 #  This plugin is NOT free software. It is open source, you are allowed to
24 #  modify it (if you keep the license), but it may not be commercially 
25 #  distributed other than under the conditions noted above.
26 #
27
28 # for localized messages
29 from . import _
30
31 from enigma import ePoint, eTimer, getDesktop
32
33 # MessageBox
34 from Screens.MessageBox import MessageBox
35 from Tools import Notifications
36
37 # ActionMap
38 from Components.ActionMap import ActionMap
39 from GlobalActions import globalActionMap
40
41 # GUI (Components)
42 from Components.Sources.StaticText import StaticText
43
44 # KeynMap
45 from keymapparser import readKeymap, removeKeymap
46
47 # Configuration
48 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigSelection, ConfigText, ConfigNumber
49 from Components.Sources.StaticText import StaticText
50
51 # Plugin definition
52 from Plugins.Plugin import PluginDescriptor
53
54 # GUI (Screens)
55 from Screens.Screen import Screen
56 from Components.ConfigList import ConfigListScreen
57 from Screens.PiPSetup import clip
58
59 # GUI (Summary)
60 from Screens.Setup import SetupSummary
61
62
63 ###############################################################################        
64 VERSION = "0.4"
65 # History:
66 # 0.4 First public version
67
68 pluginPrintname = "[ShowClock Ver. %s]" %VERSION
69 debug = False # If set True, plugin will print some additional status info to track logic flow
70 ###############################################################################
71
72 config.plugins.ShowClock = ConfigSubsection()
73 config.plugins.ShowClock.name = ConfigText(default = _('Show Clock setup'), fixed_size = False, visible_width = 80)
74 config.plugins.ShowClock.description = ConfigText(default = _('Push "Exit" long to show/hide clock'), fixed_size = False, visible_width = 80)
75 config.plugins.ShowClock.menu = ConfigSelection(default = 'plugin', choices = [('plugin', _('Plugin menu')), ('extensions', _('Extensions menu'))])
76 config.plugins.ShowClock.showTimeout = ConfigNumber(default = 10)
77
78 width = getDesktop(0).size().width()
79 height = getDesktop(0).size().height()
80 config.plugins.ShowClock.position_x = ConfigNumber(default = int(width * 0.7))
81 config.plugins.ShowClock.position_y = ConfigNumber(default=45)
82 if debug: print pluginPrintname, "Clock X,Y position: %d,%d" %(config.plugins.ShowClock.position_x.value, config.plugins.ShowClock.position_y.value)
83
84 ##############################################################################
85
86 class ShowClockSetup(Screen, ConfigListScreen): # config
87
88         skin = """
89                 <screen name="ShowClock" position="center,center" size="600,290" title="Show Clock Setup" >
90                         <ePixmap pixmap="skin_default/buttons/red.png" position="5,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
91                         <ePixmap pixmap="skin_default/buttons/green.png" position="155,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
92                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
93                         <ePixmap pixmap="skin_default/buttons/blue.png" position="455,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
94                         
95                         <widget render="Label" source="key_red" position="5,5" size="140,40" zPosition="2" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
96                         <widget render="Label" source="key_green" position="155,5" size="140,40" zPosition="2" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
97                         <widget render="Label" source="key_yellow" position="305,5" size="140,40" zPosition="2" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
98                         <widget render="Label" source="key_blue" position="455,5" size="140,40" zPosition="2" valign="center" halign="center" backgroundColor="red" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
99
100                         <widget name="config" position="5,60" size="590,105" scrollbarMode="showOnDemand" />
101
102                         <ePixmap pixmap="skin_default/div-h.png" position="0,170" zPosition="1" size="600,2" />
103                         <widget source="help" render="Label" position="5,185" size="590,100" font="Regular;21" /> 
104                 </screen>"""
105
106         def __init__(self, session):
107
108                 Screen.__init__(self, session)
109                 self.session = session
110                 #Summary
111                 self.setup_title = _("Show Clock Setup")
112
113                 self.onChangedEntry = []
114                 
115                 self.list = [   
116                         getConfigListEntry(_('Clock show timeout'), config.plugins.ShowClock.showTimeout,
117                                 _('Specify how long (seconds) the clock shall be shown before it disappears. Set to "0" to show clock until hidden manually.')),
118                         getConfigListEntry(_('Show in'), config.plugins.ShowClock.menu,
119                                 _('Specify whether plugin shall show up in plugin menu or extensions menu (needs GUI restart)')),
120                         getConfigListEntry(_('Name'), config.plugins.ShowClock.name,
121                                 _('Specify plugin name to be used in menu (needs GUI restart).')),
122                         getConfigListEntry(_("Description"), config.plugins.ShowClock.description,
123                                 _('Specify plugin description to be used in menu (needs GUI restart).')),       
124                         ]
125                                                         
126                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
127                 
128                 def selectionChanged():
129                         if self["config"].current:
130                                 self["config"].current[1].onDeselect(self.session)
131                         self["config"].current = self["config"].getCurrent()
132                         if self["config"].current:
133                                 self["config"].current[1].onSelect(self.session)
134                         for x in self["config"].onSelectionChanged:
135                                 x()
136                                 
137                 self["config"].selectionChanged = selectionChanged
138                 self["config"].onSelectionChanged.append(self.configHelp)
139
140                 # Initialize Buttons
141                 self["key_red"] = StaticText(_("Cancel"))
142                 self["key_green"] = StaticText(_("OK"))
143                 self["key_yellow"] = StaticText(_("Help"))
144                 self["key_blue"] = StaticText(_("Move clock"))
145
146                 self["help"] = StaticText()             
147
148                 # Define Actions                
149                 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
150                         {
151                         "red": self.keyCancel,
152                         "green": self.keySave,
153                         "yellow": self.keyHelp,
154                         "blue": self.keyMove,
155                         "cancel": self.keyCancel,
156                         "save": self.keySave,
157                         "ok": self.keySave,
158                         }, -2)
159
160                 # Trigger change
161                 self.changed()
162
163                 self.onLayoutFinish.append(self.setCustomTitle)
164
165         def setCustomTitle(self):
166                 self.setTitle(' '.join((_("Show Clock Setup"), _("Ver."), VERSION)))
167
168         def configHelp(self):
169                 self["help"].text = self["config"].getCurrent()[2]
170
171         def changed(self):
172                 for x in self.onChangedEntry:
173                         try:
174                                 x()
175                         except Exception:
176                                 pass    
177                         
178         def getCurrentEntry(self):
179                 return self["config"].getCurrent()[0]
180
181         def getCurrentValue(self):
182                 return str(self["config"].getCurrent()[1].getText())
183                 
184         def keyCancel(self):
185                 self.hideKeypad() # close help window if open
186                 ConfigListScreen.keyCancel(self)
187
188         def keySave(self):
189                 self.hideKeypad() # close help window if open
190                 ConfigListScreen.keySave(self)
191                                                 
192         def hideKeypad(self):
193                 try:
194                         self["config"].getCurrent()[1].help_window.instance.hide()
195                 except AttributeError:
196                         pass
197                                                 
198         def createSummary(self):
199                 return SetupSummary
200                 
201         def keyHelp(self):            
202                 self.session.open(MessageBox,
203                         _('Modify the settings to match your preferences. To change the clock position, select "Move clock" and relocate using the direction keys. Press OK to store current position and return to the setup menu or EXIT to cancel the moving.\n\nPush key "Exit long" to show the clock while watching TV. Clock will disappear after the specified timeout or by pushing key "Exit long" again.\n\nIf GP3 is installed, weekday shows up in selected language, otherwise always in english.'), 
204                         MessageBox.TYPE_INFO)
205                 
206         def keyMove(self):            
207                 if debug: print pluginPrintname, "Move Clock"
208                 self.session.openWithCallback(
209                         self.startPositioner, MessageBox,
210                         _("Please use direction keys to move the clock.\n\nPress OK to store current position and return to the setup menu or EXIT to cancel the moving."),
211                         type=MessageBox.TYPE_INFO, timeout=10
212                 )
213                 
214         def startPositioner(self, answer):                      
215                 self.session.open(ShowClockPositioner)
216
217 ##############################################################################
218
219 class ShowClockPositioner(Screen):
220         def __init__(self, session):
221                 Screen.__init__(self, session)           
222                 self.skin = clockSkin()              
223                 self["actions"] = ActionMap(["PiPSetupActions"],
224                 {
225                         "left": self.left,
226                         "up": self.up,
227                         "right": self.right,
228                         "down": self.down,
229                         "ok": self.ok,
230                         "cancel": self.cancel                                                                                  
231                 }, -1)
232                 
233                 self.onShow.append(self.setPosition)
234
235         def setPosition(self):
236                 self.pos = (config.plugins.ShowClock.position_x.value, config.plugins.ShowClock.position_y.value)
237                 self.limit = (width - self.instance.size().width(), height - self.instance.size().height())
238                 if debug: print pluginPrintname, "Clock X,Y limit: %d,%d" %(self.limit[0], self.limit[1])       
239                 self.instance.move(ePoint(min(self.pos[0], self.limit[0]), min(self.pos[1], self.limit[1]))) # ensure clock visabilty even if resolution has changed
240         
241         def moveRelative(self, x = 0, y = 0):
242                 self.pos = (clip(self.pos[0] + x, 0, self.limit[0]), clip(self.pos[1] + y, 0, self.limit[1]))
243                 self.instance.move(ePoint(self.pos[0], self.pos[1]))
244
245         def left(self):
246                 self.moveRelative(x =- 10)
247
248         def up(self):
249                 self.moveRelative(y =- 10)
250
251         def right(self):
252                 self.moveRelative(x =+ 10)
253
254         def down(self):
255                 self.moveRelative(y =+ 10)
256
257         def ok(self):
258                 config.plugins.ShowClock.position_x.value = self.pos[0]
259                 config.plugins.ShowClock.position_x.save()
260                 config.plugins.ShowClock.position_y.value = self.pos[1]
261                 config.plugins.ShowClock.position_y.save()
262                 self.close()
263
264         def cancel(self):
265                 self.close()
266                 
267 ##############################################################################
268
269 class ShowClock(Screen):
270
271         def __init__(self, session):
272                 Screen.__init__(self, session)
273                 self.skin = clockSkin()                                 
274                 self.onShow.append(self.setPosition)
275
276         def setPosition(self):
277                 self.instance.move(ePoint( \
278                         min(config.plugins.ShowClock.position_x.value, width - self.instance.size().width()), \
279                         min(config.plugins.ShowClock.position_y.value, height - self.instance.size().height()) \
280                         )) # ensure clock visabilty even if resolution has changed     
281
282 ##############################################################################
283
284 class ShowClockMain():
285         def __init__(self):
286                 self.dialog = None
287                 self.clockShown = False
288
289         def gotSession(self, session):
290                 self.timer = eTimer() # check timer
291                 self.timer.callback.append(self.ShowHide)
292                 global globalActionMap
293                 readKeymap("/usr/lib/enigma2/python/Plugins/Extensions/ShowClock/keymap.xml")
294                 self.dialog = session.instantiateDialog(ShowClock)
295                 globalActionMap.actions['showClock'] = self.ShowHide
296                 
297         def ShowHide(self):
298                 if self.clockShown:
299                         if self.timer.isActive(): # stop timer if running
300                                 self.timer.stop()
301                         self.clockShown = False
302                         showClock.dialog.hide()
303                 else:
304                         self.clockShown = True
305                         if config.plugins.ShowClock.showTimeout.value > 0:
306                                 self.timer.startLongTimer(config.plugins.ShowClock.showTimeout.value)
307                         showClock.dialog.show()
308                 
309 showClock = ShowClockMain()
310
311 ##############################################################################
312
313 def clockSkin():
314
315         clockSkinSD = """
316                 <screen name="ShowClock" size="190,60" zPosition="10" backgroundColor="#50202020" flags="wfNoBorder">
317                         <widget source="global.CurrentTime" render="Label" position="55,12" size="58,17" font="Regular;21" halign="left" valign="center" transparent="1">
318                                 <convert type="ClockToText">Default</convert>
319                         </widget>
320                         <widget source="global.CurrentTime" render="Label" position="111,15" size="30,15" font="Regular;16" halign="left" valign="center" transparent="1">
321                                 <convert type="ClockToText">Format::%S</convert>
322                         </widget>
323                         <widget source="global.CurrentTime" render="Label" position="0,37" size="190,13" font="Regular;15" halign="center" valign="center" foregroundColor="#999999" transparent="1">
324                                 <convert type="ClockToText">Format:%A, %d.%m.%Y</convert>               
325                         </widget>
326                 </screen>"""
327                 
328         clockSkinXD = """
329                 <screen name="ShowClock" size="250,70" zPosition="10" backgroundColor="#50202020" flags="wfNoBorder">
330                         <widget source="global.CurrentTime" render="Label" position="80,10" size="80,25" font="Regular;24" halign="left" valign="center" transparent="1">
331                                 <convert type="ClockToText">Default</convert>
332                         </widget>
333                         <widget source="global.CurrentTime" render="Label" position="142,15" size="40,18" font="Regular;20" halign="left" valign="center" transparent="1">
334                                 <convert type="ClockToText">Format::%S</convert>
335                         </widget>
336                         <widget source="global.CurrentTime" render="Label" position="0,40" size="250,25" font="Regular;19" halign="center" valign="center" foregroundColor="#999999" transparent="1">
337                                 <convert type="ClockToText">Format:%A, %d.%m.%Y</convert>               
338                         </widget>
339                 </screen>"""
340
341         clockSkinHD = """      
342                 <screen name="ShowClock" size="280,80" zPosition="10" backgroundColor="#50202020" flags="wfNoBorder">
343                         <widget source="global.CurrentTime" render="Label" position="85,15" size="80,25" font="Regular;30" halign="left" valign="center" transparent="1">
344                                 <convert type="ClockToText">Default</convert>
345                         </widget>
346                         <widget source="global.CurrentTime" render="Label" position="162,20" size="40,18" font="Regular;24" halign="left" valign="center" transparent="1">
347                                 <convert type="ClockToText">Format::%S</convert>
348                         </widget>
349                         <widget source="global.CurrentTime" render="Label" position="0,45" size="280,30" font="Regular;23" halign="center" valign="center" foregroundColor="#999999" transparent="1">
350                                 <convert type="ClockToText">Format:%A, %d.%m.%Y</convert>               
351                         </widget>
352                 </screen>"""
353  
354         if width < 1280:
355                 if width < 1024:
356                         currentSkin = clockSkinSD
357                 else:
358                         currentSkin = clockSkinXD
359         else:           
360                 currentSkin = clockSkinHD
361                 
362         try: # try to import DateToText converter (GP3 component) to check for its existence
363                 from Components.Converter.DateToText import DateToText # change converter to obtain localized weekdays
364                 currentSkin = currentSkin.replace('<convert type="ClockToText">Format:%A, %d.%m.%Y</convert>', '<convert type="DateToText">NNNN, DD.MM.YYYY</convert>')
365         except ImportError, ie:
366                 print pluginPrintname, "DateToText converter not installed:", ie
367         return currentSkin
368         
369 ##############################################################################
370
371 def sessionstart(reason, **kwargs):
372         if reason == 0:
373                 showClock.gotSession(kwargs["session"])
374         
375 def setup(session,**kwargs):
376         try:    
377                 session.open(ShowClockSetup)
378         except:
379                 print pluginPrintname, "Pluginexecution failed"
380
381 ##############################################################################
382
383 def Plugins(**kwargs):
384         
385         if debug: print pluginPrintname, "Setting entry points"
386
387         list = [
388                 PluginDescriptor(where=[PluginDescriptor.WHERE_SESSIONSTART], fnc=sessionstart)
389                 ]
390         if config.plugins.ShowClock.menu.value == "plugin":
391                 list.append (PluginDescriptor(
392                         name = config.plugins.ShowClock.name.value + " "  + _("Ver.") + " " + VERSION, 
393                         description = config.plugins.ShowClock.description.value, 
394                         where = PluginDescriptor.WHERE_PLUGINMENU, 
395                         icon = "plugin.png", 
396                         fnc=setup)
397                 )
398         else:
399                 list.append (PluginDescriptor(
400                         name = config.plugins.ShowClock.name.value + " "  + _("Ver.") + " " + VERSION, 
401                         description = config.plugins.ShowClock.description.value, 
402                         where = PluginDescriptor.WHERE_EXTENSIONSMENU, 
403                         fnc=setup)
404                 )
405
406         return list