f1db4645c94ce415d4a41b3b20155c6ea1c4fcc7
[vuplus_dvbapp] / lib / python / Screens / MovieSelection.py
1 from Screen import Screen
2 from Components.Button import Button
3 from Components.ActionMap import HelpableActionMap, ActionMap
4 from Components.MenuList import MenuList
5 from Components.MovieList import MovieList
6 from Components.DiskInfo import DiskInfo
7 from Components.Pixmap import Pixmap
8 from Components.Label import Label
9 from Components.PluginComponent import plugins
10 from Components.config import config, ConfigSubsection, ConfigText, ConfigInteger, ConfigLocations, ConfigSet
11 from Components.Sources.ServiceEvent import ServiceEvent
12 from Components.UsageConfig import defaultMoviePath
13
14 from Plugins.Plugin import PluginDescriptor
15
16 from Screens.MessageBox import MessageBox
17 from Screens.ChoiceBox import ChoiceBox
18 from Screens.LocationBox import MovieLocationBox
19 from Screens.HelpMenu import HelpableScreen
20
21 from Tools.Directories import *
22 from Tools.BoundFunction import boundFunction
23
24 from enigma import eServiceReference, eServiceCenter, eTimer, eSize
25
26 config.movielist = ConfigSubsection()
27 config.movielist.moviesort = ConfigInteger(default=MovieList.SORT_RECORDED)
28 config.movielist.listtype = ConfigInteger(default=MovieList.LISTTYPE_ORIGINAL)
29 config.movielist.description = ConfigInteger(default=MovieList.HIDE_DESCRIPTION)
30 config.movielist.last_videodir = ConfigText(default=resolveFilename(SCOPE_HDD))
31 config.movielist.last_timer_videodir = ConfigText(default=resolveFilename(SCOPE_HDD))
32 config.movielist.videodirs = ConfigLocations(default=[resolveFilename(SCOPE_HDD)])
33 config.movielist.first_tags = ConfigText(default="")
34 config.movielist.second_tags = ConfigText(default="")
35 config.movielist.last_selected_tags = ConfigSet([], default=[])
36
37
38 def setPreferredTagEditor(te):
39         global preferredTagEditor
40         try:
41                 if preferredTagEditor == None:
42                         preferredTagEditor = te
43                         print "Preferred tag editor changed to ", preferredTagEditor
44                 else:
45                         print "Preferred tag editor already set to ", preferredTagEditor
46                         print "ignoring ", te
47         except:
48                 preferredTagEditor = te
49                 print "Preferred tag editor set to ", preferredTagEditor
50
51 def getPreferredTagEditor():
52         global preferredTagEditor
53         return preferredTagEditor
54
55 setPreferredTagEditor(None)
56
57 class MovieContextMenu(Screen):
58         def __init__(self, session, csel, service):
59                 Screen.__init__(self, session)
60                 self.csel = csel
61                 self.service = service
62
63                 self["actions"] = ActionMap(["OkCancelActions"],
64                         {
65                                 "ok": self.okbuttonClick,
66                                 "cancel": self.cancelClick
67                         })
68
69                 menu = [(_("delete..."), self.delete)]
70                 menu.extend([(p.description, boundFunction(self.execPlugin, p)) for p in plugins.getPlugins(PluginDescriptor.WHERE_MOVIELIST)])
71
72                 if config.movielist.moviesort.value == MovieList.SORT_ALPHANUMERIC:
73                         menu.append((_("sort by date"), boundFunction(self.sortBy, MovieList.SORT_RECORDED)))
74                 else:
75                         menu.append((_("alphabetic sort"), boundFunction(self.sortBy, MovieList.SORT_ALPHANUMERIC)))
76                 
77                 menu.extend((
78                         (_("list style default"), boundFunction(self.listType, MovieList.LISTTYPE_ORIGINAL)),
79                         (_("list style compact with description"), boundFunction(self.listType, MovieList.LISTTYPE_COMPACT_DESCRIPTION)),
80                         (_("list style compact"), boundFunction(self.listType, MovieList.LISTTYPE_COMPACT)),
81                         (_("list style single line"), boundFunction(self.listType, MovieList.LISTTYPE_MINIMAL))
82                 ))
83
84                 if config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
85                         menu.append((_("hide extended description"), boundFunction(self.showDescription, MovieList.HIDE_DESCRIPTION)))
86                 else:
87                         menu.append((_("show extended description"), boundFunction(self.showDescription, MovieList.SHOW_DESCRIPTION)))
88                 self["menu"] = MenuList(menu)
89
90         def okbuttonClick(self):
91                 self["menu"].getCurrent()[1]()
92
93         def cancelClick(self):
94                 self.close(False)
95
96         def sortBy(self, newType):
97                 config.movielist.moviesort.value = newType
98                 self.csel.setSortType(newType)
99                 self.csel.reloadList()
100                 self.close()
101
102         def listType(self, newType):
103                 config.movielist.listtype.value = newType
104                 self.csel.setListType(newType)
105                 self.csel.list.redrawList()
106                 self.close()
107
108         def showDescription(self, newType):
109                 config.movielist.description.value = newType
110                 self.csel.setDescriptionState(newType)
111                 self.csel.updateDescription()
112                 self.close()
113
114         def execPlugin(self, plugin):
115                 plugin(session=self.session, service=self.service)
116
117         def delete(self):
118                 serviceHandler = eServiceCenter.getInstance()
119                 offline = serviceHandler.offlineOperations(self.service)
120                 info = serviceHandler.info(self.service)
121                 name = info and info.getName(self.service) or _("this recording")
122                 result = False
123                 if offline is not None:
124                         # simulate first
125                         if not offline.deleteFromDisk(1):
126                                 result = True
127                 if result == True:
128                         self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do you really want to delete %s?") % (name))
129                 else:
130                         self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR)
131
132         def deleteConfirmed(self, confirmed):
133                 if not confirmed:
134                         return self.close()
135                 
136                 serviceHandler = eServiceCenter.getInstance()
137                 offline = serviceHandler.offlineOperations(self.service)
138                 result = False
139                 if offline is not None:
140                         # really delete!
141                         if not offline.deleteFromDisk(0):
142                                 result = True
143                 
144                 if result == False:
145                         self.session.openWithCallback(self.close, MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
146                 else:
147                         self.csel["list"].removeService(self.service)
148                         self.csel["freeDiskSpace"].update()
149                         self.close()
150
151 class SelectionEventInfo:
152         def __init__(self):
153                 self["Service"] = ServiceEvent()
154                 self.list.connectSelChanged(self.__selectionChanged)
155                 self.timer = eTimer()
156                 self.timer.callback.append(self.updateEventInfo)
157                 self.onShown.append(self.__selectionChanged)
158
159         def __selectionChanged(self):
160                 if self.execing and config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
161                         self.timer.start(100, True)
162
163         def updateEventInfo(self):
164                 serviceref = self.getCurrent()
165                 self["Service"].newService(serviceref)
166
167 class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
168         def __init__(self, session, selectedmovie = None):
169                 Screen.__init__(self, session)
170                 HelpableScreen.__init__(self)
171
172                 self.tags = [ ]
173                 if selectedmovie:
174                         self.selected_tags = config.movielist.last_selected_tags.value
175                 else:
176                         self.selected_tags = None
177                 self.selected_tags_ele = None
178
179                 self.movemode = False
180                 self.bouquet_mark_edit = False
181
182                 self.delayTimer = eTimer()
183                 self.delayTimer.callback.append(self.updateHDDData)
184
185                 self["waitingtext"] = Label(_("Please wait... Loading list..."))
186
187                 # create optional description border and hide immediately
188                 self["DescriptionBorder"] = Pixmap()
189                 self["DescriptionBorder"].hide()
190
191                 if not fileExists(config.movielist.last_videodir.value):
192                         self.getDefaultMoviePath()
193                 self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + config.movielist.last_videodir.value)
194
195                 self["list"] = MovieList(None,
196                         config.movielist.listtype.value,
197                         config.movielist.moviesort.value,
198                         config.movielist.description.value)
199
200                 self.list = self["list"]
201                 self.selectedmovie = selectedmovie
202
203                 # Need list for init
204                 SelectionEventInfo.__init__(self)
205
206                 self["key_red"] = Button(_("All"))
207                 self["key_green"] = Button("")
208                 self["key_yellow"] = Button("")
209                 self["key_blue"] = Button("")
210
211                 self["freeDiskSpace"] = self.diskinfo = DiskInfo(config.movielist.last_videodir.value, DiskInfo.FREE, update=False)
212
213                 if config.usage.setup_level.index >= 2: # expert+
214                         self["InfobarActions"] = HelpableActionMap(self, "InfobarActions", 
215                                 {
216                                         "showMovies": (self.doPathSelect, _("select the movie path")),
217                                 })
218
219
220                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
221                         {
222                                 "contextMenu": (self.doContext, _("menu")),
223                                 "showEventInfo": (self.showEventInformation, _("show event details")),
224                         })
225
226                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
227                         {
228                                 "red": (self.showAll, _("show all")),
229                                 "green": (self.showTagsFirst, _("show first selected tag")),
230                                 "yellow": (self.showTagsSecond, _("show second selected tag")),
231                                 "blue": (self.showTagsSelect, _("show tag menu")),
232                         })
233
234                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
235                         {
236                                 "cancel": (self.abort, _("exit movielist")),
237                                 "ok": (self.movieSelected, _("select movie")),
238                         })
239
240                 self.onShown.append(self.go)
241                 self.onLayoutFinish.append(self.saveListsize)
242                 self.inited = False
243
244         def getDefaultMoviePath(self):
245                 path = defaultMoviePath()
246                 config.movielist.last_videodir.value = path
247                 config.movielist.last_videodir.save()
248                 tmp = config.movielist.videodirs.value[:]
249                 if path not in tmp:
250                         tmp.append(path)
251                         tmp.sort()
252                         config.movielist.videodirs.value = tmp
253                         config.movielist.videodirs.save()
254
255         def updateDescription(self):
256                 if config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
257                         self["DescriptionBorder"].show()
258                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight-self["DescriptionBorder"].instance.size().height()))
259                 else:
260                         self["Service"].newService(None)
261                         self["DescriptionBorder"].hide()
262                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight))
263
264         def showEventInformation(self):
265                 from Screens.EventView import EventViewSimple
266                 from ServiceReference import ServiceReference
267                 evt = self["list"].getCurrentEvent()
268                 if evt:
269                         self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
270
271         def go(self):
272                 if not self.inited:
273                 # ouch. this should redraw our "Please wait..."-text.
274                 # this is of course not the right way to do this.
275                         self.delayTimer.start(10, 1)
276                         self.inited=True
277
278         def saveListsize(self):
279                         listsize = self["list"].instance.size()
280                         self.listWidth = listsize.width()
281                         self.listHeight = listsize.height()
282                         self.updateDescription()
283
284         def updateHDDData(self):
285                 self.reloadList(self.selectedmovie)
286                 self["waitingtext"].visible = False
287
288         def moveTo(self):
289                 self["list"].moveTo(self.selectedmovie)
290
291         def getCurrent(self):
292                 return self["list"].getCurrent()
293
294         def movieSelected(self):
295                 current = self.getCurrent()
296                 if current is not None:
297                         self.saveconfig()
298                         self.close(current)
299
300         def doContext(self):
301                 current = self.getCurrent()
302                 if current is not None:
303                         self.session.open(MovieContextMenu, self, current)
304
305         def abort(self):
306                 self.saveconfig()
307                 self.close(None)
308
309         def saveconfig(self):
310                 config.movielist.last_selected_tags.value = self.selected_tags
311                 config.movielist.moviesort.save()
312                 config.movielist.listtype.save()
313                 config.movielist.description.save()
314
315         def getTagDescription(self, tag):
316                 # TODO: access the tag database
317                 return tag
318
319         def updateTags(self):
320                 # get a list of tags available in this list
321                 self.tags = list(self["list"].tags)
322
323                 if not self.tags:
324                         # by default, we do not display any filtering options
325                         self.tag_first = ""
326                         self.tag_second = ""
327                 else:
328                         tmp = config.movielist.first_tags.value
329                         if tmp in self.tags:
330                                 self.tag_first = tmp
331                         else:
332                                 self.tag_first = "<"+_("Tag 1")+">"
333                         tmp = config.movielist.second_tags.value
334                         if tmp in self.tags:
335                                 self.tag_second = tmp
336                         else:
337                                 self.tag_second = "<"+_("Tag 2")+">"
338                 self["key_green"].text = self.tag_first
339                 self["key_yellow"].text = self.tag_second
340                 
341                 # the rest is presented in a list, available on the
342                 # fourth ("blue") button
343                 if self.tags:
344                         self["key_blue"].text = _("Tags")+"..."
345                 else:
346                         self["key_blue"].text = ""
347
348         def setListType(self, type):
349                 self["list"].setListType(type)
350
351         def setDescriptionState(self, val):
352                 self["list"].setDescriptionState(val)
353
354         def setSortType(self, type):
355                 self["list"].setSortType(type)
356
357         def reloadList(self, sel = None, home = False):
358                 if not fileExists(config.movielist.last_videodir.value):
359                         self.getDefaultMoviePath()
360                         self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path)
361                         self["freeDiskSpace"].path = path
362                 if sel is None:
363                         sel = self.getCurrent()
364
365                 self["list"].reload(self.current_ref, self.selected_tags)
366                 title = _("Recorded files...")
367                 if config.usage.setup_level.index >= 2: # expert+
368                         title += "  " + config.movielist.last_videodir.value
369                 if self.selected_tags is not None:
370                         title += " - " + ','.join(self.selected_tags)
371                 self.setTitle(title)
372                 if not (sel and self["list"].moveTo(sel)):
373                         if home:
374                                 self["list"].moveToIndex(0)
375                 self.updateTags()
376                 self["freeDiskSpace"].update()
377
378         def doPathSelect(self):
379                 self.session.openWithCallback(
380                         self.gotFilename,
381                         MovieLocationBox,
382                         _("Please select the movie path..."),
383                         config.movielist.last_videodir.value
384                 )
385
386         def gotFilename(self, res):
387                 if res is not None and res is not config.movielist.last_videodir.value:
388                         if fileExists(res):
389                                 config.movielist.last_videodir.value = res
390                                 config.movielist.last_videodir.save()
391                                 self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + res)
392                                 self["freeDiskSpace"].path = res
393                                 self.reloadList(home = True)
394                         else:
395                                 self.session.open(
396                                         MessageBox,
397                                         _("Directory %s nonexistent.") % (res),
398                                         type = MessageBox.TYPE_ERROR,
399                                         timeout = 5
400                                         )
401
402         def showAll(self):
403                 self.selected_tags_ele = None
404                 self.selected_tags = None
405                 self.reloadList(home = True)
406
407         def showTagsN(self, tagele):
408                 if not self.tags:
409                         self.showTagWarning()
410                 elif not tagele or (self.selected_tags and tagele.value in self.selected_tags) or not tagele.value in self.tags:
411                         self.showTagsMenu(tagele)
412                 else:
413                         self.selected_tags_ele = tagele
414                         self.selected_tags = set([tagele.value])
415                         self.reloadList(home = True)
416
417         def showTagsFirst(self):
418                 self.showTagsN(config.movielist.first_tags)
419
420         def showTagsSecond(self):
421                 self.showTagsN(config.movielist.second_tags)
422
423         def showTagsSelect(self):
424                 self.showTagsN(None)
425
426         def tagChosen(self, tag):
427                 if tag is not None:
428                         self.selected_tags = set([tag[0]])
429                         if self.selected_tags_ele:
430                                 self.selected_tags_ele.value = tag[0]
431                                 self.selected_tags_ele.save()
432                         self.reloadList(home = True)
433
434         def showTagsMenu(self, tagele):
435                 self.selected_tags_ele = tagele
436                 list = [(tag, self.getTagDescription(tag)) for tag in self.tags ]
437                 self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select tag to filter..."), list = list)
438
439         def showTagWarning(self):
440                 self.session.open(MessageBox, _("No tags are set on these movies."), MessageBox.TYPE_ERROR)