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 6743161..1d621f4
@@ -7,15 +7,17 @@ from Components.HTMLComponent import HTMLComponent
 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.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 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 Tools.LoadPixmap import LoadPixmap
 from enigma import eEPGCache, eListbox, gFont, eListboxPythonMultiContent, \
@@ -39,7 +41,11 @@ class EPGList(HTMLComponent, GUIComponent):
                if overjump_empty:
                        self.l.setSelectableFunc(self.isSelectable)
                self.epgcache = eEPGCache.getInstance()
-               self.clock_pixmap = LoadPixmap(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
@@ -53,7 +59,7 @@ class EPGList(HTMLComponent, GUIComponent):
                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:
@@ -74,16 +80,16 @@ class EPGList(HTMLComponent, GUIComponent):
                                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):
-               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
@@ -91,14 +97,31 @@ class EPGList(HTMLComponent, GUIComponent):
                        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):
-               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]
-               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)
@@ -154,11 +177,12 @@ class EPGList(HTMLComponent, GUIComponent):
        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
 
@@ -203,7 +227,13 @@ class EPGList(HTMLComponent, GUIComponent):
        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
@@ -219,11 +249,19 @@ class EPGList(HTMLComponent, GUIComponent):
                        borderColor = self.borderColor
 
                        for ev in events:  #(event_id, event_title, begin_time, duration)
-                               rec=ev[2] and 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)
-                               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:
-                                       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):
@@ -277,8 +315,13 @@ class EPGList(HTMLComponent, GUIComponent):
                        self.time_base = int(stime)
                        test = [ (service.ref.toString(), 0, self.time_base, self.time_epoch) for service in services ]
                test.insert(0, 'XRnITBD')
+#              print "BEFORE:"
+#              for x in test:
+#                      print x
                epg_data = self.queryEPG(test)
-
+#              print "EPG:"
+#              for x in epg_data:
+#                      print x
                self.list = [ ]
                tmp_list = None
                service = ""
@@ -309,6 +352,30 @@ class EPGList(HTMLComponent, GUIComponent):
 
        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):
@@ -336,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):
+       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
@@ -344,10 +417,11 @@ class GraphMultiEPG(Screen):
                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["Clock"] = ObsoleteSource(new_source = "global.CurrentTime", removal_date = "2008-01")
                self.time_lines = [ ]
                for x in (0,1,2,3,4,5):
                        pm = Pixmap()
@@ -469,6 +543,7 @@ class GraphMultiEPG(Screen):
        #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):
@@ -486,43 +561,109 @@ class GraphMultiEPG(Screen):
                        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.zapFunc(ref.ref)
+                       if ref:
+                               self.zapFunc(ref.ref)
 
        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
-               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]:
-                       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:
+                       self["key_green"].setText(_("Add timer"))
+                       self.key_green_choice = self.ADD_TIMER
                        print "Timeredit aborted"
+       
+       def finishSanityCorrection(self, answer):
+               self.finishedAdd(answer)
 
        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_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):
+               self.updateTimelineTimer.start((60-(int(time())%60))*1000)      #keep syncronised
                l = self["list"]
                event_rect = l.getEventRect()
                time_epoch = l.getTimeEpoch()
@@ -530,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
+               
                num_lines = time_epoch/time_steps
                incWidth=event_rect.width()/num_lines
                pos=event_rect.left()
@@ -557,8 +699,7 @@ class GraphMultiEPG(Screen):
                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:
@@ -566,3 +707,6 @@ class GraphMultiEPG(Screen):
                        timeline_now.visible = True
                else:
                        timeline_now.visible = False
+               # here no l.l.invalidate() is needed when the zPosition in the skin is correct!
+
+