Enigma2-Plugins-{GraphMultiEPG/GraphMultiEpg.py, MediaPlayer/plugin.py, SoftwareManag...
[enigma2.git] / lib / python / Plugins / Extensions / GraphMultiEPG / GraphMultiEpg.py
old mode 100644 (file)
new mode 100755 (executable)
index 3148879..1d621f4
@@ -7,17 +7,20 @@ from Components.HTMLComponent import HTMLComponent
 from Components.GUIComponent import GUIComponent
 from Components.EpgList import Rect
 from Components.Sources.Event import Event
 from Components.GUIComponent import GUIComponent
 from Components.EpgList import Rect
 from Components.Sources.Event import Event
-from Components.Sources.Source import ObsoleteSource
 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
+from Components.TimerList import TimerList
 from Screens.Screen import Screen
 from Screens.EventView import EventViewSimple
 from Screens.TimeDateInput import TimeDateInput
 from Screens.TimerEntry import TimerEntry
 from Screens.EpgSelection import EPGSelection
 from Screens.Screen import Screen
 from Screens.EventView import EventViewSimple
 from Screens.TimeDateInput import TimeDateInput
 from Screens.TimerEntry import TimerEntry
 from Screens.EpgSelection import EPGSelection
-from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE
-from RecordTimer import RecordTimerEntry, parseEvent
+from Screens.TimerEdit import TimerSanityConflict
+from Screens.MessageBox import MessageBox
+from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
+from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT
 from ServiceReference import ServiceReference
 from ServiceReference import ServiceReference
-from enigma import eEPGCache, eListbox, gFont, loadPNG, eListboxPythonMultiContent, \
+from Tools.LoadPixmap import LoadPixmap
+from enigma import eEPGCache, eListbox, gFont, eListboxPythonMultiContent, \
        RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eRect, eTimer
 
 from time import localtime, time, strftime
        RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eRect, eTimer
 
 from time import localtime, time, strftime
@@ -38,7 +41,11 @@ class EPGList(HTMLComponent, GUIComponent):
                if overjump_empty:
                        self.l.setSelectableFunc(self.isSelectable)
                self.epgcache = eEPGCache.getInstance()
                if overjump_empty:
                        self.l.setSelectableFunc(self.isSelectable)
                self.epgcache = eEPGCache.getInstance()
-               self.clock_pixmap = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, 'epgclock-fs8.png'))
+               self.clock_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, 'skin_default/icons/epgclock.png'))
+               self.clock_add_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, 'skin_default/icons/epgclock_add.png'))
+               self.clock_pre_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, 'skin_default/icons/epgclock_pre.png'))
+               self.clock_post_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, 'skin_default/icons/epgclock_post.png'))
+               self.clock_prepost_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, 'skin_default/icons/epgclock_prepost.png'))
                self.time_base = None
                self.time_epoch = time_epoch
                self.list = None
                self.time_base = None
                self.time_epoch = time_epoch
                self.list = None
@@ -52,7 +59,7 @@ class EPGList(HTMLComponent, GUIComponent):
                self.foreColorService = None
                self.backColorService = None
 
                self.foreColorService = None
                self.backColorService = None
 
-       def applySkin(self, desktop):
+       def applySkin(self, desktop, screen):
                if self.skinAttributes is not None:
                        attribs = [ ]
                        for (attrib, value) in self.skinAttributes:
                if self.skinAttributes is not None:
                        attribs = [ ]
                        for (attrib, value) in self.skinAttributes:
@@ -73,16 +80,16 @@ class EPGList(HTMLComponent, GUIComponent):
                                else:
                                        attribs.append((attrib,value))
                        self.skinAttributes = attribs
                                else:
                                        attribs.append((attrib,value))
                        self.skinAttributes = attribs
-               return GUIComponent.applySkin(self, desktop)
+               return GUIComponent.applySkin(self, desktop, screen)
 
        def isSelectable(self, service, sname, event_list):
                return (event_list and len(event_list) and True) or False
 
        def setEpoch(self, epoch):
 
        def isSelectable(self, service, sname, event_list):
                return (event_list and len(event_list) and True) or False
 
        def setEpoch(self, epoch):
-               if self.cur_event is not None and self.cur_service is not None:
-                       self.offs = 0
-                       self.time_epoch = epoch
-                       self.fillMultiEPG(None) # refill
+#              if self.cur_event is not None and self.cur_service is not None:
+               self.offs = 0
+               self.time_epoch = epoch
+               self.fillMultiEPG(None) # refill
 
        def getEventFromId(self, service, eventid):
                event = None
 
        def getEventFromId(self, service, eventid):
                event = None
@@ -90,14 +97,31 @@ class EPGList(HTMLComponent, GUIComponent):
                        event = self.epgcache.lookupEventId(service.ref, eventid)
                return event
 
                        event = self.epgcache.lookupEventId(service.ref, eventid)
                return event
 
+       def moveToService(self,serviceref):
+               if serviceref is not None:
+                       for x in range(len(self.list)):
+                               if self.list[x][0] == serviceref.toString():
+                                       self.instance.moveSelectionTo(x)
+                                       break
+       
+       def getIndexFromService(self, serviceref):
+               if serviceref is not None:
+                       for x in range(len(self.list)):
+                               if self.list[x][0] == serviceref.toString():
+                                       return x
+               
+       def setCurrentIndex(self, index):
+               if self.instance is not None:
+                       self.instance.moveSelectionTo(index)
+       
        def getCurrent(self):
        def getCurrent(self):
-               if self.cur_service is None or self.cur_event is None:
+               if self.cur_service is None:
                        return ( None, None )
                old_service = self.cur_service  #(service, service_name, events)
                events = self.cur_service[2]
                refstr = self.cur_service[0]
                        return ( None, None )
                old_service = self.cur_service  #(service, service_name, events)
                events = self.cur_service[2]
                refstr = self.cur_service[0]
-               if not events or not len(events):
-                       return ( None, None )
+               if self.cur_event is None or not events or not len(events):
+                       return ( None, ServiceReference(refstr) )
                event = events[self.cur_event] #(event_id, event_title, begin_time, duration)
                eventid = event[0]
                service = ServiceReference(refstr)
                event = events[self.cur_event] #(event_id, event_title, begin_time, duration)
                eventid = event[0]
                service = ServiceReference(refstr)
@@ -153,11 +177,12 @@ class EPGList(HTMLComponent, GUIComponent):
        def selectionChanged(self):
                for x in self.onSelChanged:
                        if x is not None:
        def selectionChanged(self):
                for x in self.onSelChanged:
                        if x is not None:
-                               try:
-                                       x()
-                               except: # FIXME!!!
-                                       print "FIXME in EPGList.selectionChanged"
-                                       pass
+                               x()
+#                              try:
+#                                      x()
+#                              except: # FIXME!!!
+#                                      print "FIXME in EPGList.selectionChanged"
+#                                      pass
 
        GUI_WIDGET = eListbox
 
 
        GUI_WIDGET = eListbox
 
@@ -169,6 +194,10 @@ class EPGList(HTMLComponent, GUIComponent):
                self.l.setFont(1, gFont("Regular", 14))
                self.l.setSelectionClip(eRect(0,0,0,0), False)
 
                self.l.setFont(1, gFont("Regular", 14))
                self.l.setSelectionClip(eRect(0,0,0,0), False)
 
+       def preWidgetRemove(self, instance):
+               instance.selectionChanged.get().remove(self.serviceChanged)
+               instance.setContent(None)
+
        def recalcEntrySize(self):
                esize = self.l.getItemSize()
                width = esize.width()
        def recalcEntrySize(self):
                esize = self.l.getItemSize()
                width = esize.width()
@@ -198,7 +227,13 @@ class EPGList(HTMLComponent, GUIComponent):
        def buildEntry(self, service, service_name, events):
                r1=self.service_rect
                r2=self.event_rect
        def buildEntry(self, service, service_name, events):
                r1=self.service_rect
                r2=self.event_rect
-               res = [ None, MultiContentEntryText(pos = (r1.left(),r1.top()), size = (r1.width(), r1.height()), font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_CENTER, text = service_name, color = self.foreColorService, backcolor = self.backColorService) ]
+               res = [ None, MultiContentEntryText(
+                                               pos = (r1.left(),r1.top()),
+                                               size = (r1.width(), r1.height()),
+                                               font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_CENTER,
+                                               text = service_name,
+                                               color = self.foreColorService,
+                                               backcolor = self.backColorService) ]
 
                if events:
                        start = self.time_base+self.offs*self.time_epoch*60
 
                if events:
                        start = self.time_base+self.offs*self.time_epoch*60
@@ -214,11 +249,19 @@ class EPGList(HTMLComponent, GUIComponent):
                        borderColor = self.borderColor
 
                        for ev in events:  #(event_id, event_title, begin_time, duration)
                        borderColor = self.borderColor
 
                        for ev in events:  #(event_id, event_title, begin_time, duration)
-                               rec=self.timer.isInTimer(ev[0], ev[2], ev[3], service) > ((ev[3]/10)*8)
+                               rec=ev[2] and self.timer.isInTimer(ev[0], ev[2], ev[3], service)
                                xpos, ewidth = self.calcEntryPosAndWidthHelper(ev[2], ev[3], start, end, width)
                                xpos, ewidth = self.calcEntryPosAndWidthHelper(ev[2], ev[3], start, end, width)
-                               res.append(MultiContentEntryText(pos = (left+xpos, top), size = (ewidth, height), font = 1, flags = RT_HALIGN_CENTER | RT_VALIGN_CENTER | RT_WRAP, text = ev[1], color = foreColor, color_sel = foreColorSelected, backcolor = backColor, backcolor_sel = backColorSelected, border_width = 1, border_color = borderColor))
+                               res.append(MultiContentEntryText(
+                                       pos = (left+xpos, top), size = (ewidth, height),
+                                       font = 1, flags = RT_HALIGN_CENTER | RT_VALIGN_CENTER | RT_WRAP,
+                                       text = ev[1], color = foreColor, color_sel = foreColorSelected,
+                                       backcolor = backColor, backcolor_sel = backColorSelected, border_width = 1, border_color = borderColor))
                                if rec and ewidth > 23:
                                if rec and ewidth > 23:
-                                       res.append(MultiContentEntryPixmapAlphaTest(pos = (left+xpos+ewidth-22, top+height-22), size = (21, 21), png = self.clock_pixmap, backcolor = backColor, backcolor_sel = backColorSelected))
+                                       res.append(MultiContentEntryPixmapAlphaTest(
+                                               pos = (left+xpos+ewidth-22, top+height-22), size = (21, 21),
+                                               png = self.getClockPixmap(service, ev[2], ev[3], ev[0]),
+                                               backcolor = backColor,
+                                               backcolor_sel = backColorSelected))
                return res
 
        def selEntry(self, dir, visible=True):
                return res
 
        def selEntry(self, dir, visible=True):
@@ -271,9 +314,14 @@ class EPGList(HTMLComponent, GUIComponent):
                        self.cur_service = None
                        self.time_base = int(stime)
                        test = [ (service.ref.toString(), 0, self.time_base, self.time_epoch) for service in services ]
                        self.cur_service = None
                        self.time_base = int(stime)
                        test = [ (service.ref.toString(), 0, self.time_base, self.time_epoch) for service in services ]
-               test.insert(0, 'RnITBD')
+               test.insert(0, 'XRnITBD')
+#              print "BEFORE:"
+#              for x in test:
+#                      print x
                epg_data = self.queryEPG(test)
                epg_data = self.queryEPG(test)
-
+#              print "EPG:"
+#              for x in epg_data:
+#                      print x
                self.list = [ ]
                tmp_list = None
                service = ""
                self.list = [ ]
                tmp_list = None
                service = ""
@@ -304,6 +352,30 @@ class EPGList(HTMLComponent, GUIComponent):
 
        def resetOffset(self):
                self.offs = 0
 
        def resetOffset(self):
                self.offs = 0
+       
+       def getClockPixmap(self, refstr, beginTime, duration, eventId):
+               pre_clock = 1
+               post_clock = 2
+               clock_type = 0
+               endTime = beginTime + duration
+               for x in self.timer.timer_list:
+                       if x.service_ref.ref.toString() == refstr:
+                               if x.eit == eventId:
+                                       return self.clock_pixmap
+                               beg = x.begin
+                               end = x.end
+                               if beginTime > beg and beginTime < end and endTime > end:
+                                       clock_type |= pre_clock
+                               elif beginTime < beg and endTime > beg and endTime < end:
+                                       clock_type |= post_clock
+               if clock_type == 0:
+                       return self.clock_add_pixmap
+               elif clock_type == pre_clock:
+                       return self.clock_pre_pixmap
+               elif clock_type == post_clock:
+                       return self.clock_post_pixmap
+               else:
+                       return self.clock_prepost_pixmap
 
 class TimelineText(HTMLComponent, GUIComponent):
        def __init__(self):
 
 class TimelineText(HTMLComponent, GUIComponent):
        def __init__(self):
@@ -331,6 +403,12 @@ config.misc.graph_mepg_prev_time=ConfigClock(default = time())
 config.misc.graph_mepg_prev_time_period=ConfigInteger(default=120, limits=(60,300))
 
 class GraphMultiEPG(Screen):
 config.misc.graph_mepg_prev_time_period=ConfigInteger(default=120, limits=(60,300))
 
 class GraphMultiEPG(Screen):
+       EMPTY = 0
+       ADD_TIMER = 1
+       REMOVE_TIMER = 2
+       
+       ZAP = 1
+
        def __init__(self, session, services, zapFunc=None, bouquetChangeCB=None):
                Screen.__init__(self, session)
                self.bouquetChangeCB = bouquetChangeCB
        def __init__(self, session, services, zapFunc=None, bouquetChangeCB=None):
                Screen.__init__(self, session)
                self.bouquetChangeCB = bouquetChangeCB
@@ -339,10 +417,11 @@ class GraphMultiEPG(Screen):
                self.ask_time = now - tmp
                self.closeRecursive = False
                self["key_red"] = Button("")
                self.ask_time = now - tmp
                self.closeRecursive = False
                self["key_red"] = Button("")
-               self["key_green"] = Button(_("Add timer"))
+               self["key_green"] = Button("")
+               self.key_green_choice = self.EMPTY
+               self.key_red_choice = self.EMPTY
                self["timeline_text"] = TimelineText()
                self["Event"] = Event()
                self["timeline_text"] = TimelineText()
                self["Event"] = Event()
-               self["Clock"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
                self.time_lines = [ ]
                for x in (0,1,2,3,4,5):
                        pm = Pixmap()
                self.time_lines = [ ]
                for x in (0,1,2,3,4,5):
                        pm = Pixmap()
@@ -379,7 +458,7 @@ class GraphMultiEPG(Screen):
                        },-1)
 
                self.updateTimelineTimer = eTimer()
                        },-1)
 
                self.updateTimelineTimer = eTimer()
-               self.updateTimelineTimer.timeout.get().append(self.moveTimeLines)
+               self.updateTimelineTimer.callback.append(self.moveTimeLines)
                self.updateTimelineTimer.start(60*1000)
                self.onLayoutFinish.append(self.onCreate)
 
                self.updateTimelineTimer.start(60*1000)
                self.onLayoutFinish.append(self.onCreate)
 
@@ -464,6 +543,7 @@ class GraphMultiEPG(Screen):
        #just used in multipeg
        def onCreate(self):
                self["list"].fillMultiEPG(self.services, self.ask_time)
        #just used in multipeg
        def onCreate(self):
                self["list"].fillMultiEPG(self.services, self.ask_time)
+               self["list"].moveToService(self.session.nav.getCurrentlyPlayingServiceReference())
                self.moveTimeLines()
 
        def eventViewCallback(self, setEvent, setService, val):
                self.moveTimeLines()
 
        def eventViewCallback(self, setEvent, setService, val):
@@ -481,43 +561,109 @@ class GraphMultiEPG(Screen):
                        setEvent(cur[0])
 
        def zapTo(self):
                        setEvent(cur[0])
 
        def zapTo(self):
-               if self.zapFunc and self["key_red"].getText() == "Zap":
+               if self.zapFunc and self.key_red_choice == self.ZAP:
                        self.closeRecursive = True
                        ref = self["list"].getCurrent()[1]
                        self.closeRecursive = True
                        ref = self["list"].getCurrent()[1]
-                       self.zapFunc(ref.ref)
+                       if ref:
+                               self.zapFunc(ref.ref)
 
        def eventSelected(self):
                self.infoKeyPressed()
 
 
        def eventSelected(self):
                self.infoKeyPressed()
 
+       def removeTimer(self, timer):
+               timer.afterEvent = AFTEREVENT.NONE
+               self.session.nav.RecordTimer.removeEntry(timer)
+               self["key_green"].setText(_("Add timer"))
+               self.key_green_choice = self.ADD_TIMER
+       
        def timerAdd(self):
                cur = self["list"].getCurrent()
                event = cur[0]
                serviceref = cur[1]
                if event is None:
                        return
        def timerAdd(self):
                cur = self["list"].getCurrent()
                event = cur[0]
                serviceref = cur[1]
                if event is None:
                        return
-               newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event))
-               self.session.openWithCallback(self.timerEditFinished, TimerEntry, newEntry)
+               eventid = event.getEventId()
+               refstr = serviceref.ref.toString()
+               for timer in self.session.nav.RecordTimer.timer_list:
+                       if timer.eit == eventid and timer.service_ref.ref.toString() == refstr:
+                               cb_func = lambda ret : not ret or self.removeTimer(timer)
+                               self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName())
+                               break
+               else:
+                       newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event))
+                       self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
 
 
-       def timerEditFinished(self, answer):
+       def finishedAdd(self, answer):
+               print "finished add"
                if answer[0]:
                if answer[0]:
-                       self.session.nav.RecordTimer.record(answer[1])
+                       entry = answer[1]
+                       simulTimerList = self.session.nav.RecordTimer.record(entry)
+                       if simulTimerList is not None:
+                               for x in simulTimerList:
+                                       if x.setAutoincreaseEnd(entry):
+                                               self.session.nav.RecordTimer.timeChanged(x)
+                               simulTimerList = self.session.nav.RecordTimer.record(entry)
+                               if simulTimerList is not None:
+                                       self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
+                       self["key_green"].setText(_("Remove timer"))
+                       self.key_green_choice = self.REMOVE_TIMER
                else:
                else:
+                       self["key_green"].setText(_("Add timer"))
+                       self.key_green_choice = self.ADD_TIMER
                        print "Timeredit aborted"
                        print "Timeredit aborted"
+       
+       def finishSanityCorrection(self, answer):
+               self.finishedAdd(answer)
 
        def onSelectionChanged(self):
 
        def onSelectionChanged(self):
-               evt = self["list"].getCurrent()
-               self["Event"].newEvent(evt and evt[0])
-               if evt and evt[0]:
-                       evt = evt[0]
-                       now = time()
-                       start = evt.getBeginTime()
-                       end = start + evt.getDuration()
-                       if now >= start and now <= end:
-                               self["key_red"].setText("Zap")
-                       else:
+               cur = self["list"].getCurrent()
+               if cur is None:
+                       if self.key_green_choice != self.EMPTY:
+                               self["key_green"].setText("")
+                               self.key_green_choice = self.EMPTY
+                       if self.key_red_choice != self.EMPTY:
                                self["key_red"].setText("")
                                self["key_red"].setText("")
-
+                               self.key_red_choice = self.EMPTY
+                       return
+               
+               event = cur[0]
+               self["Event"].newEvent(event)
+               
+               if cur[1] is None or cur[1].getServiceName() == "":
+                       if self.key_green_choice != self.EMPTY:
+                               self["key_green"].setText("")
+                               self.key_green_choice = self.EMPTY
+                       if self.key_red_choice != self.EMPTY:
+                               self["key_red"].setText("")
+                               self.key_red_choice = self.EMPTY
+                       return
+               elif self.key_red_choice != self.ZAP:
+                               self["key_red"].setText("Zap")
+                               self.key_red_choice = self.ZAP
+                       
+               if not event:
+                       if self.key_green_choice != self.EMPTY:
+                               self["key_green"].setText("")
+                               self.key_green_choice = self.EMPTY
+                       return
+               
+               serviceref = cur[1]
+               eventid = event.getEventId()
+               refstr = serviceref.ref.toString()
+               isRecordEvent = False
+               for timer in self.session.nav.RecordTimer.timer_list:
+                       if timer.eit == eventid and timer.service_ref.ref.toString() == refstr:
+                               isRecordEvent = True
+                               break
+               if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER:
+                       self["key_green"].setText(_("Remove timer"))
+                       self.key_green_choice = self.REMOVE_TIMER
+               elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER:
+                       self["key_green"].setText(_("Add timer"))
+                       self.key_green_choice = self.ADD_TIMER
+       
        def moveTimeLines(self, force=False):
        def moveTimeLines(self, force=False):
+               self.updateTimelineTimer.start((60-(int(time())%60))*1000)      #keep syncronised
                l = self["list"]
                event_rect = l.getEventRect()
                time_epoch = l.getTimeEpoch()
                l = self["list"]
                event_rect = l.getEventRect()
                time_epoch = l.getTimeEpoch()
@@ -525,6 +671,7 @@ class GraphMultiEPG(Screen):
                if event_rect is None or time_epoch is None or time_base is None:
                        return
                time_steps = time_epoch > 180 and 60 or 30
                if event_rect is None or time_epoch is None or time_base is None:
                        return
                time_steps = time_epoch > 180 and 60 or 30
+               
                num_lines = time_epoch/time_steps
                incWidth=event_rect.width()/num_lines
                pos=event_rect.left()
                num_lines = time_epoch/time_steps
                incWidth=event_rect.width()/num_lines
                pos=event_rect.left()
@@ -552,8 +699,7 @@ class GraphMultiEPG(Screen):
                now=time()
                timeline_now = self["timeline_now"]
                if now >= time_base and now < (time_base + time_epoch * 60):
                now=time()
                timeline_now = self["timeline_now"]
                if now >= time_base and now < (time_base + time_epoch * 60):
-                       bla = (event_rect.width() * 1000) / time_epoch
-                       xpos = ((now/60) - (time_base/60)) * bla / 1000
+                       xpos = int((((now - time_base) * event_rect.width()) / (time_epoch * 60))-(timeline_now.instance.size().width()/2))
                        old_pos = timeline_now.position
                        new_pos = (xpos+event_rect.left(), old_pos[1])
                        if old_pos != new_pos:
                        old_pos = timeline_now.position
                        new_pos = (xpos+event_rect.left(), old_pos[1])
                        if old_pos != new_pos:
@@ -561,3 +707,6 @@ class GraphMultiEPG(Screen):
                        timeline_now.visible = True
                else:
                        timeline_now.visible = False
                        timeline_now.visible = True
                else:
                        timeline_now.visible = False
+               # here no l.l.invalidate() is needed when the zPosition in the skin is correct!
+
+