enigma2 20131001 (master) -> 20131112 (master)
[enigma2.git] / usr / lib / enigma2 / python / Components / ServiceList.py
1 from HTMLComponent import HTMLComponent
2 from GUIComponent import GUIComponent
3 from skin import parseColor, parseFont
4 from enigma import eListbox, eRect, eEnv
5 from Tools.LoadPixmap import LoadPixmap
6 from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN, fileExists
7 from Components.config import config
8 from enigma import RT_WRAP, RT_VALIGN_CENTER, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, gFont, eListbox, eServiceReference, eServiceCenter, iServiceInformation, eListboxPythonMultiContent, eListboxServiceContent, eEPGCache
9 from ServiceReference import ServiceReference
10 from Components.MultiContent import MultiContentEntryText
11 from time import time
12 from enigma import eLabel, eSize, eEnv, eServiceReference
13 from skin import TemplatedColors
14 import NavigationInstance
15 from time import localtime
16 from timer import TimerEntry
17 from re import compile
18
19 class PiconLoader():
20         def __init__(self):
21                 self.nameCache = { }
22                 config.usage.configselection_piconspath.addNotifier(self.piconPathChanged, initial_call = False)
23                 self.partnerbox = compile('1:0:[0-9a-fA-F]+:[1-9a-fA-F]+[0-9a-fA-F]*:[1-9a-fA-F]+[0-9a-fA-F]*:[1-9a-fA-F]+[0-9a-fA-F]*:[1-9a-fA-F]+[0-9a-fA-F]*:[0-9a-fA-F]+:[0-9a-fA-F]+:[0-9a-fA-F]+:http')
24
25         def getPicon(self, sRef):
26                 pos = sRef.rfind(':')
27                 pos2 = sRef.rfind(':', 0, pos)
28                 if pos - pos2 == 1 or self.partnerbox.match(sRef) is not None:
29                         sRef = sRef[:pos2].replace(':', '_')
30                 else:
31                         sRef = sRef[:pos].replace(':', '_')
32                 pngname = self.nameCache.get(sRef, "")
33                 if pngname == "":
34                         pngname = self.findPicon(sRef)
35                         if pngname != "":
36                                 self.nameCache[sRef] = pngname
37                         if pngname == "": # no picon for service found
38                                 pngname = self.nameCache.get("default", "")
39                                 if pngname == "": # no default yet in cache..
40                                         pngname = self.findPicon("picon_default")
41                                         if pngname != "":
42                                                 self.nameCache["default"] = pngname
43                 if fileExists(pngname):
44                         return LoadPixmap(cached = True, path = pngname)
45                 else:
46                         return None
47
48         def findPicon(self, sRef):
49                 pngname = "%s%s.png" % (config.usage.configselection_piconspath.value, sRef)
50                 if not fileExists(pngname):
51                         pngname = ""
52                 return pngname
53
54         def piconPathChanged(self, configElement = None):
55                 self.nameCache.clear()
56
57 class ServiceList(HTMLComponent, GUIComponent):
58         MODE_NORMAL = 0
59         MODE_FAVOURITES = 1
60
61         def __init__(self, session = None):
62                 GUIComponent.__init__(self)
63
64                 self.session = session
65                 self.picFolder = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png"))
66                 self.picMarker = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/marker.png"))
67                 self.picDVB_S = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_s-fs8.png"))
68                 self.picDVB_C = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_c-fs8.png"))
69                 self.picDVB_T = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_t-fs8.png"))
70                 self.picServiceGroup = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_service_group-fs8.png"))
71                 self.markedForeground = 0xffffff
72                 self.markedBackground = 0xff0000
73                 self.markedForegroundSelected = 0xffffff
74                 self.markedBackgroundSelected = 0x800000
75
76                 colors = TemplatedColors().colors
77                 if "ListboxMarkedForeground" in colors:
78                         self.markedForeground = colors["ListboxMarkedForeground"]
79                 if "ListboxMarkedBackground" in colors:
80                         self.markedBackground = colors["ListboxMarkedBackground"]
81                 if "ListboxMarkedAndSelectedForeground" in colors:
82                         self.markedForegroundSelected = colors["ListboxMarkedAndSelectedForeground"]
83                 if "ListboxMarkedAndSelectedBackground" in colors:
84                         self.markedBackgroundSelected = colors["ListboxMarkedAndSelectedBackground"]
85
86                 self.serviceNotAvail = 0xbbbbbb
87                 self.serviceEventProgressbarColor = None
88                 self.serviceEventProgressbarColorSelected = None
89                 self.serviceEventProgressbarBackColor = None
90                 self.serviceEventProgressbarBackColorSelected = None
91                 self.serviceEventProgressbarBorderColor = None
92                 self.serviceEventProgressbarBorderColorSelected = None
93                 self.serviceDescriptionColor = 0xe7b53f
94                 self.serviceDescriptionColorSelected = 0xe7b53f
95                 self.recordingColor = 0xff4A3C
96                 self.recordingColorSelected = 0xff4A3C
97                 self.additionalInfoColor =  None
98                 self.additionalInfoColorSelected =  None
99                 self.picServiceEventProgressbar = None
100                 self.selectionPixmapStandard = None
101                 self.selectionPixmapBig = None
102                 self.l = eListboxServiceContent()
103                 self.l.setBuildFunc(self.buildOptionEntry, True)
104                 self.l.setFont(0, gFont("Regular", 18)) # AdditionalInfoFont
105                 self.l.setFont(1, gFont("Regular", 20)) # ServiceNumberFont
106                 self.l.setFont(2, gFont("Regular", 22)) # ServiceNameFont
107                 self.l.setFont(3, gFont("Regular", 18)) # ServiceInfoFont
108                 self.serviceNameFont = gFont("Regular", 22)
109                 self.serviceInfoFontHeight = 18
110                 self.additionalInfoFont = gFont("Regular", 18)
111                 self.list = []
112                 self.size = 0
113                 self.service_center = eServiceCenter.getInstance()
114                 self.numberoffset = 0
115                 self.is_playable_ignore = eServiceReference()
116                 self.root = None
117                 self.mode = self.MODE_NORMAL
118                 self.itemHeight = 28
119                 self.l.setItemHeight(28)
120                 self.onSelectionChanged = [ ]
121                 self.recordingList = {}
122                 self.piconLoader = PiconLoader()
123                 if self.session:
124                         self.session.nav.RecordTimer.on_state_change.append(self.onTimerEntryStateChange)
125                 config.usage.configselection_showrecordings.addNotifier(self.getRecordingList, initial_call = True)
126                 config.usage.configselection_bigpicons.addNotifier(self.setItemHeight, initial_call = True)
127
128         def getRecordingList(self,configElement = None):
129                 self.recordingList = {}
130                 if config.usage.configselection_showrecordings.value:
131                         if NavigationInstance.instance.getRecordings():
132                                 for timer in NavigationInstance.instance.RecordTimer.timer_list:
133                                         if timer.state == TimerEntry.StateRunning and not timer.justplay and hasattr(timer, "Filename"):
134                                                 self.recordingList[str(timer.service_ref)] = 1
135
136         def onTimerEntryStateChange(self,timer):
137                 if config.usage.configselection_showrecordings.value:
138                         if hasattr(timer, "Filename") and not timer.justplay and timer.state == TimerEntry.StateRunning:
139                                 self.recordingList[str(timer.service_ref)] = 1
140                         else:
141                                 if self.recordingList.has_key(str(timer.service_ref)):
142                                         del self.recordingList[str(timer.service_ref)]
143
144         def setItemHeight(self, configElement = None):
145                 if config.usage.configselection_bigpicons.value and self.mode == self.MODE_FAVOURITES:
146                         self.l.setItemHeight(60)
147                         if self.instance is not None and self.selectionPixmapBig:
148                                 self.instance.setSelectionPicture(self.selectionPixmapBig)
149                 else:
150                         self.l.setItemHeight(self.itemHeight)
151                         if self.instance is not None and self.selectionPixmapStandard:
152                                 self.instance.setSelectionPicture(self.selectionPixmapStandard)
153
154         def paintProgressBar(self, event, xoffset, width, height):
155                 percent = 0
156                 progressW = 52
157                 progressH = 8
158                 if event:
159                         now = int(time())
160                         percent = 100 * (now - event.getBeginTime()) / event.getDuration()
161                 top = int((height - progressH) / 2)
162                 if self.picServiceEventProgressbar is None:
163                         return(eListboxPythonMultiContent.TYPE_PROGRESS, xoffset, top, progressW, progressH, percent, 1, self.serviceEventProgressbarColor, self.serviceEventProgressbarColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected)
164                 else:
165                         return(eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, xoffset, top, progressW, progressH, percent, self.picServiceEventProgressbar, 1, self.serviceEventProgressbarBorderColor, self.serviceEventProgressbarBorderColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected)
166
167         def buildOptionEntry(self, service, **args):
168                 width = self.l.getItemSize().width()
169                 height = self.l.getItemSize().height()
170                 selected = args["selected"]
171                 res = [ None ]
172                 showListNumbers = config.usage.configselection_showlistnumbers.value
173                 showPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_showpicons.value
174                 showServiceName = self.mode == self.MODE_NORMAL or (self.mode == self.MODE_FAVOURITES and config.usage.configselection_showservicename.value)
175                 showProgressbar = config.usage.show_event_progress_in_servicelist.value
176                 progressbarPosition = config.usage.configselection_progressbarposition.value
177                 servicenameWidth = config.usage.configselection_servicenamecolwidth.value
178                 columnStyle = config.usage.configselection_columnstyle.value
179                 additionalposition = config.usage.configselection_additionaltimedisplayposition.value
180                 bigPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_bigpicons.value
181                 secondlineinfo = config.usage.configselection_secondlineinfo.value
182                 # get service information
183                 service_info = self.service_center.info(service)
184                 isMarker = service.flags & eServiceReference.isMarker
185                 isPlayable = not(service.flags & eServiceReference.isDirectory or isMarker)
186                 recording = False
187                 if config.usage.configselection_showrecordings.value:
188                         if self.recordingList.has_key(service.toString()):
189                                 recording = True
190                         else:
191                                 if isPlayable and len(self.recordingList) and service.flags & eServiceReference.mustDescent:
192                                         alist = ServiceReference(service).list()
193                                         while True:
194                                                 aservice = alist.getNext()
195                                                 if not aservice.valid():
196                                                         break
197                                                 if self.recordingList.has_key(aservice.toString()):
198                                                         recording = True
199                                                         break
200
201                 marked = 0
202                 if self.l.isCurrentMarked() and selected:
203                         marked = 2
204                 elif self.l.isMarked(service):
205                         if selected:
206                                 marked = 2
207                         else:
208                                 marked = 1
209                 if marked == 1: #  marked
210                         additionalInfoColor = serviceDescriptionColor = forgroundColor = self.markedForeground
211                         backgroundColor = self.markedBackground
212                         forgroundColorSel = backgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = None
213                 elif marked == 2: # marked and selected
214                         additionalInfoColorSelected = serviceDescriptionColorSelected = forgroundColorSel = self.markedForegroundSelected
215                         backgroundColorSel = self.markedBackgroundSelected
216                         forgroundColor = additionalInfoColor = serviceDescriptionColor = backgroundColor = None
217                 else:
218                         if recording:
219                                 forgroundColor = additionalInfoColor = serviceDescriptionColor = self.recordingColor
220                                 forgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = self.recordingColorSelected
221                                 backgroundColor = backgroundColorSel = None
222                         else:
223                                 forgroundColor = forgroundColorSel = backgroundColor = backgroundColorSel = None
224                                 serviceDescriptionColor = self.serviceDescriptionColor
225                                 serviceDescriptionColorSelected = self.serviceDescriptionColorSelected
226                                 additionalInfoColor = self.additionalInfoColor
227                                 additionalInfoColorSelected = self.additionalInfoColorSelected
228
229                 if (marked == 0 and isPlayable and service_info and self.is_playable_ignore.valid() and not service_info.isPlayable(service, self.is_playable_ignore)):
230                         forgroundColor = forgroundColorSel = additionalInfoColor = additionalInfoColorSelected = serviceDescriptionColor = serviceDescriptionColorSelected = self.serviceNotAvail
231
232                 # set windowstyle
233                 if marked > 0:
234                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width , height, 1, RT_HALIGN_RIGHT, "", forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
235
236                 info = self.service_center.info(service)
237                 serviceName = info.getName(service) or "<n/a>"
238                 event = info.getEvent(service)
239                 index = self.getCurrentIndex()
240                 xoffset = 2
241                 pixmap = None
242                 drawProgressbar = isPlayable and showProgressbar
243                 if service.flags & eServiceReference.isMarker:
244                         pixmap = self.picMarker
245                 elif service.flags & eServiceReference.isGroup:
246                         pixmap = self.picServiceGroup
247                 elif service.flags & eServiceReference.isDirectory:
248                         pixmap = self.picFolder
249                 else:
250                         orbpos = service.getUnsignedData(4) >> 16;
251                         if orbpos == 0xFFFF:
252                                 pixmap = self.picDVB_C
253                         elif orbpos == 0xEEEE:
254                                 pixmap = self.picDVB_T
255                         else:
256                                 pixmap = self.picDVB_S
257                 if pixmap is not None:
258                         pixmap_size = self.picMarker.size()
259                         ypos = (height - pixmap_size.height()) / 2
260                         pix_width = pixmap_size.width()
261                         res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, height, pixmap))
262                         xoffset += pix_width + 8
263
264                 if self.mode != self.MODE_NORMAL:
265                         # servicenumber
266                         if not (service.flags & eServiceReference.isMarker) and showListNumbers:
267                                 markers_before = self.l.getNumMarkersBeforeCurrent()
268                                 text = "%d" % (self.numberoffset + index + 1 - markers_before)
269                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, 50 , height, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
270                                 xoffset += 60
271                 # picons
272                 if isPlayable and showPicons:
273                         if service.flags & eServiceReference.mustDescent:
274                                 alist = ServiceReference(service).list()
275                                 first_in_alternative = alist and alist.getNext()
276                                 if first_in_alternative:
277                                         service_str = first_in_alternative.toString()
278                                 else:
279                                         service_str = service.toString()
280                         else:
281                                 service_str = service.toString()
282                         picon = self.piconLoader.getPicon(service_str)
283                         if picon:
284                                 pixmap_size = picon.size()
285                                 ypos = (height - pixmap_size.height()) / 2
286                                 pix_width = pixmap_size.width()
287                                 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, height, picon))
288                         if bigPicons:
289                                 xoffset += 108
290                         else:
291                                 xoffset += 58
292                 # progressbar between servicenumber and servicename
293                 if drawProgressbar and progressbarPosition == "0":
294                         res.append(self.paintProgressBar(event, xoffset, width, height))
295                         xoffset += 60
296                 addtimedisplay = ""
297                 addtimedisplayWidth = 0
298                 if config.usage.configselection_showadditionaltimedisplay.value != "0" and event and isPlayable:
299                         if columnStyle:
300                                 self.textRenderer.setFont(self.additionalInfoFont)
301                         if config.usage.configselection_showadditionaltimedisplay.value == "1": # percent
302                                 now = int(time())
303                                 percent = 100 * (now - event.getBeginTime()) / event.getDuration()
304                                 addtimedisplay = "%d%%" % percent
305                                 if columnStyle:
306                                         self.textRenderer.setText("100%")
307                         elif config.usage.configselection_showadditionaltimedisplay.value == "2": # remain
308                                 now = int(time())
309                                 remain =  int((event.getBeginTime() + event.getDuration() - now) / 60)
310                                 addtimedisplay = "+%d min" % remain
311                                 if columnStyle:
312                                         self.textRenderer.setText("+%d min" % 9999)
313                         elif config.usage.configselection_showadditionaltimedisplay.value == "3": # Remain / duration
314                                 now = int(time())
315                                 remain =  int((event.getBeginTime() + event.getDuration() - now) / 60)
316                                 duration = int(event.getDuration() / 60)
317                                 addtimedisplay = "+%d/%d min"  % (remain, duration)
318                                 if columnStyle:
319                                         self.textRenderer.setText("+%d/%d min"  % (9999, 9999))
320                         elif config.usage.configselection_showadditionaltimedisplay.value == "4": # elapsed
321                                 now = int(time())
322                                 elapsed =  int((now - event.getBeginTime()) / 60)
323                                 addtimedisplay = "%d min" % elapsed
324                                 if columnStyle:
325                                         self.textRenderer.setText("%d min" % 9999)
326                         elif config.usage.configselection_showadditionaltimedisplay.value == "5": # elapsed / duration
327                                 now = int(time())
328                                 elapsed =  int((now - event.getBeginTime()) / 60)
329                                 duration = int(event.getDuration() / 60)
330                                 addtimedisplay = "%d/%d min"  % (elapsed, duration)
331                                 if columnStyle:
332                                         self.textRenderer.setText("%d/%d min"  % (9999, 9999))
333                         elif config.usage.configselection_showadditionaltimedisplay.value == "6": # elapsed / remain /  duration
334                                 now = int(time())
335                                 elapsed =  int((now - event.getBeginTime()) / 60)
336                                 remain =  int((event.getBeginTime() + event.getDuration() - now) / 60)
337                                 duration = int(event.getDuration() / 60)
338                                 addtimedisplay = "%d/+%d/%d min"  % (elapsed, remain, duration)
339                                 if columnStyle:
340                                         self.textRenderer.setText("%d/+%d/%d min"  % (9999, 9999, 9999))
341                         elif config.usage.configselection_showadditionaltimedisplay.value == "7": #  begin - end time
342                                 beginTime = localtime(event.getBeginTime())
343                                 endTime = localtime(event.getBeginTime()+event.getDuration())
344                                 addtimedisplay = "%02d:%02d - %02d:%02d" % (beginTime[3],beginTime[4],endTime[3],endTime[4])
345                                 if columnStyle:
346                                         self.textRenderer.setText("00:00 - 00:000")
347                         if columnStyle:
348                                 addtimedisplayWidth = self.textRenderer.calculateSize().width()
349                 if columnStyle:
350                         rwidth = 0
351                         # servicename
352                         if (isPlayable and showServiceName) or not isPlayable:
353                                 if isPlayable:
354                                         rwidth = servicenameWidth # space for servicename
355                                 else:
356                                         rwidth = width - xoffset # space for servicename
357                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
358                                 xoffset = xoffset + rwidth + 10
359                                 # progressbar between servicename and service description
360                                 if drawProgressbar and progressbarPosition == "1":
361                                         res.append(self.paintProgressBar(event, xoffset, width, height))
362                                         xoffset += 60
363                         if event and isPlayable:
364                                 if addtimedisplay != "" and additionalposition == "1":
365                                         if drawProgressbar and progressbarPosition == "2":
366                                                 rwidth = width - xoffset - addtimedisplayWidth
367                                                 rwidth -= 60
368                                         else:
369                                                 rwidth = width - xoffset - addtimedisplayWidth
370                                 else:
371                                         rwidth = width-xoffset
372                                         if drawProgressbar and progressbarPosition == "2":
373                                                 rwidth -= 60
374                                 if addtimedisplay != "" and additionalposition == "0":
375                                         # add time text before service description
376                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth, height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel))
377                                         addoffset = addtimedisplayWidth + 10
378                                         xoffset += addoffset
379                                         rwidth -= addoffset
380                                 # service description
381                                 if bigPicons and secondlineinfo != "0":
382                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, self.serviceInfoFontHeight+6, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel))
383                                         if secondlineinfo == "1": # shortdescription
384                                                 text = event.getShortDescription()
385                                         else:
386                                                 event_next = eEPGCache.getInstance().lookupEventTime(service, -1, 1)
387                                                 if event_next:
388                                                         beginTime = localtime(event_next.getBeginTime())
389                                                         endTime = localtime(event_next.getBeginTime()+event_next.getDuration())
390                                                         text = "%02d:%02d - %02d:%02d %s" % (beginTime[3],beginTime[4],endTime[3],endTime[4], event_next.getEventName())
391                                                 else:
392                                                         text = "%s: n/a" % _("upcoming event")
393                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, self.serviceInfoFontHeight+6, rwidth, height - (self.serviceInfoFontHeight+6), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel))
394                                 else:
395                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel))
396                                 # progressbar after service description
397                                 if drawProgressbar and progressbarPosition == "2":
398                                         xoffset = xoffset + rwidth + 5
399                                         res.append(self.paintProgressBar(event, xoffset, width, height))
400                                         xoffset += 60
401                                 elif addtimedisplay != "":
402                                         xoffset = xoffset + rwidth
403                                 # add time text at last position
404                                 if addtimedisplay != "" and additionalposition == "1":
405                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width-xoffset , height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel))
406                 else:
407                         if event and isPlayable:
408                                 self.textRenderer.setFont(self.serviceNameFont)
409                                 self.textRenderer.setText(serviceName)
410                                 length = self.textRenderer.calculateSize().width() + 10
411                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
412                                 xoffset += length
413                                 if addtimedisplay != "":
414                                         if additionalposition == "1":
415                                                 # add time text after service description
416                                                 text = "(%s %s)" % (event.getEventName(), addtimedisplay)
417                                         else:
418                                                 # add time text before service description
419                                                 text = "(%s %s)" % (addtimedisplay, event.getEventName())
420                                 else:
421                                         text = "(%s)" % (event.getEventName())
422                                 if drawProgressbar and progressbarPosition == "2":
423                                         # progressbar after service description
424                                         length = width-xoffset - 60
425                                 else:
426                                         length = width-xoffset
427                                 # service description
428                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel))
429                                 if drawProgressbar and progressbarPosition == "2":
430                                         xoffset += length + 5
431                                         res.append(self.paintProgressBar(event, xoffset, width, height))
432                         else:
433                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width - xoffset , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
434                 return res
435
436         def applySkin(self, desktop, parent):
437                 attribs = [ ]
438                 for (attrib, value) in self.skinAttributes:
439                         if attrib == "foregroundColorMarked":
440                                 self.markedForeground = parseColor(value).argb()
441                         elif attrib == "foregroundColorMarkedSelected":
442                                 self.markedForegroundSelected = parseColor(value).argb()
443                         elif attrib == "backgroundColorMarked":
444                                 self.markedBackground = parseColor(value).argb()
445                         elif attrib == "backgroundColorMarkedSelected":
446                                 self.markedBackgroundSelected = parseColor(value).argb()
447                         elif attrib == "foregroundColorServiceNotAvail":
448                                 self.serviceNotAvail = parseColor(value).argb()
449                         elif attrib == "colorEventProgressbar":
450                                 self.serviceEventProgressbarColor = parseColor(value).argb()
451                         elif attrib == "colorEventProgressbarSelected":
452                                 self.serviceEventProgressbarColorSelected = parseColor(value).argb()
453                         elif attrib == "forgroundColorEventProgressbarBorder":
454                                 self.serviceEventProgressbarBackColor = parseColor(value).argb()
455                         elif attrib == "backgroundColorEventProgressbarBorderSelected":
456                                 self.serviceEventProgressbarBackColorSelected = parseColor(value).argb()
457                         elif attrib == "colorEventProgressbarBorder":
458                                 self.serviceEventProgressbarBorderColor = parseColor(value).argb()
459                         elif attrib == "colorEventProgressbarBorderSelected":
460                                 self.serviceEventProgressbarBorderColorSelected = parseColor(value).argb()
461                         elif attrib == "colorServiceDescription":
462                                 self.serviceDescriptionColor = parseColor(value).argb()
463                         elif attrib == "colorServiceDescriptionSelected":
464                                 self.serviceDescriptionColorSelected = parseColor(value).argb()
465                         elif attrib == "colorRecording":
466                                 self.recordingColor = parseColor(value).argb()
467                         elif attrib == "colorRecordingSelected":
468                                 self.recordingColorSelected = parseColor(value).argb()
469                         elif attrib == "colorAdditionalInfo":
470                                 self.additionalInfoColor = parseColor(value).argb()
471                         elif attrib == "colorAdditionalInfoSelected":
472                                 self.additionalInfoColorSelected = parseColor(value).argb()
473                         elif attrib == "picServiceEventProgressbar":
474                                 pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value))
475                                 if pic:
476                                         self.picServiceEventProgressbar = pic
477                         elif attrib == "serviceItemHeight":
478                                 self.itemHeight = int(value)
479                         elif attrib == "serviceNameFont":
480                                 self.l.setFont(2, parseFont(value, ((1,1),(1,1))))
481                                 self.serviceNameFont = parseFont(value, ((1,1),(1,1)))
482                         elif attrib == "serviceInfoFont":
483                                 self.l.setFont(3, parseFont(value, ((1,1),(1,1))))
484                                 name, size = value.split(';')
485                                 self.serviceInfoFontHeight = int(size)
486                         elif attrib == "serviceNumberFont":
487                                 self.l.setFont(1, parseFont(value, ((1,1),(1,1))))
488                         elif attrib == "additionalInfoFont":
489                                 self.l.setFont(0, parseFont(value, ((1,1),(1,1))))
490                                 self.additionalInfoFont = parseFont(value, ((1,1),(1,1)))
491                         elif attrib == "selectionPixmap":
492                                 pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value))
493                                 if pic:
494                                         self.selectionPixmapStandard = pic
495                                         if not config.usage.configselection_bigpicons.value:
496                                                 self.instance.setSelectionPicture(self.selectionPixmapStandard)
497                         elif attrib == "selectionPixmapHigh":
498                                 pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value))
499                                 if pic:
500                                         self.selectionPixmapBig = pic
501                                         if config.usage.configselection_bigpicons.value:
502                                                 self.instance.setSelectionPicture(self.selectionPixmapBig)
503                         else:
504                                 attribs.append((attrib, value))
505                 self.skinAttributes = attribs
506                 return GUIComponent.applySkin(self, desktop, parent)
507
508         def connectSelChanged(self, fnc):
509                 if not fnc in self.onSelectionChanged:
510                         self.onSelectionChanged.append(fnc)
511
512         def disconnectSelChanged(self, fnc):
513                 if fnc in self.onSelectionChanged:
514                         self.onSelectionChanged.remove(fnc)
515
516         def selectionChanged(self):
517                 for x in self.onSelectionChanged:
518                         x()
519
520         def setCurrent(self, ref):
521                 self.l.setCurrent(ref)
522
523         def getCurrent(self):
524                 r = eServiceReference()
525                 self.l.getCurrent(r)
526                 return r
527
528         def atBegin(self):
529                 return self.instance.atBegin()
530
531         def atEnd(self):
532                 return self.instance.atEnd()
533
534         def moveUp(self):
535                 self.instance.moveSelection(self.instance.moveUp)
536
537         def moveDown(self):
538                 self.instance.moveSelection(self.instance.moveDown)
539
540         def moveToChar(self, char):
541                 print "Next char: ", char
542                 index = self.l.getNextBeginningWithChar(char)
543                 indexup = self.l.getNextBeginningWithChar(char.upper())
544                 if indexup != 0:
545                         if (index > indexup or index == 0):
546                                 index = indexup
547
548                 self.instance.moveSelectionTo(index)
549                 print "Moving to character " + str(char)
550
551         def moveToNextMarker(self):
552                 idx = self.l.getNextMarkerPos()
553                 self.instance.moveSelectionTo(idx)
554
555         def moveToPrevMarker(self):
556                 idx = self.l.getPrevMarkerPos()
557                 self.instance.moveSelectionTo(idx)
558
559         def moveToIndex(self, index):
560                 self.instance.moveSelectionTo(index)
561
562         def getCurrentIndex(self):
563                 return self.instance.getCurrentIndex()
564
565         GUI_WIDGET = eListbox
566
567         def postWidgetCreate(self, instance):
568                 instance.setWrapAround(True)
569                 instance.setContent(self.l)
570                 instance.selectionChanged.get().append(self.selectionChanged)
571                 self.setMode(self.mode)
572                 self.textRenderer = eLabel(self.instance)
573                 self.textRenderer.resize(eSize(400,0))
574                 self.textRenderer.hide()
575
576         def preWidgetRemove(self, instance):
577                 if self.session:
578                         self.session.nav.RecordTimer.on_state_change.remove(self.onTimerEntryStateChange)
579                 instance.setContent(None)
580                 instance.selectionChanged.get().remove(self.selectionChanged)
581                 config.usage.configselection_showrecordings.removeNotifier(self.getRecordingList)
582
583         def getRoot(self):
584                 return self.root
585
586         def getRootServices(self):
587                 serviceHandler = eServiceCenter.getInstance()
588                 list = serviceHandler.list(self.root)
589                 dest = [ ]
590                 if list is not None:
591                         while 1:
592                                 s = list.getNext()
593                                 if s.valid():
594                                         dest.append(s.toString())
595                                 else:
596                                         break
597                 return dest
598
599         def setNumberOffset(self, offset):
600                 self.numberoffset = offset
601
602         def setPlayableIgnoreService(self, ref):
603                 self.is_playable_ignore = ref
604
605         def setRoot(self, root, justSet=False):
606                 self.root = root
607                 self.l.setRoot(root, justSet)
608                 if not justSet:
609                         self.l.sort()
610                 self.selectionChanged()
611
612         def removeCurrent(self):
613                 self.l.removeCurrent()
614
615         def addService(self, service, beforeCurrent=False):
616                 self.l.addService(service, beforeCurrent)
617
618         def finishFill(self):
619                 self.l.FillFinished()
620                 self.l.sort()
621
622 # stuff for multiple marks (edit mode / later multiepg)
623         def clearMarks(self):
624                 self.l.initMarked()
625
626         def isMarked(self, ref):
627                 return self.l.isMarked(ref)
628
629         def addMarked(self, ref):
630                 self.l.addMarked(ref)
631
632         def removeMarked(self, ref):
633                 self.l.removeMarked(ref)
634
635         def getMarked(self):
636                 i = self.l
637                 i.markedQueryStart()
638                 ref = eServiceReference()
639                 marked = [ ]
640                 while i.markedQueryNext(ref) == 0:
641                         marked.append(ref.toString())
642                         ref = eServiceReference()
643                 return marked
644
645 #just for movemode.. only one marked entry..
646         def setCurrentMarked(self, state):
647                 self.l.setCurrentMarked(state)
648
649         def setMode(self, mode):
650                 self.mode = mode
651                 self.setItemHeight()