[RecordTimer] fix repeat timer issue.
[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                 return path
256
257         def updateDescription(self):
258                 if config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
259                         self["DescriptionBorder"].show()
260                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight-self["DescriptionBorder"].instance.size().height()))
261                 else:
262                         self["Service"].newService(None)
263                         self["DescriptionBorder"].hide()
264                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight))
265
266         def showEventInformation(self):
267                 from Screens.EventView import EventViewSimple
268                 from ServiceReference import ServiceReference
269                 evt = self["list"].getCurrentEvent()
270                 if evt:
271                         self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
272
273         def go(self):
274                 if not self.inited:
275                 # ouch. this should redraw our "Please wait..."-text.
276                 # this is of course not the right way to do this.
277                         self.delayTimer.start(10, 1)
278                         self.inited=True
279
280         def saveListsize(self):
281                         listsize = self["list"].instance.size()
282                         self.listWidth = listsize.width()
283                         self.listHeight = listsize.height()
284                         self.updateDescription()
285
286         def updateHDDData(self):
287                 self.reloadList(self.selectedmovie)
288                 self["waitingtext"].visible = False
289
290         def moveTo(self):
291                 self["list"].moveTo(self.selectedmovie)
292
293         def getCurrent(self):
294                 return self["list"].getCurrent()
295
296         def movieSelected(self):
297                 current = self.getCurrent()
298                 if current is not None:
299                         self.saveconfig()
300                         self.close(current)
301
302         def doContext(self):
303                 current = self.getCurrent()
304                 if current is not None:
305                         self.session.open(MovieContextMenu, self, current)
306
307         def abort(self):
308                 self.saveconfig()
309                 self.close(None)
310
311         def saveconfig(self):
312                 config.movielist.last_selected_tags.value = self.selected_tags
313                 config.movielist.moviesort.save()
314                 config.movielist.listtype.save()
315                 config.movielist.description.save()
316
317         def getTagDescription(self, tag):
318                 # TODO: access the tag database
319                 return tag
320
321         def updateTags(self):
322                 # get a list of tags available in this list
323                 self.tags = list(self["list"].tags)
324
325                 if not self.tags:
326                         # by default, we do not display any filtering options
327                         self.tag_first = ""
328                         self.tag_second = ""
329                 else:
330                         tmp = config.movielist.first_tags.value
331                         if tmp in self.tags:
332                                 self.tag_first = tmp
333                         else:
334                                 self.tag_first = "<"+_("Tag 1")+">"
335                         tmp = config.movielist.second_tags.value
336                         if tmp in self.tags:
337                                 self.tag_second = tmp
338                         else:
339                                 self.tag_second = "<"+_("Tag 2")+">"
340                 self["key_green"].text = self.tag_first
341                 self["key_yellow"].text = self.tag_second
342                 
343                 # the rest is presented in a list, available on the
344                 # fourth ("blue") button
345                 if self.tags:
346                         self["key_blue"].text = _("Tags")+"..."
347                 else:
348                         self["key_blue"].text = ""
349
350         def setListType(self, type):
351                 self["list"].setListType(type)
352
353         def setDescriptionState(self, val):
354                 self["list"].setDescriptionState(val)
355
356         def setSortType(self, type):
357                 self["list"].setSortType(type)
358
359         def reloadList(self, sel = None, home = False):
360                 if not fileExists(config.movielist.last_videodir.value):
361                         path = self.getDefaultMoviePath()
362                         self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path)
363                         self["freeDiskSpace"].path = path
364                 if sel is None:
365                         sel = self.getCurrent()
366
367                 self["list"].reload(self.current_ref, self.selected_tags)
368                 title = _("Recorded files...")
369                 if config.usage.setup_level.index >= 2: # expert+
370                         title += "  " + config.movielist.last_videodir.value
371                 if self.selected_tags is not None:
372                         title += " - " + ','.join(self.selected_tags)
373                 self.setTitle(title)
374                 if not (sel and self["list"].moveTo(sel)):
375                         if home:
376                                 self["list"].moveToIndex(0)
377                 self.updateTags()
378                 self["freeDiskSpace"].update()
379
380         def doPathSelect(self):
381                 self.session.openWithCallback(
382                         self.gotFilename,
383                         MovieLocationBox,
384                         _("Please select the movie path..."),
385                         config.movielist.last_videodir.value
386                 )
387
388         def gotFilename(self, res):
389                 if res is not None and res is not config.movielist.last_videodir.value:
390                         if fileExists(res):
391                                 config.movielist.last_videodir.value = res
392                                 config.movielist.last_videodir.save()
393                                 self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + res)
394                                 self["freeDiskSpace"].path = res
395                                 self.reloadList(home = True)
396                         else:
397                                 self.session.open(
398                                         MessageBox,
399                                         _("Directory %s nonexistent.") % (res),
400                                         type = MessageBox.TYPE_ERROR,
401                                         timeout = 5
402                                         )
403
404         def showAll(self):
405                 self.selected_tags_ele = None
406                 self.selected_tags = None
407                 self.reloadList(home = True)
408
409         def showTagsN(self, tagele):
410                 if not self.tags:
411                         self.showTagWarning()
412                 elif not tagele or (self.selected_tags and tagele.value in self.selected_tags) or not tagele.value in self.tags:
413                         self.showTagsMenu(tagele)
414                 else:
415                         self.selected_tags_ele = tagele
416                         self.selected_tags = set([tagele.value])
417                         self.reloadList(home = True)
418
419         def showTagsFirst(self):
420                 self.showTagsN(config.movielist.first_tags)
421
422         def showTagsSecond(self):
423                 self.showTagsN(config.movielist.second_tags)
424
425         def showTagsSelect(self):
426                 self.showTagsN(None)
427
428         def tagChosen(self, tag):
429                 if tag is not None:
430                         self.selected_tags = set([tag[0]])
431                         if self.selected_tags_ele:
432                                 self.selected_tags_ele.value = tag[0]
433                                 self.selected_tags_ele.save()
434                         self.reloadList(home = True)
435
436         def showTagsMenu(self, tagele):
437                 self.selected_tags_ele = tagele
438                 list = [(tag, self.getTagDescription(tag)) for tag in self.tags ]
439                 self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select tag to filter..."), list = list)
440
441         def showTagWarning(self):
442                 self.session.open(MessageBox, _("No tags are set on these movies."), MessageBox.TYPE_ERROR)