1 from GUIComponent import GUIComponent
2 from Tools.FuzzyDate import FuzzyTime
3 from ServiceReference import ServiceReference
4 from Components.MultiContent import MultiContentEntryText
5 from Components.config import config
7 from enigma import eListboxPythonMultiContent, eListbox, gFont, iServiceInformation, \
8 RT_HALIGN_LEFT, RT_HALIGN_RIGHT, eServiceReference, eServiceCenter
10 class MovieList(GUIComponent):
15 LISTTYPE_COMPACT_DESCRIPTION = 2
22 def __init__(self, root, list_type=None, sort_type=None, descr_state=None):
23 GUIComponent.__init__(self)
24 self.list_type = list_type or self.LISTTYPE_ORIGINAL
25 self.descr_state = descr_state or self.HIDE_DESCRIPTION
26 self.sort_type = sort_type or self.SORT_RECORDED
28 self.fontName = "Regular"
29 self.fontSizesOriginal = (22,18,16)
30 self.fontSizesCompact = (20,14)
31 self.fontSizesMinimal = (20,16)
32 self.itemHeights = (75,37,25)
33 self.columnsOriginal = (180,200)
34 self.columnsCompactDescription = (120,154,58)
35 self.compactColumn = (75,200)
37 self.l = eListboxPythonMultiContent()
44 self.l.setBuildFunc(self.buildMovieListEntry)
46 self.onSelectionChanged = [ ]
48 def connectSelChanged(self, fnc):
49 if not fnc in self.onSelectionChanged:
50 self.onSelectionChanged.append(fnc)
52 def disconnectSelChanged(self, fnc):
53 if fnc in self.onSelectionChanged:
54 self.onSelectionChanged.remove(fnc)
56 def selectionChanged(self):
57 for x in self.onSelectionChanged:
60 def setListType(self, type):
63 def setDescriptionState(self, val):
64 self.descr_state = val
66 def setSortType(self, type):
69 def applySkin(self, desktop, parent):
70 def warningWrongSkinParameter(string):
71 print "[MovieList] wrong '%s' skin parameters" % string
74 def fontSizesOriginal(value):
75 self.fontSizesOriginal = map(int, value.split(","))
76 if len(self.fontSizesOriginal) != 3:
77 warningWrongSkinParameter(attrib)
78 def fontSizesCompact(value):
79 self.fontSizesCompact = map(int, value.split(","))
80 if len(self.fontSizesCompact) != 2:
81 warningWrongSkinParameter(attrib)
82 def fontSizesMinimal(value):
83 self.fontSizesMinimal = map(int, value.split(","))
84 if len(self.fontSizesMinimal) != 2:
85 warningWrongSkinParameter(attrib)
86 def itemHeights(value):
87 self.itemHeights = map(int, value.split(","))
88 if len(self.itemHeights) != 3:
89 warningWrongSkinParameter(attrib)
90 def columnsOriginal(value):
91 self.columnsOriginal = map(int, value.split(","))
92 if len(self.columnsOriginal) != 2:
93 warningWrongSkinParameter(attrib)
94 def columnsCompactDescription(value):
95 self.columnsCompactDescription = map(int, value.split(","))
96 if len(self.columnsCompactDescription) != 3:
97 warningWrongSkinParameter(attrib)
98 def compactColumn(value):
99 self.compactColumn = map(int, value.split(","))
100 if len(self.compactColumn) != 2:
101 warningWrongSkinParameter(attrib)
102 for (attrib, value) in self.skinAttributes[:]:
104 locals().get(attrib)(value)
105 self.skinAttributes.remove((attrib, value))
109 return GUIComponent.applySkin(self, desktop, parent)
111 def redrawList(self):
112 if self.list_type == MovieList.LISTTYPE_ORIGINAL:
114 self.l.setFont(i, gFont(self.fontName, self.fontSizesOriginal[i]))
115 self.itemHeight = self.itemHeights[0]
116 elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION or self.list_type == MovieList.LISTTYPE_COMPACT:
117 self.l.setItemHeight(37)
119 self.l.setFont(i, gFont(self.fontName, self.fontSizesCompact[i]))
120 self.itemHeight = self.itemHeights[1]
123 self.l.setFont(i, gFont(self.fontName, self.fontSizesMinimal[i]))
124 self.itemHeight = self.itemHeights[2]
125 self.l.setItemHeight(self.itemHeight)
130 def buildMovieListEntry(self, serviceref, info, begin, len):
131 if serviceref.flags & eServiceReference.mustDescent:
134 width = self.l.getItemSize().width()
136 if len <= 0: #recalc len when not already done
137 cur_idx = self.l.getCurrentSelectionIndex()
138 x = self.list[cur_idx]
139 if config.usage.load_length_of_movies_in_moviellist.value:
140 len = x[1].getLength(x[0]) #recalc the movie length...
142 len = 0 #dont recalc movielist to speedup loading the list
143 self.list[cur_idx] = (x[0], x[1], x[2], len) #update entry in list... so next time we don't need to recalc
146 len = "%d:%02d" % (len / 60, len % 60)
152 txt = info.getName(serviceref)
153 service = ServiceReference(info.getInfoString(serviceref, iServiceInformation.sServiceref))
154 description = info.getInfoString(serviceref, iServiceInformation.sDescription)
155 tags = info.getInfoString(serviceref, iServiceInformation.sTags)
160 begin_string = t[0] + ", " + t[1]
162 if self.list_type == MovieList.LISTTYPE_ORIGINAL:
163 fc, sc = self.columnsOriginal[0], self.columnsOriginal[1]
164 ih1 = (ih * 2) / 5 # 75 -> 30
165 ih2 = (ih * 2) / 3 # 75 -> 50
166 res.append(MultiContentEntryText(pos=(0, 0), size=(width-fc-2, ih1), font = 0, flags = RT_HALIGN_LEFT, text=txt))
168 res.append(MultiContentEntryText(pos=(width-fc, 0), size=(fc, ih1), font = 2, flags = RT_HALIGN_RIGHT, text = tags))
169 if service is not None:
170 res.append(MultiContentEntryText(pos=(sc, ih2), size=(sc, ih2-ih1), font = 1, flags = RT_HALIGN_LEFT, text = service.getServiceName()))
172 if service is not None:
173 res.append(MultiContentEntryText(pos=(width-fc, 0), size=(fc, ih1), font = 2, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
174 res.append(MultiContentEntryText(pos=(0, ih1), size=(width, ih2-ih1), font=1, flags=RT_HALIGN_LEFT, text=description))
175 res.append(MultiContentEntryText(pos=(0, ih2), size=(sc, ih2-ih1), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
176 res.append(MultiContentEntryText(pos=(width-sc, ih2), size=(sc-2, ih2-ih1), font=1, flags=RT_HALIGN_RIGHT, text=len))
177 elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION:
178 ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up
179 fc, sc, lc = self.columnsCompactDescription[0], self.columnsCompactDescription[1], self.columnsCompactDescription[2]
180 res.append(MultiContentEntryText(pos=(0, 0), size=(width-fc, ih1), font = 0, flags = RT_HALIGN_LEFT, text = txt))
181 res.append(MultiContentEntryText(pos=(0, ih1), size=(width-sc-lc, ih-ih1), font=1, flags=RT_HALIGN_LEFT, text=description))
182 res.append(MultiContentEntryText(pos=(width-fc, 6), size=(fc, ih1), font=1, flags=RT_HALIGN_RIGHT, text=begin_string))
183 if service is not None:
184 res.append(MultiContentEntryText(pos=(width-sc-lc, ih1), size=(sc, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
185 res.append(MultiContentEntryText(pos=(width-lc, ih1), size=(lc, ih1), font=1, flags=RT_HALIGN_RIGHT, text=len))
186 elif self.list_type == MovieList.LISTTYPE_COMPACT:
187 ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up
188 lc, col = self.compactColumn[0], self.compactColumn[1]
189 res.append(MultiContentEntryText(pos=(0, 0), size=(width-lc-2, ih1), font = 0, flags = RT_HALIGN_LEFT, text = txt))
191 res.append(MultiContentEntryText(pos=(width-col, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = tags))
192 if service is not None:
193 res.append(MultiContentEntryText(pos=(col, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_LEFT, text = service.getServiceName()))
195 if service is not None:
196 res.append(MultiContentEntryText(pos=(width-col, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName()))
197 res.append(MultiContentEntryText(pos=(0, ih1), size=(col, ih-ih1), font=1, flags=RT_HALIGN_LEFT, text=begin_string))
198 res.append(MultiContentEntryText(pos=(width-lc, 0), size=(lc, ih1), font=0, flags=RT_HALIGN_RIGHT, text=len))
200 assert(self.list_type == MovieList.LISTTYPE_MINIMAL)
201 if self.descr_state == MovieList.SHOW_DESCRIPTION:
202 dateSize = ih * 145 / 20 # 20 -> 145
203 res.append(MultiContentEntryText(pos=(0, 0), size=(width-dateSize, ih), font = 0, flags = RT_HALIGN_LEFT, text = txt))
204 res.append(MultiContentEntryText(pos=(width-dateSize, 4), size=(dateSize, ih), font=1, flags=RT_HALIGN_RIGHT, text=begin_string))
206 lenSize = ih * 75 / 20 # 20 -> 75
207 res.append(MultiContentEntryText(pos=(0, 0), size=(width-lenSize-2, ih), font = 0, flags = RT_HALIGN_LEFT, text = txt))
208 res.append(MultiContentEntryText(pos=(width-lenSize, 0), size=(lenSize, ih), font=0, flags=RT_HALIGN_RIGHT, text=len))
212 def moveToIndex(self, index):
213 self.instance.moveSelectionTo(index)
215 def getCurrentIndex(self):
216 return self.instance.getCurrentIndex()
218 def getCurrentEvent(self):
219 l = self.l.getCurrentSelection()
220 return l and l[0] and l[1] and l[1].getEvent(l[0])
222 def getCurrent(self):
223 l = self.l.getCurrentSelection()
226 GUI_WIDGET = eListbox
228 def postWidgetCreate(self, instance):
229 instance.setContent(self.l)
230 instance.selectionChanged.get().append(self.selectionChanged)
232 def preWidgetRemove(self, instance):
233 instance.setContent(None)
234 instance.selectionChanged.get().remove(self.selectionChanged)
236 def reload(self, root = None, filter_tags = None):
238 self.load(root, filter_tags)
240 self.load(self.root, filter_tags)
241 self.l.setList(self.list)
243 def removeService(self, service):
244 for l in self.list[:]:
247 self.l.setList(self.list)
250 return len(self.list)
252 def load(self, root, filter_tags):
253 # this lists our root service, then building a
257 self.serviceHandler = eServiceCenter.getInstance()
260 list = self.serviceHandler.list(root)
262 print "listing of movies failed"
268 serviceref = list.getNext()
269 if not serviceref.valid():
271 if serviceref.flags & eServiceReference.mustDescent:
274 info = self.serviceHandler.info(serviceref)
277 begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate)
279 # convert space-seperated list of tags into a set
280 this_tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ')
281 if this_tags == ['']:
283 this_tags = set(this_tags)
286 # filter_tags is either None (which means no filter at all), or
287 # a set. In this case, all elements of filter_tags must be present,
288 # otherwise the entry will be dropped.
289 if filter_tags is not None and not this_tags.issuperset(filter_tags):
292 self.list.append((serviceref, info, begin, -1))
294 if self.sort_type == MovieList.SORT_ALPHANUMERIC:
295 self.list.sort(key=self.buildAlphaNumericSortKey)
297 # sort: key is 'begin'
298 self.list.sort(key=lambda x: -x[2])
300 # finally, store a list of all tags which were found. these can be presented
301 # to the user to filter the list
304 def buildAlphaNumericSortKey(self, x):
306 info = self.serviceHandler.info(ref)
307 name = info and info.getName(ref)
308 return (name and name.lower() or "", -x[2])
310 def moveTo(self, serviceref):
313 if x[0] == serviceref:
314 self.instance.moveSelectionTo(count)
320 self.instance.moveSelection(self.instance.moveDown)