fix findBestEvent function
[enigma2.git] / lib / python / Plugins / Extensions / GraphMultiEPG / GraphMultiEpg.py
index d8c654bc3972426f0d9fb3943d6f2b4ba2692254..45a5139bce6cb18cade5630e05ffd39d39edd11c 100644 (file)
@@ -1,20 +1,23 @@
+from skin import parseColor
 from Components.config import config, ConfigClock, ConfigInteger
 from Components.config import config, ConfigClock, ConfigInteger
-from Components.Button import Button
 from Components.Pixmap import Pixmap
 from Components.Pixmap import Pixmap
+from Components.Button import Button
 from Components.ActionMap import ActionMap
 from Components.HTMLComponent import HTMLComponent
 from Components.GUIComponent import GUIComponent
 from Components.EpgList import Rect
 from Components.Sources.Event import Event
 from Components.ActionMap import ActionMap
 from Components.HTMLComponent import HTMLComponent
 from Components.GUIComponent import GUIComponent
 from Components.EpgList import Rect
 from Components.Sources.Event import Event
-from Components.Sources.Clock import Clock
+from Components.Sources.Source import ObsoleteSource
+from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
 from Screens.Screen import Screen
 from Screens.EventView import EventViewSimple
 from Screens.TimeDateInput import TimeDateInput
 from Screens.TimerEntry import TimerEntry
 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 ServiceReference import ServiceReference
 from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE
 from RecordTimer import RecordTimerEntry, parseEvent
 from ServiceReference import ServiceReference
-from enigma import eEPGCache, eListbox, eListboxPythonMultiContent, gFont, loadPNG, \
+from enigma import eEPGCache, eListbox, gFont, loadPNG, 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
@@ -39,7 +42,32 @@ class EPGList(HTMLComponent, GUIComponent):
                self.time_base = None
                self.time_epoch = time_epoch
                self.list = None
                self.time_base = None
                self.time_epoch = time_epoch
                self.list = None
-               self.entry_rect = None
+               self.event_rect = None
+
+               self.foreColor = None
+               self.foreColorSelected = None
+               self.borderColor = None
+               self.backColor = 0x586d88
+               self.backColorSelected = 0x808080
+
+       def applySkin(self, desktop):
+               if self.skinAttributes is not None:
+                       attribs = [ ]
+                       for (attrib, value) in self.skinAttributes:
+                               if attrib == "EntryForegroundColor":
+                                       self.foreColor = parseColor(value).argb()
+                               elif attrib == "EntryForegroundColorSelected":
+                                       self.foreColorSelected = parseColor(value).argb()
+                               elif attrib == "EntryBorderColor":
+                                       self.borderColor = parseColor(value).argb()
+                               elif attrib == "EntryBackgroundColor":
+                                       self.backColor = parseColor(value).argb()
+                               elif attrib == "EntryBackgroundColorSelected":
+                                       self.backColorSelected = parseColor(value).argb()
+                               else:
+                                       attribs.append((attrib,value))
+                       self.skinAttributes = attribs
+               return GUIComponent.applySkin(self, desktop)
 
        def isSelectable(self, service, sname, event_list):
                return (event_list and len(event_list) and True) or False
 
        def isSelectable(self, service, sname, event_list):
                return (event_list and len(event_list) and True) or False
@@ -86,10 +114,13 @@ class EPGList(HTMLComponent, GUIComponent):
                old_service = self.cur_service  #(service, service_name, events)
                cur_service = self.cur_service = self.l.getCurrentSelection()
                last_time = 0;
                old_service = self.cur_service  #(service, service_name, events)
                cur_service = self.cur_service = self.l.getCurrentSelection()
                last_time = 0;
+               time_base = self.getTimeBase()
                if old_service and self.cur_event is not None:
                        events = old_service[2]
                        cur_event = events[self.cur_event] #(event_id, event_title, begin_time, duration)
                        last_time = cur_event[2]
                if old_service and self.cur_event is not None:
                        events = old_service[2]
                        cur_event = events[self.cur_event] #(event_id, event_title, begin_time, duration)
                        last_time = cur_event[2]
+                       if last_time < time_base:
+                               last_time = time_base
                if cur_service:
                        self.cur_event = 0
                        events = cur_service[2]
                if cur_service:
                        self.cur_event = 0
                        events = cur_service[2]
@@ -99,7 +130,10 @@ class EPGList(HTMLComponent, GUIComponent):
                                        best = len(events) #set invalid
                                        idx = 0
                                        for event in events: #iterate all events
                                        best = len(events) #set invalid
                                        idx = 0
                                        for event in events: #iterate all events
-                                               diff = abs(event[2]-last_time)
+                                               ev_time = event[2]
+                                               if ev_time < time_base:
+                                                       ev_time = time_base
+                                               diff = abs(ev_time-last_time)
                                                if (best == len(events)) or (diff < best_diff):
                                                        best = idx
                                                        best_diff = diff
                                                if (best == len(events)) or (diff < best_diff):
                                                        best = idx
                                                        best_diff = diff
@@ -138,7 +172,7 @@ class EPGList(HTMLComponent, GUIComponent):
                xpos += w;
                w = width/10*8;
                self.event_rect = Rect(xpos, 0, w, height)
                xpos += w;
                w = width/10*8;
                self.event_rect = Rect(xpos, 0, w, height)
-               self.l.setSelectionClip(eRect(xpos, 0, w, height), False)
+               self.l.setSelectionClip(eRect(0,0,0,0), False)
 
        def calcEntryPosAndWidthHelper(self, stime, duration, start, end, width):
                xpos = (stime - start) * width / (end - start)
 
        def calcEntryPosAndWidthHelper(self, stime, duration, start, end, width):
                xpos = (stime - start) * width / (end - start)
@@ -158,54 +192,60 @@ 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 ] # no private data needed
-               res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, service_name))
-               start = self.time_base+self.offs*self.time_epoch*60
-               end = start + self.time_epoch * 60
-               left = r2.left()
-               top = r2.top()
-               width = r2.width()
-               height = r2.height()
+               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) ]
+
                if events:
                if events:
+                       start = self.time_base+self.offs*self.time_epoch*60
+                       end = start + self.time_epoch * 60
+                       left = r2.left()
+                       top = r2.top()
+                       width = r2.width()
+                       height = r2.height()
+                       foreColor = self.foreColor
+                       foreColorSelected = self.foreColorSelected
+                       backColor = self.backColor
+                       backColorSelected = self.backColorSelected
+                       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)
                                xpos, ewidth = self.calcEntryPosAndWidthHelper(ev[2], ev[3], start, end, width)
                        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)
                                xpos, ewidth = self.calcEntryPosAndWidthHelper(ev[2], ev[3], start, end, width)
-                               res.append((eListboxPythonMultiContent.TYPE_TEXT, left+xpos, top, ewidth, height, 1, RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, ev[1], None, 0x586d88, 0x808080, 1))
+                               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((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, left+xpos+ewidth-22, top+height-22, 21, 21, self.clock_pixmap, 0x586d88, 0x808080))
+                                       res.append(MultiContentEntryPixmapAlphaTest(pos = (left+xpos+ewidth-22, top+height-22), size = (21, 21), png = self.clock_pixmap, backcolor = backColor, backcolor_selected = backColorSelected))
                return res
 
                return res
 
-       def selEntry(self, dir):
+       def selEntry(self, dir, visible=True):
                cur_service = self.cur_service #(service, service_name, events)
                cur_service = self.cur_service #(service, service_name, events)
-               if not self.entry_rect:
+               if not self.event_rect:
                        self.recalcEntrySize()
                if cur_service and self.cur_event is not None:
                        update = True
                        entries = cur_service[2]
                        if dir == 0: #current
                                update = False
                        self.recalcEntrySize()
                if cur_service and self.cur_event is not None:
                        update = True
                        entries = cur_service[2]
                        if dir == 0: #current
                                update = False
-                               pass
                        elif dir == +1: #next
                                if self.cur_event+1 < len(entries):
                                        self.cur_event+=1
                                else:
                                        self.offs += 1
                                        self.fillMultiEPG(None) # refill
                        elif dir == +1: #next
                                if self.cur_event+1 < len(entries):
                                        self.cur_event+=1
                                else:
                                        self.offs += 1
                                        self.fillMultiEPG(None) # refill
-                                       return
+                                       return True
                        elif dir == -1: #prev
                                if self.cur_event-1 >= 0:
                                        self.cur_event-=1
                                elif self.offs > 0:
                                        self.offs -= 1
                                        self.fillMultiEPG(None) # refill
                        elif dir == -1: #prev
                                if self.cur_event-1 >= 0:
                                        self.cur_event-=1
                                elif self.offs > 0:
                                        self.offs -= 1
                                        self.fillMultiEPG(None) # refill
-                                       return
+                                       return True
                        entry = entries[self.cur_event] #(event_id, event_title, begin_time, duration)
                        time_base = self.time_base+self.offs*self.time_epoch*60
                        xpos, width = self.calcEntryPosAndWidth(self.event_rect, time_base, self.time_epoch, entry[2], entry[3])
                        entry = entries[self.cur_event] #(event_id, event_title, begin_time, duration)
                        time_base = self.time_base+self.offs*self.time_epoch*60
                        xpos, width = self.calcEntryPosAndWidth(self.event_rect, time_base, self.time_epoch, entry[2], entry[3])
-                       self.l.setSelectionClip(eRect(xpos, 0, width, self.event_rect.height()), update)
+                       self.l.setSelectionClip(eRect(xpos, 0, width, self.event_rect.height()), visible and update)
                else:
                        self.l.setSelectionClip(eRect(self.event_rect.left(), self.event_rect.top(), self.event_rect.width(), self.event_rect.height()), False)
                self.selectionChanged()
                else:
                        self.l.setSelectionClip(eRect(self.event_rect.left(), self.event_rect.top(), self.event_rect.width(), self.event_rect.height()), False)
                self.selectionChanged()
+               return False
 
        def queryEPG(self, list, buildFunc=None):
                if self.epgcache is not None:
 
        def queryEPG(self, list, buildFunc=None):
                if self.epgcache is not None:
@@ -246,13 +286,17 @@ class EPGList(HTMLComponent, GUIComponent):
                self.findBestEvent()
 
        def getEventRect(self):
                self.findBestEvent()
 
        def getEventRect(self):
-               return self.event_rect
+               rc = self.event_rect
+               return Rect( rc.left() + (self.instance and self.instance.position().x() or 0), rc.top(), rc.width(), rc.height() )
 
        def getTimeEpoch(self):
                return self.time_epoch
 
        def getTimeBase(self):
 
        def getTimeEpoch(self):
                return self.time_epoch
 
        def getTimeBase(self):
-               return self.time_base
+               return self.time_base + (self.offs * self.time_epoch * 60)
+
+       def resetOffset(self):
+               self.offs = 0
 
 class TimelineText(HTMLComponent, GUIComponent):
        def __init__(self):
 
 class TimelineText(HTMLComponent, GUIComponent):
        def __init__(self):
@@ -291,7 +335,7 @@ class GraphMultiEPG(Screen):
                self["key_green"] = Button(_("Add timer"))
                self["timeline_text"] = TimelineText()
                self["Event"] = Event()
                self["key_green"] = Button(_("Add timer"))
                self["timeline_text"] = TimelineText()
                self["Event"] = Event()
-               self["Clock"] = Clock()
+               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()
@@ -318,8 +362,8 @@ class GraphMultiEPG(Screen):
 
                self["input_actions"] = ActionMap(["InputActions"],
                        {
 
                self["input_actions"] = ActionMap(["InputActions"],
                        {
-                               "left": self.prevEvent,
-                               "right": self.nextEvent,
+                               "left": self.leftPressed,
+                               "right": self.rightPressed,
                                "1": self.key1,
                                "2": self.key2,
                                "3": self.key3,
                                "1": self.key1,
                                "2": self.key2,
                                "3": self.key3,
@@ -332,11 +376,21 @@ class GraphMultiEPG(Screen):
                self.updateTimelineTimer.start(60*1000)
                self.onLayoutFinish.append(self.onCreate)
 
                self.updateTimelineTimer.start(60*1000)
                self.onLayoutFinish.append(self.onCreate)
 
-       def nextEvent(self):
-               self["list"].selEntry(+1)
+       def leftPressed(self):
+               self.prevEvent()
+
+       def rightPressed(self):
+               self.nextEvent()
+
+       def nextEvent(self, visible=True):
+               ret = self["list"].selEntry(+1, visible)
+               if ret:
+                       self.moveTimeLines(True)
 
 
-       def prevEvent(self):
-               self["list"].selEntry(-1)
+       def prevEvent(self, visible=True):
+               ret = self["list"].selEntry(-1, visible)
+               if ret:
+                       self.moveTimeLines(True)
 
        def key1(self):
                self["list"].setEpoch(60)
 
        def key1(self):
                self["list"].setEpoch(60)
@@ -378,8 +432,10 @@ class GraphMultiEPG(Screen):
                if len(ret) > 1:
                        if ret[0]:
                                self.ask_time=ret[1]
                if len(ret) > 1:
                        if ret[0]:
                                self.ask_time=ret[1]
-                               self["list"].fillMultiEPG(self.services, ret[1])
-                               self.moveTimeLines()
+                               l = self["list"]
+                               l.resetOffset()
+                               l.fillMultiEPG(self.services, ret[1])
+                               self.moveTimeLines(True)
 
        def closeScreen(self):
                self.close(self.closeRecursive)
 
        def closeScreen(self):
                self.close(self.closeRecursive)
@@ -407,9 +463,9 @@ class GraphMultiEPG(Screen):
                l = self["list"]
                old = l.getCurrent()
                if val == -1:
                l = self["list"]
                old = l.getCurrent()
                if val == -1:
-                       l.selEntry(-1)
+                       self.prevEvent(False)
                elif val == +1:
                elif val == +1:
-                       self.selEntry(+1)
+                       self.nextEvent(False)
                cur = l.getCurrent()
                if cur[0] is None and cur[1].ref != old[1].ref:
                        self.eventViewCallback(setEvent, setService, val)
                cur = l.getCurrent()
                if cur[0] is None and cur[1].ref != old[1].ref:
                        self.eventViewCallback(setEvent, setService, val)
@@ -454,7 +510,7 @@ class GraphMultiEPG(Screen):
                        else:
                                self["key_red"].setText("")
 
                        else:
                                self["key_red"].setText("")
 
-       def moveTimeLines(self):
+       def moveTimeLines(self, force=False):
                l = self["list"]
                event_rect = l.getEventRect()
                time_epoch = l.getTimeEpoch()
                l = self["list"]
                event_rect = l.getEventRect()
                time_epoch = l.getTimeEpoch()
@@ -483,7 +539,7 @@ class GraphMultiEPG(Screen):
                        x += 1
                        pos += incWidth
 
                        x += 1
                        pos += incWidth
 
-               if changecount:
+               if changecount or force:
                        self["timeline_text"].setEntries(timeline_entries)
 
                now=time()
                        self["timeline_text"].setEntries(timeline_entries)
 
                now=time()