1 # -*- coding: UTF-8 -*-
2 # Zap Statistic by AliAbdul
3 from Components.ActionMap import ActionMap
4 from Components.config import config
5 from Components.Label import Label
6 from Components.Language import language
7 from Components.MenuList import MenuList
8 from Components.MultiContent import MultiContentEntryText
9 from enigma import eListboxPythonMultiContent, eServiceReference, gFont
10 from os import environ
11 from Plugins.Plugin import PluginDescriptor
\r
12 from Screens.ChoiceBox import ChoiceBox
13 from Screens.ParentalControlSetup import ProtectedScreen
14 from Screens.Screen import Screen
15 from ServiceReference import ServiceReference
16 from time import localtime, time
17 from Tools.Directories import fileExists, resolveFilename, SCOPE_LANGUAGE, SCOPE_PLUGINS
18 from xml.etree.cElementTree import parse
21 ###########################################################
24 lang = language.getLanguage()
25 environ["LANGUAGE"] = lang[:2]
26 gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
27 gettext.textdomain("enigma2")
28 gettext.bindtextdomain("ZapStatistic", "%s%s" % (resolveFilename(SCOPE_PLUGINS), "Extensions/ZapStatistic/locale/"))
31 t = gettext.dgettext("ZapStatistic", txt)
33 t = gettext.gettext(txt)
37 language.addCallback(localeInit)
39 ###########################################################
41 def decode_charset(str, charset):
43 uni = unicode(str, charset, 'strict')
48 ###########################################################
51 xml = xml.replace("&", "&")
52 xml = xml.replace("'", "'")
53 xml = xml.replace("<", "<")
54 xml = xml.replace(">", ">")
55 xml = xml.replace('"', """)
59 xml = xml.replace("&", "&")
60 xml = xml.replace("'", "'")
61 xml = xml.replace("<", "<")
62 xml = xml.replace(">", ">")
63 xml = xml.replace(""", '"')
66 ###########################################################
69 def __init__(self, ref, begin=None, end=None):
71 self.name = ServiceReference(eServiceReference(ref)).getServiceName()
81 ###########################################################
83 class DurationZapEntry:
84 def __init__(self, zapentry):
85 self.ref = zapentry.ref
86 self.name = zapentry.name
87 duration = zapentry.end - zapentry.begin
88 self.duration = "%02d:%02d:%02d" % (duration/3600, (duration/60) - ((duration/3600) * 60), duration%60)
89 t = localtime(zapentry.begin)
90 self.begin = "%02d.%02d. %02d:%02d:%02d" % (t[2], t[1], t[3], t[4], t[5])
92 ###########################################################
94 class CombinedZapEntry:
95 def __init__(self, zapentry):
96 self.ref = zapentry.ref
97 self.name = zapentry.name
98 self.duration = zapentry.end - zapentry.begin
100 def addDuration(self, zapentry):
101 self.duration = self.duration + zapentry.end - zapentry.begin
103 def getDurationText(self):
104 return "%02d:%02d:%02d" % (self.duration/3600, (self.duration/60) - ((self.duration/3600) * 60), self.duration%60)
106 ###########################################################
110 self.xmlFile = "/etc/zapstastistic.xml"
112 self.currentEntry = None
114 def loadZapEntries(self):
115 if fileExists(self.xmlFile):
117 menu = parse(self.xmlFile).getroot()
118 for item in menu.findall("entry"):
119 ref = item.get("ref") or None
121 ref = decode_charset(ref, "UTF-8").encode("UTF-8")
123 begin = item.get("begin") or None
124 end = item.get("end") or None
125 if ref and begin and end:
126 self.zapEntries.append(ZapEntry(ref, float(begin), float(end)))
128 print "[ZapStatistic] Error while reading xml file"
130 def saveZapEntries(self):
131 xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<zapstastistic>\n'
132 for x in self.zapEntries:
135 xml += '\t<entry ref="%s" begin="%s" end ="%s" />\n' % (decode_charset(deformXml(x.ref), "UTF-8"), str(x.begin), str(x.end))
136 xml += '</zapstastistic>'
138 f = open(self.xmlFile, "w")
139 f.write(xml.encode("UTF-8"))
142 print "[ZapStatistic] Error while writing xml file"
144 def handlePlayServiceCommand(self, ref):
145 self.handleStopServiceCommand()
147 self.currentEntry = ZapEntry(ref.toString())
149 def handleStopServiceCommand(self):
150 if self.currentEntry:
151 self.currentEntry.stop()
152 self.zapEntries.append(self.currentEntry)
153 self.currentEntry = None
155 zapstatistic = ZapStatistic()
157 ###########################################################
164 def playService(ref, checkParentalControl=True, forceRestart=False):
166 zapstatistic.handlePlayServiceCommand(ref)
167 PlayService(ref, checkParentalControl, forceRestart)
171 zapstatistic.handleStopServiceCommand()
174 ###########################################################
176 class ZapStatisticBrowserList(MenuList):
177 def __init__(self, list, enableWrapAround=False):
178 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
179 self.l.setItemHeight(25)
180 self.l.setFont(0, gFont("Regular", 20))
182 def ZapStatisticBrowserListEntry(entry):
184 t_begin = localtime(entry.begin)
185 t_end = localtime(entry.end)
186 res.append(MultiContentEntryText(pos=(0, 0), size=(240, 25), font=0, text="%02d.%02d. %02d:%02d:%02d - %02d:%02d:%02d" % (t_begin[2], t_begin[1], t_begin[3], t_begin[4], t_begin[5], t_end[3], t_end[4], t_end[5])))
187 res.append(MultiContentEntryText(pos=(250, 0), size=(310, 25), font=0, text=entry.name))
190 def ZapStatisticBrowserDurationListEntry(entry):
192 res.append(MultiContentEntryText(pos=(0, 0), size=(240, 25), font=0, text="%s (%s)" % (entry.duration, entry.begin)))
193 res.append(MultiContentEntryText(pos=(250, 0), size=(310, 25), font=0, text=entry.name))
196 def ZapStatisticBrowserCombinedListEntry(entry):
198 res.append(MultiContentEntryText(pos=(0, 0), size=(150, 25), font=0, text="%s" % (entry.getDurationText())))
199 res.append(MultiContentEntryText(pos=(160, 0), size=(400, 25), font=0, text=entry.name))
202 ###########################################################
204 class ZapStatisticDurationScreen(Screen):
205 SORT_NAME_ASCENDING = 0
206 SORT_NAME_DESCENDING = 1
207 SORT_DURATION_ASCENDING = 2
208 SORT_DURATION_DESCENDING = 3
210 <screen position="center,center" size="560,450" title="%s" >
211 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
212 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
213 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
214 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
215 <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
216 <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
217 <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
218 <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
219 <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
220 </screen>""" % _("Zap Statistic")
222 def __init__(self, session):
223 Screen.__init__(self, session)
225 self.sortType = self.SORT_NAME_ASCENDING
227 self["key_red"] = Label(_("Sort (name+)"))
228 self["key_green"] = Label(_("Sort (name-)"))
229 self["key_yellow"] = Label(_("Sort (duration+)"))
230 self["key_blue"] = Label(_("Sort (duration-)"))
231 self["list"] = ZapStatisticBrowserList([])
233 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
236 "cancel": self.close,
237 "red": self.sortByNameAscending,
238 "green": self.sortByNameDescending,
239 "yellow": self.sortByDurationAscending,
240 "blue": self.sortByDurationDescending
243 self.onLayoutFinish.append(self.buildList)
245 def sortList(self, l):
246 if self.sortType == self.SORT_NAME_ASCENDING:
247 return l.sort(key=self.buildSortNameKey, reverse=False)
248 elif self.sortType == self.SORT_NAME_DESCENDING:
249 return l.sort(key=self.buildSortNameKey, reverse=True)
250 elif self.sortType == self.SORT_DURATION_ASCENDING:
251 return l.sort(key=self.buildSortDurationKey, reverse=False)
252 elif self.sortType == self.SORT_DURATION_DESCENDING:
253 return l.sort(key=self.buildSortDurationKey, reverse=True)
257 def buildSortNameKey(self, x):
260 return (name and name.lower() or "")
262 def buildSortDurationKey(self, x):
263 try: name = str(x.duration)
265 return (name and name.lower() or "")
270 for x in zapstatistic.zapEntries:
271 l.append(DurationZapEntry(x))
274 list.append(ZapStatisticBrowserDurationListEntry(x))
275 self["list"].setList(list)
278 cur = self["list"].getCurrent()
281 self.session.nav.playService(eServiceReference(entry.ref))
283 def sortByNameAscending(self):
284 self.sortType = self.SORT_NAME_ASCENDING
287 def sortByNameDescending(self):
288 self.sortType = self.SORT_NAME_DESCENDING
291 def sortByDurationAscending(self):
292 self.sortType = self.SORT_DURATION_ASCENDING
295 def sortByDurationDescending(self):
296 self.sortType = self.SORT_DURATION_DESCENDING
299 ###########################################################
301 class ZapStatisticCombinedScreen(Screen):
302 SORT_NAME_ASCENDING = 0
303 SORT_NAME_DESCENDING = 1
304 SORT_DURATION_ASCENDING = 2
305 SORT_DURATION_DESCENDING = 3
307 <screen position="center,center" size="560,450" title="%s" >
308 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
309 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
310 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
311 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
312 <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
313 <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
314 <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
315 <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
316 <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
317 </screen>""" % _("Zap Statistic")
319 def __init__(self, session):
320 Screen.__init__(self, session)
323 self.sortType = self.SORT_DURATION_DESCENDING
325 self["key_red"] = Label(_("Sort (name+)"))
326 self["key_green"] = Label(_("Sort (name-)"))
327 self["key_yellow"] = Label(_("Sort (duration+)"))
328 self["key_blue"] = Label(_("Sort (duration-)"))
329 self["list"] = ZapStatisticBrowserList([])
331 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
334 "cancel": self.close,
335 "red": self.sortByNameAscending,
336 "green": self.sortByNameDescending,
337 "yellow": self.sortByDurationAscending,
338 "blue": self.sortByDurationDescending
341 self.onLayoutFinish.append(self.buildList)
343 def sortList(self, l):
344 if self.sortType == self.SORT_NAME_ASCENDING:
345 return l.sort(key=self.buildSortNameKey, reverse=False)
346 elif self.sortType == self.SORT_NAME_DESCENDING:
347 return l.sort(key=self.buildSortNameKey, reverse=True)
348 elif self.sortType == self.SORT_DURATION_ASCENDING:
349 return l.sort(key=self.buildSortDurationKey, reverse=False)
350 elif self.sortType == self.SORT_DURATION_DESCENDING:
351 return l.sort(key=self.buildSortDurationKey, reverse=True)
355 def buildSortNameKey(self, x):
358 return (name and name.lower() or "")
360 def buildSortDurationKey(self, x):
361 try: name = x.getDurationText()
363 return (name and name.lower() or "")
367 if len(self.list) == 0:
368 for x in zapstatistic.zapEntries:
376 self.list.append(CombinedZapEntry(x))
377 self.sortList(self.list)
379 list.append(ZapStatisticBrowserCombinedListEntry(x))
380 self["list"].setList(list)
383 cur = self["list"].getCurrent()
386 self.session.nav.playService(eServiceReference(entry.ref))
388 def sortByNameAscending(self):
389 self.sortType = self.SORT_NAME_ASCENDING
392 def sortByNameDescending(self):
393 self.sortType = self.SORT_NAME_DESCENDING
396 def sortByDurationAscending(self):
397 self.sortType = self.SORT_DURATION_ASCENDING
400 def sortByDurationDescending(self):
401 self.sortType = self.SORT_DURATION_DESCENDING
404 ###########################################################
406 class ZapStatisticScreen(Screen, ProtectedScreen):
407 SORT_NAME_ASCENDING = 0
408 SORT_NAME_DESCENDING = 1
409 SORT_DATE_ASCENDING = 2
410 SORT_DATE_DESCENDING = 3
412 <screen position="center,center" size="560,450" title="%s" >
413 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />
414 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />
415 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />
416 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />
417 <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
418 <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
419 <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
420 <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
421 <widget name="list" position="0,40" size="560,400" scrollbarMode="showOnDemand" />
422 </screen>""" % _("Zap Statistic")
424 def __init__(self, session):
425 Screen.__init__(self, session)
426 ProtectedScreen.__init__(self)
428 self.session = session
429 self.sortType = self.SORT_DATE_ASCENDING
431 self["key_red"] = Label(_("Delete"))
432 self["key_green"] = Label(" ")
433 self["key_yellow"] = Label(" ")
434 self["key_blue"] = Label(_("Durations"))
435 self["list"] = ZapStatisticBrowserList([])
437 self["actions"] = ActionMap(["ColorActions", "OkCancelActions", "InfobarMenuActions"],
440 "cancel": self.close,
442 "green": self.sortByName,
443 "yellow": self.sortByDate,
444 "blue": self.duration,
\r
445 "mainMenu": self.menu
448 self.onLayoutFinish.append(self.buildList)
450 def updateLabels(self):
451 self["key_green"].setText(_("Sort (name+)"))
452 self["key_yellow"].setText(_("Sort (date+)"))
453 if self.sortType == self.SORT_NAME_ASCENDING:
454 self["key_green"].setText(_("Sort (name-)"))
455 if self.sortType == self.SORT_DATE_ASCENDING:
456 self["key_yellow"].setText(_("Sort (date-)"))
458 def sortList(self, l):
459 if self.sortType == self.SORT_NAME_ASCENDING:
460 return l.sort(key=self.buildSortNameKey, reverse=False)
461 elif self.sortType == self.SORT_NAME_DESCENDING:
462 return l.sort(key=self.buildSortNameKey, reverse=True)
463 elif self.sortType == self.SORT_DATE_ASCENDING:
464 return l.sort(key=self.buildSortDateKey, reverse=False)
465 elif self.sortType == self.SORT_DATE_DESCENDING:
466 return l.sort(key=self.buildSortDateKey, reverse=True)
470 def buildSortNameKey(self, x):
473 return (name and name.lower() or "")
475 def buildSortDateKey(self, x):
476 try: name = str(x.begin)
478 return (name and name.lower() or "")
482 l = zapstatistic.zapEntries
485 list.append(ZapStatisticBrowserListEntry(x))
486 self["list"].setList(list)
489 def isProtected(self):
490 return config.ParentalControl.setuppinactive.value and config.ParentalControl.configured.value
492 def pinEntered(self, result):
499 cur = self["list"].getCurrent()
502 self.session.nav.playService(eServiceReference(entry.ref))
505 cur = self["list"].getCurrent()
509 for x in zapstatistic.zapEntries:
511 del zapstatistic.zapEntries[idx]
518 if len(zapstatistic.zapEntries):
519 del zapstatistic.zapEntries
520 zapstatistic.zapEntries = []
523 def sortByName(self):
524 if self["key_green"].getText() == _("Sort (name-)"):
525 self.sortType = self.SORT_NAME_DESCENDING
527 self.sortType = self.SORT_NAME_ASCENDING
530 def sortByNameAscending(self):
531 self.sortType = self.SORT_NAME_ASCENDING
534 def sortByNameDescending(self):
535 self.sortType = self.SORT_NAME_DESCENDING
538 def sortByDate(self):
539 if self["key_yellow"].getText() == _("Sort (date-)"):
540 self.sortType = self.SORT_DATE_DESCENDING
542 self.sortType = self.SORT_DATE_ASCENDING
545 def sortByDateAscending(self):
546 self.sortType = self.SORT_DATE_ASCENDING
549 def sortByDateDescending(self):
550 self.sortType = self.SORT_DATE_DESCENDING
554 self.session.open(ZapStatisticDurationScreen)
557 self.session.open(ZapStatisticCombinedScreen)
561 list.append((_("Play entry"), self.play))
\r
562 list.append((_("Delete entry"), self.delete))
\r
563 list.append((_("Delete all entries"), self.deleteAll))
\r
564 list.append((_("Sort by name (ascending)"), self.sortByNameAscending))
\r
565 list.append((_("Sort by name (descending)"), self.sortByNameDescending))
\r
566 list.append((_("Sort by date (ascending)"), self.sortByDateAscending))
\r
567 list.append((_("Sort by date (descending)"), self.sortByDateDescending))
\r
568 list.append((_("Show duration window"), self.duration))
\r
569 list.append((_("Show combined duration window"), self.combined))
\r
570 list.append((_("Close plugin"), self.close))
\r
571 self.session.openWithCallback(self.menuCallback, ChoiceBox, title=_("Please choose a function..."), list=list)
573 def menuCallback(self, callback=None):
\r
574 if callback is not None:
\r
577 ###########################################################
579 def main(session, **kwargs):
580 session.open(ZapStatisticScreen)
582 def sessionstart(reason, **kwargs):
584 zapstatistic.loadZapEntries()
585 session = kwargs["session"]
588 PlayService = session.nav.playService
589 StopService = session.nav.stopService
590 session.nav.playService = playService
591 session.nav.stopService = stopService
593 def autostart(reason, **kwargs):
595 zapstatistic.saveZapEntries()
597 def Plugins(**kwargs):
598 return [PluginDescriptor(name=_("Zap Statistic"), description=_("Shows the watched services with some statistic"), where=PluginDescriptor.WHERE_PLUGINMENU, fnc=main),
599 PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, fnc=sessionstart),
600 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=autostart)]