Merge remote-tracking branch 'origin/master' into master
[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.6"
65 # History:
66 # 0.4 First public version
67 # 0.5 Minor code optimization
68 # 0.6 Simplify translation code: Setting the os LANGUAGE variable isn't needed anymore
69 pluginPrintname = "[ShowClock Ver. %s]" %VERSION
70 debug = False # If set True, plugin will print some additional status info to track logic flow
71 ###############################################################################
72
73 config.plugins.ShowClock = ConfigSubsection()
74 config.plugins.ShowClock.name = ConfigText(default = _('Show Clock setup'), fixed_size = False, visible_width = 80)
75 config.plugins.ShowClock.description = ConfigText(default = _('Push "Exit" long to show/hide clock'), fixed_size = False, visible_width = 80)
76 config.plugins.ShowClock.menu = ConfigSelection(default = 'plugin', choices = [('plugin', _('Plugin menu')), ('extensions', _('Extensions menu'))])
77 config.plugins.ShowClock.showTimeout = ConfigNumber(default = 10)
78
79 width = getDesktop(0).size().width()
80 height = getDesktop(0).size().height()
81 config.plugins.ShowClock.position_x = ConfigNumber(default = int(width * 0.7))
82 config.plugins.ShowClock.position_y = ConfigNumber(default=45)
83 if debug: print pluginPrintname, "Clock X,Y position: %d,%d" %(config.plugins.ShowClock.position_x.value, config.plugins.ShowClock.position_y.value)
84
85 ##############################################################################
86
87 class ShowClockSetup(Screen, ConfigListScreen): # config
88
89         skin = """
90                 <screen name="ShowClock" position="center,center" size="600,290" title="Show Clock Setup" >
91                         <ePixmap pixmap="skin_default/buttons/red.png" position="5,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
92                         <ePixmap pixmap="skin_default/buttons/green.png" position="155,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
93                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
94                         <ePixmap pixmap="skin_default/buttons/blue.png" position="455,5" zPosition="0" size="140,40" transparent="1" alphatest="on" />
95                         
96                         <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" />
97                         <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" />
98                         <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" />
99                         <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" />
100
101                         <widget name="config" position="5,60" size="590,105" scrollbarMode="showOnDemand" />
102
103                         <ePixmap pixmap="skin_default/div-h.png" position="0,170" zPosition="1" size="600,2" />
104                         <widget source="help" render="Label" position="5,185" size="590,100" font="Regular;21" /> 
105                 </screen>"""
106
107         def __init__(self, session):
108
109                 Screen.__init__(self, session)
110                 self.session = session
111                 #Summary
112                 self.setup_title = _("Show Clock Setup")
113
114                 self.onChangedEntry = []
115                 
116                 self.list = [   
117                         getConfigListEntry(_('Clock show timeout'), config.plugins.ShowClock.showTimeout,
118                                 _('Specify how long (seconds) the clock shall be shown before it disappears. Set to "0" to show clock until hidden manually.')),
119                         getConfigListEntry(_('Show in'), config.plugins.ShowClock.menu,
120                                 _('Specify whether plugin shall show up in plugin menu or extensions menu (needs GUI restart)')),
121                         getConfigListEntry(_('Name'), config.plugins.ShowClock.name,
122                                 _('Specify plugin name to be used in menu (needs GUI restart).')),
123                         getConfigListEntry(_("Description"), config.plugins.ShowClock.description,
124                                 _('Specify plugin description to be used in menu (needs GUI restart).')),       
125                         ]
126                                                         
127                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
128                 
129                 def selectionChanged():
130                         if self["config"].current:
131                                 self["config"].current[1].onDeselect(self.session)
132                         self["config"].current = self["config"].getCurrent()
133                         if self["config"].current:
134                                 self["config"].current[1].onSelect(self.session)
135                         for x in self["config"].onSelectionChanged:
136                                 x()
137                                 
138                 self["config"].selectionChanged = selectionChanged
139                 self["config"].onSelectionChanged.append(self.configHelp)
140
141                 # Initialize Buttons
142                 self["key_red"] = StaticText(_("Cancel"))
143                 self["key_green"] = StaticText(_("OK"))
144                 self["key_yellow"] = StaticText(_("Help"))
145                 self["key_blue"] = StaticText(_("Move clock"))
146
147                 self["help"] = StaticText()             
148
149                 # Define Actions                
150                 self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
151                         {
152                         "red": self.keyCancel,
153                         "green": self.keySave,
154                         "yellow": self.keyHelp,
155                         "blue": self.keyMove,
156                         "cancel": self.keyCancel,
157                         "save": self.keySave,
158                         "ok": self.keySave,
159                         }, -2)
160
161                 # Trigger change
162                 self.changed()
163
164                 self.onLayoutFinish.append(self.setCustomTitle)
165
166         def setCustomTitle(self):
167                 self.setTitle(' '.join((_("Show Clock Setup"), _("Ver."), VERSION)))
168
169         def configHelp(self):
170                 self["help"].text = self["config"].getCurrent()[2]
171
172         def changed(self):
173                 for x in self.onChangedEntry:
174                         try:
175                                 x()
176                         except Exception:
177                                 pass    
178                         
179         def getCurrentEntry(self):
180                 return self["config"].getCurrent()[0]
181
182         def getCurrentValue(self):
183                 return str(self["config"].getCurrent()[1].getText())
184                 
185         def keyCancel(self):
186                 self.hideKeypad() # close help window if open
187                 ConfigListScreen.keyCancel(self)
188
189         def keySave(self):
190                 self.hideKeypad() # close help window if open
191                 ConfigListScreen.keySave(self)
192                                                 
193         def hideKeypad(self):
194                 try:
195                         self["config"].getCurrent()[1].help_window.instance.hide()
196                 except AttributeError:
197                         pass
198                                                 
199         def createSummary(self):
200                 return SetupSummary
201                 
202         def keyHelp(self):
203                 self.hideKeypad() # close help window if open
204                 self.session.open(MessageBox,
205                         _('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.'), 
206                         MessageBox.TYPE_INFO)
207                 
208         def keyMove(self):            
209                 if debug: print pluginPrintname, "Move Clock"
210                 self.hideKeypad() # close help window if open
211                 self.session.openWithCallback(
212                         self.startPositioner, MessageBox,
213                         _("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."),
214                         type=MessageBox.TYPE_INFO, timeout=10
215                 )
216                 
217         def startPositioner(self, answer):                      
218                 self.session.open(ShowClockPositioner)
219
220 ##############################################################################
221
222 class ShowClockPositioner(Screen):
223         def __init__(self, session):
224                 Screen.__init__(self, session)           
225                 self.skin = clockSkin()              
226                 self["actions"] = ActionMap(["PiPSetupActions"],
227                 {
228                         "left": self.left,
229                         "up": self.up,
230                         "right": self.right,
231                         "down": self.down,
232                         "ok": self.ok,
233                         "cancel": self.cancel                                                                                  
234                 }, -1)
235                 
236                 self.onShow.append(self.setPosition)
237
238         def setPosition(self):
239                 self.pos = (config.plugins.ShowClock.position_x.value, config.plugins.ShowClock.position_y.value)
240                 self.limit = (width - self.instance.size().width(), height - self.instance.size().height())
241                 if debug: print pluginPrintname, "Clock X,Y limit: %d,%d" %(self.limit[0], self.limit[1])       
242                 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
243         
244         def moveRelative(self, x = 0, y = 0):
245                 self.pos = (clip(self.pos[0] + x, 0, self.limit[0]), clip(self.pos[1] + y, 0, self.limit[1]))
246                 self.instance.move(ePoint(self.pos[0], self.pos[1]))
247
248         def left(self):
249                 self.moveRelative(x =- 10)
250
251         def up(self):
252                 self.moveRelative(y =- 10)
253
254         def right(self):
255                 self.moveRelative(x =+ 10)
256
257         def down(self):
258                 self.moveRelative(y =+ 10)
259
260         def ok(self):
261                 config.plugins.ShowClock.position_x.value = self.pos[0]
262                 config.plugins.ShowClock.position_x.save()
263                 config.plugins.ShowClock.position_y.value = self.pos[1]
264                 config.plugins.ShowClock.position_y.save()
265                 self.close()
266
267         def cancel(self):
268                 self.close()
269                 
270 ##############################################################################
271
272 class ShowClock(Screen):
273
274         def __init__(self, session):
275                 Screen.__init__(self, session)
276                 self.skin = clockSkin()                                 
277                 self.onShow.append(self.setPosition)
278
279         def setPosition(self):
280                 self.instance.move(ePoint( \
281                         min(config.plugins.ShowClock.position_x.value, width - self.instance.size().width()), \
282                         min(config.plugins.ShowClock.position_y.value, height - self.instance.size().height()) \
283                         )) # ensure clock visabilty even if resolution has changed     
284
285 ##############################################################################
286
287 class ShowClockMain():
288         def __init__(self):
289                 self.dialog = None
290                 self.clockShown = False
291
292         def gotSession(self, session):
293                 self.timer = eTimer() # check timer
294                 self.timer_conn = self.timer.timeout.connect(self.ShowHide)
295                 global globalActionMap
296                 readKeymap("/usr/lib/enigma2/python/Plugins/Extensions/ShowClock/keymap.xml")
297                 self.dialog = session.instantiateDialog(ShowClock)
298                 globalActionMap.actions['showClock'] = self.ShowHide
299                 
300         def ShowHide(self):
301                 if self.clockShown:
302                         if self.timer.isActive(): # stop timer if running
303                                 self.timer.stop()
304                         self.clockShown = False
305                         showClock.dialog.hide()
306                 else:
307                         self.clockShown = True
308                         if config.plugins.ShowClock.showTimeout.value > 0:
309                                 self.timer.startLongTimer(config.plugins.ShowClock.showTimeout.value)
310                         showClock.dialog.show()
311                 
312 showClock = ShowClockMain()
313
314 ##############################################################################
315
316 def clockSkin():
317         if width < 1280:
318                 if width < 1024: # SD
319                         currentSkin = """
320                                 <screen name="ShowClock" size="190,60" zPosition="10" backgroundColor="#50202020" flags="wfNoBorder">
321                                         <widget source="global.CurrentTime" render="Label" position="55,12" size="58,17" font="Regular;21" halign="left" valign="center" transparent="1">
322                                                 <convert type="ClockToText">Default</convert>
323                                         </widget>
324                                         <widget source="global.CurrentTime" render="Label" position="111,15" size="30,15" font="Regular;16" halign="left" valign="center" transparent="1">
325                                                 <convert type="ClockToText">Format::%S</convert>
326                                         </widget>
327                                         <widget source="global.CurrentTime" render="Label" position="0,37" size="190,13" font="Regular;15" halign="center" valign="center" foregroundColor="#999999" transparent="1">
328                                                 <convert type="ClockToText">Format:%A, %d.%m.%Y</convert>               
329                                         </widget>
330                                 </screen>"""
331                 else: # XD
332                         currentSkin = """
333                                 <screen name="ShowClock" size="250,70" zPosition="10" backgroundColor="#50202020" flags="wfNoBorder">
334                                         <widget source="global.CurrentTime" render="Label" position="80,10" size="80,25" font="Regular;24" halign="left" valign="center" transparent="1">
335                                                 <convert type="ClockToText">Default</convert>
336                                         </widget>
337                                         <widget source="global.CurrentTime" render="Label" position="142,15" size="40,18" font="Regular;20" halign="left" valign="center" transparent="1">
338                                                 <convert type="ClockToText">Format::%S</convert>
339                                         </widget>
340                                         <widget source="global.CurrentTime" render="Label" position="0,40" size="250,25" font="Regular;19" halign="center" valign="center" foregroundColor="#999999" transparent="1">
341                                                 <convert type="ClockToText">Format:%A, %d.%m.%Y</convert>               
342                                         </widget>
343                                 </screen>"""
344         else: # HD
345                 currentSkin = """      
346                                 <screen name="ShowClock" size="280,80" zPosition="10" backgroundColor="#50202020" flags="wfNoBorder">
347                                         <widget source="global.CurrentTime" render="Label" position="85,15" size="80,25" font="Regular;30" halign="left" valign="center" transparent="1">
348                                                 <convert type="ClockToText">Default</convert>
349                                         </widget>
350                                         <widget source="global.CurrentTime" render="Label" position="162,20" size="40,18" font="Regular;24" halign="left" valign="center" transparent="1">
351                                                 <convert type="ClockToText">Format::%S</convert>
352                                         </widget>
353                                         <widget source="global.CurrentTime" render="Label" position="0,45" size="280,30" font="Regular;23" halign="center" valign="center" foregroundColor="#999999" transparent="1">
354                                                 <convert type="ClockToText">Format:%A, %d.%m.%Y</convert>               
355                                         </widget>
356                                 </screen>"""
357                 
358         try: # try to import DateToText converter (GP3 component) to check for its existence
359                 from Components.Converter.DateToText import DateToText # change converter to obtain localized weekdays
360                 currentSkin = currentSkin.replace('<convert type="ClockToText">Format:%A, %d.%m.%Y</convert>', '<convert type="DateToText">NNNN, DD.MM.YYYY</convert>')
361         except ImportError, ie:
362                 print pluginPrintname, "DateToText converter not installed:", ie
363         return currentSkin
364         
365 ##############################################################################
366
367 def sessionstart(reason, **kwargs):
368         if reason == 0:
369                 showClock.gotSession(kwargs["session"])
370         
371 def setup(session,**kwargs):
372         try:    
373                 session.open(ShowClockSetup)
374         except:
375                 print pluginPrintname, "Pluginexecution failed"
376
377 ##############################################################################
378
379 def Plugins(**kwargs):
380         
381         if debug: print pluginPrintname, "Setting entry points"
382
383         list = [
384                 PluginDescriptor(where=[PluginDescriptor.WHERE_SESSIONSTART], fnc=sessionstart)
385                 ]
386         if config.plugins.ShowClock.menu.value == "plugin":
387                 list.append (PluginDescriptor(
388                         name = config.plugins.ShowClock.name.value + " "  + _("Ver.") + " " + VERSION, 
389                         description = config.plugins.ShowClock.description.value, 
390                         where = PluginDescriptor.WHERE_PLUGINMENU, 
391                         icon = "plugin.png", 
392                         fnc=setup)
393                 )
394         else:
395                 list.append (PluginDescriptor(
396                         name = config.plugins.ShowClock.name.value + " "  + _("Ver.") + " " + VERSION, 
397                         description = config.plugins.ShowClock.description.value, 
398                         where = PluginDescriptor.WHERE_EXTENSIONSMENU, 
399                         fnc=setup)
400                 )
401
402         return list