fixes bug #593
[enigma2.git] / 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                         config.movielist.last_videodir.value = defaultMoviePath()
193                         config.movielist.last_videodir.save()
194                 self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + config.movielist.last_videodir.value)
195
196                 self["list"] = MovieList(None,
197                         config.movielist.listtype.value,
198                         config.movielist.moviesort.value,
199                         config.movielist.description.value)
200
201                 self.list = self["list"]
202                 self.selectedmovie = selectedmovie
203
204                 # Need list for init
205                 SelectionEventInfo.__init__(self)
206
207                 self["key_red"] = Button(_("All"))
208                 self["key_green"] = Button("")
209                 self["key_yellow"] = Button("")
210                 self["key_blue"] = Button("")
211
212                 self["freeDiskSpace"] = self.diskinfo = DiskInfo(config.movielist.last_videodir.value, DiskInfo.FREE, update=False)
213
214                 if config.usage.setup_level.index >= 2: # expert+
215                         self["InfobarActions"] = HelpableActionMap(self, "InfobarActions", 
216                                 {
217                                         "showMovies": (self.doPathSelect, _("select the movie path")),
218                                 })
219
220
221                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
222                         {
223                                 "contextMenu": (self.doContext, _("menu")),
224                                 "showEventInfo": (self.showEventInformation, _("show event details")),
225                         })
226
227                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
228                         {
229                                 "red": (self.showAll, _("show all")),
230                                 "green": (self.showTagsFirst, _("show first selected tag")),
231                                 "yellow": (self.showTagsSecond, _("show second selected tag")),
232                                 "blue": (self.showTagsSelect, _("show tag menu")),
233                         })
234
235                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
236                         {
237                                 "cancel": (self.abort, _("exit movielist")),
238                                 "ok": (self.movieSelected, _("select movie")),
239                         })
240
241                 self.onShown.append(self.go)
242                 self.onLayoutFinish.append(self.saveListsize)
243                 self.inited = False
244
245         def updateDescription(self):
246                 if config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
247                         self["DescriptionBorder"].show()
248                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight-self["DescriptionBorder"].instance.size().height()))
249                 else:
250                         self["Service"].newService(None)
251                         self["DescriptionBorder"].hide()
252                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight))
253
254         def showEventInformation(self):
255                 from Screens.EventView import EventViewSimple
256                 from ServiceReference import ServiceReference
257                 evt = self["list"].getCurrentEvent()
258                 if evt:
259                         self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
260
261         def go(self):
262                 if not self.inited:
263                 # ouch. this should redraw our "Please wait..."-text.
264                 # this is of course not the right way to do this.
265                         self.delayTimer.start(10, 1)
266                         self.inited=True
267
268         def saveListsize(self):
269                         listsize = self["list"].instance.size()
270                         self.listWidth = listsize.width()
271                         self.listHeight = listsize.height()
272                         self.updateDescription()
273
274         def updateHDDData(self):
275                 self.reloadList(self.selectedmovie)
276                 self["waitingtext"].visible = False
277
278         def moveTo(self):
279                 self["list"].moveTo(self.selectedmovie)
280
281         def getCurrent(self):
282                 return self["list"].getCurrent()
283
284         def movieSelected(self):
285                 current = self.getCurrent()
286                 if current is not None:
287                         self.saveconfig()
288                         self.close(current)
289
290         def doContext(self):
291                 current = self.getCurrent()
292                 if current is not None:
293                         self.session.open(MovieContextMenu, self, current)
294
295         def abort(self):
296                 self.saveconfig()
297                 self.close(None)
298
299         def saveconfig(self):
300                 config.movielist.last_selected_tags.value = self.selected_tags
301                 config.movielist.moviesort.save()
302                 config.movielist.listtype.save()
303                 config.movielist.description.save()
304
305         def getTagDescription(self, tag):
306                 # TODO: access the tag database
307                 return tag
308
309         def updateTags(self):
310                 # get a list of tags available in this list
311                 self.tags = list(self["list"].tags)
312
313                 if not self.tags:
314                         # by default, we do not display any filtering options
315                         self.tag_first = ""
316                         self.tag_second = ""
317                 else:
318                         tmp = config.movielist.first_tags.value
319                         if tmp in self.tags:
320                                 self.tag_first = tmp
321                         else:
322                                 self.tag_first = "<"+_("Tag 1")+">"
323                         tmp = config.movielist.second_tags.value
324                         if tmp in self.tags:
325                                 self.tag_second = tmp
326                         else:
327                                 self.tag_second = "<"+_("Tag 2")+">"
328                 self["key_green"].text = self.tag_first
329                 self["key_yellow"].text = self.tag_second
330                 
331                 # the rest is presented in a list, available on the
332                 # fourth ("blue") button
333                 if self.tags:
334                         self["key_blue"].text = _("Tags")+"..."
335                 else:
336                         self["key_blue"].text = ""
337
338         def setListType(self, type):
339                 self["list"].setListType(type)
340
341         def setDescriptionState(self, val):
342                 self["list"].setDescriptionState(val)
343
344         def setSortType(self, type):
345                 self["list"].setSortType(type)
346
347         def reloadList(self, sel = None, home = False):
348                 if not fileExists(config.movielist.last_videodir.value):
349                         path = defaultMoviePath()
350                         config.movielist.last_videodir.value = path
351                         config.movielist.last_videodir.save()
352                         self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path)
353                         self["freeDiskSpace"].path = path
354                 if sel is None:
355                         sel = self.getCurrent()
356                 self["list"].reload(self.current_ref, self.selected_tags)
357                 title = _("Recorded files...")
358                 if config.usage.setup_level.index >= 2: # expert+
359                         title += "  " + config.movielist.last_videodir.value
360                 if self.selected_tags is not None:
361                         title += " - " + ','.join(self.selected_tags)
362                 self.setTitle(title)
363                 if not (sel and self["list"].moveTo(sel)):
364                         if home:
365                                 self["list"].moveToIndex(0)
366                 self.updateTags()
367                 self["freeDiskSpace"].update()
368
369         def doPathSelect(self):
370                 self.session.openWithCallback(
371                         self.gotFilename,
372                         MovieLocationBox,
373                         _("Please select the movie path..."),
374                         config.movielist.last_videodir.value
375                 )
376
377         def gotFilename(self, res):
378                 if res is not None and res is not config.movielist.last_videodir.value:
379                         if fileExists(res):
380                                 config.movielist.last_videodir.value = res
381                                 config.movielist.last_videodir.save()
382                                 self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + res)
383                                 self["freeDiskSpace"].path = res
384                                 self.reloadList(home = True)
385                         else:
386                                 self.session.open(
387                                         MessageBox,
388                                         _("Directory %s nonexistent.") % (res),
389                                         type = MessageBox.TYPE_ERROR,
390                                         timeout = 5
391                                         )
392
393         def showAll(self):
394                 self.selected_tags_ele = None
395                 self.selected_tags = None
396                 self.reloadList(home = True)
397
398         def showTagsN(self, tagele):
399                 if not self.tags:
400                         self.showTagWarning()
401                 elif not tagele or (self.selected_tags and tagele.value in self.selected_tags) or not tagele.value in self.tags:
402                         self.showTagsMenu(tagele)
403                 else:
404                         self.selected_tags_ele = tagele
405                         self.selected_tags = set([tagele.value])
406                         self.reloadList(home = True)
407
408         def showTagsFirst(self):
409                 self.showTagsN(config.movielist.first_tags)
410
411         def showTagsSecond(self):
412                 self.showTagsN(config.movielist.second_tags)
413
414         def showTagsSelect(self):
415                 self.showTagsN(None)
416
417         def tagChosen(self, tag):
418                 if tag is not None:
419                         self.selected_tags = set([tag[0]])
420                         if self.selected_tags_ele:
421                                 self.selected_tags_ele.value = tag[0]
422                                 self.selected_tags_ele.save()
423                         self.reloadList(home = True)
424
425         def showTagsMenu(self, tagele):
426                 self.selected_tags_ele = tagele
427                 list = [(tag, self.getTagDescription(tag)) for tag in self.tags ]
428                 self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select tag to filter..."), list = list)
429
430         def showTagWarning(self):
431                 self.session.open(MessageBox, _("No tags are set on these movies."), MessageBox.TYPE_ERROR)