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