write memleak info to /var/tmp/enigma2_mem.out instead of stdout
[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, ConfigInteger, configfile
11 from Components.Sources.ServiceEvent import ServiceEvent
12
13 from Plugins.Plugin import PluginDescriptor
14
15 from Screens.MessageBox import MessageBox
16 from Screens.ChoiceBox import ChoiceBox
17 from Screens.HelpMenu import HelpableScreen
18
19 from Tools.Directories import *
20 from Tools.BoundFunction import boundFunction
21
22 from enigma import eServiceReference, eServiceCenter, eTimer, eSize
23
24 config.movielist = ConfigSubsection()
25 config.movielist.moviesort = ConfigInteger(default=MovieList.SORT_RECORDED)
26 config.movielist.listtype = ConfigInteger(default=MovieList.LISTTYPE_ORIGINAL)
27 config.movielist.description = ConfigInteger(default=MovieList.HIDE_DESCRIPTION)
28
29 class MovieContextMenu(Screen):
30         def __init__(self, session, csel, service):
31                 Screen.__init__(self, session)
32                 self.csel = csel
33                 self.service = service
34
35                 self["actions"] = ActionMap(["OkCancelActions"],
36                         {
37                                 "ok": self.okbuttonClick,
38                                 "cancel": self.cancelClick
39                         })
40
41                 menu = [(_("delete..."), self.delete)]
42                 
43                 for p in plugins.getPlugins(PluginDescriptor.WHERE_MOVIELIST):
44                         menu.append((p.description, boundFunction(self.execPlugin, p)))
45                 
46                 if config.movielist.moviesort.value == MovieList.SORT_ALPHANUMERIC:
47                         menu.append((_("sort by date"), boundFunction(self.sortBy, MovieList.SORT_RECORDED)))
48                 else:
49                         menu.append((_("alphabetic sort"), boundFunction(self.sortBy, MovieList.SORT_ALPHANUMERIC)))
50                 
51                 menu.append((_("list style default"), boundFunction(self.listType, MovieList.LISTTYPE_ORIGINAL)))
52                 menu.append((_("list style compact with description"), boundFunction(self.listType, MovieList.LISTTYPE_COMPACT_DESCRIPTION)))
53                 menu.append((_("list style compact"), boundFunction(self.listType, MovieList.LISTTYPE_COMPACT)))
54                 menu.append((_("list style single line"), boundFunction(self.listType, MovieList.LISTTYPE_MINIMAL)))
55                 
56                 if config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
57                         menu.append((_("hide extended description"), boundFunction(self.showDescription, MovieList.HIDE_DESCRIPTION)))
58                 else:
59                         menu.append((_("show extended description"), boundFunction(self.showDescription, MovieList.SHOW_DESCRIPTION)))
60                 self["menu"] = MenuList(menu)
61
62         def okbuttonClick(self):
63                 self["menu"].getCurrent()[1]()
64
65         def cancelClick(self):
66                 self.close(False)
67
68         def sortBy(self, newType):
69                 self.csel.saveflag = True
70                 config.movielist.moviesort.value = newType
71                 self.csel.selectedmovie = self.csel.getCurrent()
72                 self.csel.setSortType(newType)
73                 self.csel.reloadList()
74                 self.csel.moveTo()
75                 self.close()
76
77         def listType(self, newType):
78                 self.csel.saveflag = True
79                 config.movielist.listtype.value = newType
80                 self.csel.setListType(newType)
81                 self.csel.list.redrawList()
82                 self.close()
83
84         def showDescription(self, newType):
85                 self.csel.saveflag = True
86                 config.movielist.description.value = newType
87                 self.csel.setDescriptionState(newType)
88                 self.csel.updateDescription()
89                 self.close()
90
91         def execPlugin(self, plugin):
92                 plugin(session=self.session, service=self.service)
93
94         def delete(self):
95                 serviceHandler = eServiceCenter.getInstance()
96                 offline = serviceHandler.offlineOperations(self.service)
97                 info = serviceHandler.info(self.service)
98                 name = info and info.getName(self.service) or _("this recording")
99                 result = False
100                 if offline is not None:
101                         # simulate first
102                         if not offline.deleteFromDisk(1):
103                                 result = True
104                 if result == True:
105                         self.session.openWithCallback(self.deleteConfirmed, MessageBox, _("Do you really want to delete %s?") % (name))
106                 else:
107                         self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR)
108
109         def deleteConfirmed(self, confirmed):
110                 if not confirmed:
111                         return self.close()
112                 
113                 serviceHandler = eServiceCenter.getInstance()
114                 offline = serviceHandler.offlineOperations(self.service)
115                 result = False
116                 if offline is not None:
117                         # really delete!
118                         if not offline.deleteFromDisk(0):
119                                 result = True
120                 
121                 if result == False:
122                         self.session.openWithCallback(self.close, MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR)
123                 else:
124                         list = self.csel["list"].removeService(self.service)
125                         self.close()
126
127 class SelectionEventInfo:
128         def __init__(self):
129                 self["Service"] = ServiceEvent()
130                 self.list.connectSelChanged(self.__selectionChanged)
131                 self.timer = eTimer()
132                 self.timer.timeout.get().append(self.updateEventInfo)
133                 self.onShown.append(self.__selectionChanged)
134
135         def __selectionChanged(self):
136                 if self.execing and config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
137                         self.timer.start(100, True)
138
139         def updateEventInfo(self):
140                 serviceref = self.getCurrent()
141                 self["Service"].newService(serviceref)
142
143 class MovieSelection(Screen, HelpableScreen, SelectionEventInfo):
144         def __init__(self, session, selectedmovie = None):
145                 Screen.__init__(self, session)
146                 HelpableScreen.__init__(self)
147
148                 self.saveflag = False
149
150                 self.tags = [ ]
151                 self.selected_tags = None
152
153                 self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + resolveFilename(SCOPE_HDD))
154
155                 self.movemode = False
156                 self.bouquet_mark_edit = False
157
158                 self.delayTimer = eTimer()
159                 self.delayTimer.timeout.get().append(self.updateHDDData)
160
161                 self["waitingtext"] = Label(_("Please wait... Loading list..."))
162
163                 # create optional description border and hide immediately
164                 self["DescriptionBorder"] = Pixmap()
165                 self["DescriptionBorder"].hide()
166
167                 self["list"] = MovieList(None,
168                         config.movielist.listtype.value,
169                         config.movielist.moviesort.value,
170                         config.movielist.description.value)
171
172                 self.list = self["list"]
173                 self.selectedmovie = selectedmovie
174
175                 # Need list for init
176                 SelectionEventInfo.__init__(self)
177
178                 self["key_red"] = Button(_("All..."))
179                 self["key_green"] = Button("")
180                 self["key_yellow"] = Button("")
181                 self["key_blue"] = Button("")
182
183                 #self["freeDiskSpace"] = DiskInfo(resolveFilename(SCOPE_HDD), DiskInfo.FREE, update=False)
184                 self["freeDiskSpace"] = self.diskinfo = DiskInfo(resolveFilename(SCOPE_HDD), DiskInfo.FREE, update=False)
185
186                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
187                         {
188                                 "contextMenu": (self.doContext, _("menu")),
189                                 "showEventInfo": (self.showEventInformation, _("show event details")),
190                         })
191
192                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
193                         {
194                                 "red": (self.showAll, _("show all")),
195                                 "green": (self.showTagsFirst, _("show first tag")),
196                                 "yellow": (self.showTagsSecond, _("show second tag")),
197                                 "blue": (self.showTagsMenu, _("show tag menu")),
198                         })
199
200                 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
201                         {
202                                 "cancel": (self.abort, _("exit movielist")),
203                                 "ok": (self.movieSelected, _("select movie")),
204                         })
205
206                 self.onShown.append(self.go)
207                 self.inited = False
208
209         def updateDescription(self):
210                 if config.movielist.description.value == MovieList.SHOW_DESCRIPTION:
211                         self["DescriptionBorder"].show()
212                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight-self["DescriptionBorder"].instance.size().height()))
213                 else:
214                         self["Service"].newService(None)
215                         self["DescriptionBorder"].hide()
216                         self["list"].instance.resize(eSize(self.listWidth, self.listHeight))
217
218         def showEventInformation(self):
219                 from Screens.EventView import EventViewSimple
220                 from ServiceReference import ServiceReference
221                 evt = self["list"].getCurrentEvent()
222                 if evt:
223                         self.session.open(EventViewSimple, evt, ServiceReference(self.getCurrent()))
224
225         def go(self):
226                 if not self.inited:
227                 # ouch. this should redraw our "Please wait..."-text.
228                 # this is of course not the right way to do this.
229                         self.delayTimer.start(10, 1)
230                         self.inited=True
231                 # as this workaround is here anyways we can wait until the skin is initialized
232                 # and afterwards read out the information we need to draw the dynamic style
233                         listsize = self["list"].instance.size()
234                         self.listWidth = listsize.width()
235                         self.listHeight = listsize.height()
236                         self.updateDescription()
237
238         def updateHDDData(self):
239                 self.reloadList()
240                 if self.selectedmovie is not None:
241                         self.moveTo()
242                 self["waitingtext"].visible = False
243                 self["freeDiskSpace"].update()
244                 self.updateTags()
245
246         def moveTo(self):
247                 self["list"].moveTo(self.selectedmovie)
248
249         def getCurrent(self):
250                 return self["list"].getCurrent()
251
252         def movieSelected(self):
253                 current = self.getCurrent()
254                 if current is not None:
255                         self.saveconfig()
256                         self.close(current)
257
258         def doContext(self):
259                 current = self.getCurrent()
260                 if current is not None:
261                         self.session.open(MovieContextMenu, self, current)
262
263         def abort(self):
264                 self.saveconfig()
265                 self.close(None)
266
267         def saveconfig(self):
268                 if self.saveflag == True:
269                         config.movielist.moviesort.save()
270                         config.movielist.listtype.save()
271                         config.movielist.description.save()
272                         configfile.save()
273                         self.saveflag = False
274
275         def getTagDescription(self, tag):
276                 # TODO: access the tag database
277                 return tag
278
279         def updateTags(self):
280                 # get a list of tags available in this list
281                 self.tags = list(self["list"].tags)
282                 
283                 # by default, we do not display any filtering options
284                 self.tag_first = ""
285                 self.tag_second = ""
286                 
287                 # when tags are present, however, the first two are 
288                 # directly mapped to the second, third ("green", "yellow") buttons
289                 if len(self.tags) > 0:
290                         self.tag_first = self.getTagDescription(self.tags[0])
291                 
292                 if len(self.tags) > 1:
293                         self.tag_second = self.getTagDescription(self.tags[1])
294                 
295                 self["key_green"].text = self.tag_first
296                 self["key_yellow"].text = self.tag_second
297                 
298                 # the rest is presented in a list, available on the
299                 # fourth ("blue") button
300                 if len(self.tags) > 2:
301                         self["key_blue"].text = _("Other...")
302                 else:
303                         self["key_blue"].text = ""
304
305         def setListType(self, type):
306                 self["list"].setListType(type)
307
308         def setDescriptionState(self, val):
309                 self["list"].setDescriptionState(val)
310
311         def setSortType(self, type):
312                 self["list"].setSortType(type)
313
314         def reloadList(self):
315                 self["list"].reload(self.current_ref, self.selected_tags)
316                 title = _("Recorded files...")
317                 if self.selected_tags is not None:
318                         title += " - " + ','.join(self.selected_tags)
319                 self.setTitle(title)
320
321         def showAll(self):
322                 self.selected_tags = None
323                 self.reloadList()
324
325         def showTagsN(self, n):
326                 if len(self.tags) < n:
327                         self.showTagWarning()
328                 else:
329                         print "select tag #%d, %s, %s" % (n, self.tags[n - 1], ','.join(self.tags))
330                         self.selected_tags = set([self.tags[n - 1]])
331                         self.reloadList()
332
333         def showTagsFirst(self):
334                 self.showTagsN(1)
335
336         def showTagsSecond(self):
337                 self.showTagsN(2)
338
339         def tagChosen(self, tag):
340                 if tag is not None:
341                         self.selected_tags = set([tag[0]])
342                         self.reloadList()
343
344         def showTagsMenu(self):
345                 if len(self.tags) < 3:
346                         self.showTagWarning()
347                 else:
348                         list = [(tag, self.getTagDescription(tag)) for tag in self.tags ]
349                         self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select keyword to filter..."), list = list)
350
351         def showTagWarning(self):
352                 # TODO
353                 self.session.open(MessageBox, _("You need to define some keywords first!\nPress the menu-key to define keywords.\nDo you want to define keywords now?"), MessageBox.TYPE_ERROR)