zaphistorybrowser: add switch for "classic" enigma1-like history
[enigma2-plugins.git] / zaphistorybrowser / src / plugin.py
1 # -*- coding: UTF-8 -*-
2 ## Zap-History Browser by AliAbdul
3 from Components.ActionMap import ActionMap
4 from Components.config import config, ConfigInteger, ConfigSelection, \
5                 ConfigYesNo, ConfigSet, ConfigSubsection, getConfigListEntry
6 from Components.ConfigList import ConfigListScreen
7 from Components.Label import Label
8 from Components.Language import language
9 from Components.MenuList import MenuList
10 from Components.MultiContent import MultiContentEntryText
11 from enigma import eListboxPythonMultiContent, eServiceCenter, \
12                 eServiceReference, gFont
13 from os import environ
14 from Plugins.Plugin import PluginDescriptor
15 from Screens.ChannelSelection import ChannelSelection
16 from Screens.ParentalControlSetup import ProtectedScreen
17 from Screens.Screen import Screen
18 from Tools.Directories import resolveFilename, SCOPE_LANGUAGE, SCOPE_PLUGINS
19 from enigma import eServiceReference
20 import gettext
21
22 ################################################
23
24 def localeInit():
25         lang = language.getLanguage()
26         environ["LANGUAGE"] = lang[:2]
27         gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
28         gettext.textdomain("enigma2")
29         gettext.bindtextdomain("ZapHistoryBrowser", "%s%s" % (resolveFilename(SCOPE_PLUGINS), "Extensions/ZapHistoryBrowser/locale/"))
30
31 def _(txt):
32         t = gettext.dgettext("ZapHistoryBrowser", txt)
33         if t == txt:
34                 t = gettext.gettext(txt)
35         return t
36
37 localeInit()
38 language.addCallback(localeInit)
39
40 ################################################
41
42 config.plugins.ZapHistoryConfigurator = ConfigSubsection()
43 config.plugins.ZapHistoryConfigurator.enable_zap_history = ConfigSelection(choices = {"off": _("disabled"), "on": _("enabled"), "parental_lock": _("disabled at parental lock")}, default="on")
44 config.plugins.ZapHistoryConfigurator.maxEntries_zap_history = ConfigInteger(default=20, limits=(1, 60))
45 config.plugins.ZapHistoryConfigurator.e1_like_history = ConfigYesNo(default = False)
46 config.plugins.ZapHistoryConfigurator.history_tv = ConfigSet(choices = [])
47 config.plugins.ZapHistoryConfigurator.history_radio = ConfigSet(choices = [])
48
49 ################################################
50
51 def addToHistory(instance, ref):
52         if config.plugins.ZapHistoryConfigurator.enable_zap_history.value == "off":
53                 return
54         if config.ParentalControl.configured.value and config.plugins.ZapHistoryConfigurator.enable_zap_history.value == "parental_lock":
55                 if parentalControl.getProtectionLevel(ref.toCompareString()) != -1:
56                         return
57         if instance.servicePath is not None:
58                 tmp = instance.servicePath[:]
59                 tmp.append(ref)
60                 try: del instance.history[instance.history_pos+1:]
61                 except Exception, e: pass
62                 if config.plugins.ZapHistoryConfigurator.e1_like_history.value and tmp in instance.history:
63                         instance.history.remove(tmp)
64                 instance.history.append(tmp)
65                 hlen = len(instance.history)
66                 if hlen > config.plugins.ZapHistoryConfigurator.maxEntries_zap_history.value:
67                         del instance.history[0]
68                         hlen -= 1
69                 instance.history_pos = hlen-1
70                 if config.plugins.ZapHistoryConfigurator.e1_like_history.value:
71                         # TODO: optimize this
72                         if instance.history == instance.history_tv:
73                                 config.plugins.ZapHistoryConfigurator.history_tv.value = [[y.toString() for y in x] for x in instance.history]
74                         else:
75                                 config.plugins.ZapHistoryConfigurator.history_radio.value = [[y.toString() for y in x] for x in instance.history]
76                         config.plugins.ZapHistoryConfigurator.save()
77
78 ChannelSelection.addToHistory = addToHistory
79
80 def newInit(self, session):
81         baseInit(self, session)
82         if config.plugins.ZapHistoryConfigurator.e1_like_history.value:
83                 append = self.history_tv.append
84                 for x in config.plugins.ZapHistoryConfigurator.history_tv.value:
85                         append([eServiceReference(y) for y in x])
86                 append = self.history_radio.append
87                 for x in config.plugins.ZapHistoryConfigurator.history_radio.value:
88                         append([eServiceReference(y) for y in x])
89
90                 # XXX: self.lastChannelRootTimer was always finished for me, so just fix its mistakes ;)
91                 if self.history == self.history_tv:
92                         self.history_pos = len(self.history_tv)-1
93                 else:
94                         self.history_pos = len(self.history_radio)-1
95
96 baseInit = ChannelSelection.__init__
97 ChannelSelection.__init__ = newInit
98
99 ################################################
100
101 class ZapHistoryConfigurator(ConfigListScreen, Screen):
102         skin = """
103                 <screen position="center,center" size="420,80" title="%s" >
104                         <widget name="config" position="0,0" size="420,80" scrollbarMode="showOnDemand" />
105                 </screen>""" % _("Zap-History Configurator")
106
107         def __init__(self, session):
108                 Screen.__init__(self, session)
109                 self.session = session
110                 
111                 ConfigListScreen.__init__(self, [
112                         getConfigListEntry(_("Enable zap history:"), config.plugins.ZapHistoryConfigurator.enable_zap_history),
113                         getConfigListEntry(_("Maximum zap history entries:"), config.plugins.ZapHistoryConfigurator.maxEntries_zap_history),
114                         getConfigListEntry(_("Enigma1-like history:"), config.plugins.ZapHistoryConfigurator.e1_like_history)])
115                 
116                 self["actions"] = ActionMap(["OkCancelActions"], {"ok": self.save, "cancel": self.exit}, -2)
117
118         def save(self):
119                 # alternative to notifier
120                 if config.plugins.ZapHistoryConfigurator.e1_like_history.value and config.plugins.ZapHistoryConfigurator.e1_like_history.isChanged():
121                         from Screens.InfoBar import InfoBar
122                         try:
123                                 csel = InfoBar.instance.servicelist
124                         except AttributeError, e:
125                                 pass
126                         else:
127                                 config.plugins.ZapHistoryConfigurator.history_tv.value = [[y.toString() for y in x] for x in csel.history_tv]
128                                 config.plugins.ZapHistoryConfigurator.history_radio.value = [[y.toString() for y in x] for x in csel.history_radio]
129                                 config.plugins.ZapHistoryConfigurator.history_tv.save()
130                                 config.plugins.ZapHistoryConfigurator.history_radio.save()
131
132                 for x in self["config"].list:
133                         x[1].save()
134                 self.close()
135
136         def exit(self):
137                 for x in self["config"].list:
138                         x[1].cancel()
139                 self.close()
140
141 ################################################
142
143 class ZapHistoryBrowserList(MenuList):
144         def __init__(self, list, enableWrapAround=False):
145                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
146                 self.l.setItemHeight(40)
147                 self.l.setFont(0, gFont("Regular", 20))
148                 self.l.setFont(1, gFont("Regular", 18))
149
150 def ZapHistoryBrowserListEntry(serviceName, eventName):
151         res = [serviceName]
152         res.append(MultiContentEntryText(pos=(0, 0), size=(560, 22), font=0, text=serviceName))
153         res.append(MultiContentEntryText(pos=(0, 22), size=(560, 18), font=1, text=eventName))
154         return res
155
156 ################################################
157
158 class ZapHistoryBrowser(Screen, ProtectedScreen):
159         skin = """
160         <screen position="center,center" size="560,440" title="%s" >
161                 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
162                 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
163                 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
164                 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
165                 <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
166                 <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
167                 <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
168                 <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
169                 <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
170         </screen>""" % _("Zap-History Browser")
171
172         def __init__(self, session, servicelist):
173                 Screen.__init__(self, session)
174                 ProtectedScreen.__init__(self)
175                 self.session = session
176                 
177                 self.servicelist = servicelist
178                 self.serviceHandler = eServiceCenter.getInstance()
179                 self.allowChanges = True
180                 
181                 self["list"] = ZapHistoryBrowserList([])
182                 self["key_red"] = Label(_("Clear"))
183                 self["key_green"] = Label(_("Delete"))
184                 self["key_yellow"] = Label(_("Zap & Close"))
185                 self["key_blue"] = Label(_("Config"))
186                 
187                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
188                         {
189                                 "ok": self.zap,
190                                 "cancel": self.close,
191                                 "red": self.clear,
192                                 "green": self.delete,
193                                 "yellow": self.zapAndClose,
194                                 "blue": self.config
195                         }, prio=-1)
196                 
197                 self.onLayoutFinish.append(self.buildList)
198
199         def buildList(self):
200                 list = []
201                 for x in self.servicelist.history:
202                         if len(x) == 2: # Single-Bouquet
203                                 ref = x[1]
204                         else: # Multi-Bouquet
205                                 ref = x[2]
206                         info = self.serviceHandler.info(ref)
207                         if info:
208                                 name = info.getName(ref).replace('\xc2\x86', '').replace('\xc2\x87', '')
209                                 event = info.getEvent(ref)
210                                 if event is not None:
211                                         eventName = event.getEventName()
212                                         if eventName is None:
213                                                 eventName = ""
214                                 else:
215                                         eventName = ""
216                         else:
217                                 name = "N/A"
218                                 eventName = ""
219                         list.append(ZapHistoryBrowserListEntry(name, eventName))
220                 list.reverse()
221                 self["list"].setList(list)
222
223         def zap(self):
224                 length = len(self.servicelist.history)
225                 if length > 0:
226                         self.servicelist.history_pos = (length - self["list"].getSelectionIndex()) - 1
227                         self.servicelist.setHistoryPath()
228
229         def clear(self):
230                 if self.allowChanges:
231                         for i in range(0, len(self.servicelist.history)):
232                                 del self.servicelist.history[0]
233                         self.buildList()
234                         self.servicelist.history_pos = 0
235
236         def delete(self):
237                 if self.allowChanges:
238                         length = len(self.servicelist.history)
239                         if length > 0:
240                                 idx = (length - self["list"].getSelectionIndex()) - 1
241                                 del self.servicelist.history[idx]
242                                 self.buildList()
243                                 currRef = self.session.nav.getCurrentlyPlayingServiceReference()
244                                 idx = 0
245                                 for x in self.servicelist.history:
246                                         if len(x) == 2: # Single-Bouquet
247                                                 ref = x[1]
248                                         else: # Multi-Bouquet
249                                                 ref = x[2]
250                                         if ref == currRef:
251                                                 self.servicelist.history_pos = idx
252                                                 break
253                                         else:
254                                                 idx += 1
255
256         def zapAndClose(self):
257                 self.zap()
258                 self.close()
259
260         def config(self):
261                 if self.allowChanges:
262                         self.session.open(ZapHistoryConfigurator)
263
264         def isProtected(self):
265                 return config.ParentalControl.setuppinactive.value and config.ParentalControl.configured.value
266         
267         def pinEntered(self, result):
268                 if result is None:
269                         self.allowChanges = False
270                 elif not result:
271                         self.allowChanges = False
272                 else:
273                         self.allowChanges = True
274
275 ################################################
276
277 def main(session, servicelist, **kwargs):
278         session.open(ZapHistoryBrowser, servicelist)
279
280 def Plugins(**kwargs):
281         return PluginDescriptor(name=_("Zap-History Browser"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main)