Merge branch 'bug_236_recordpath'
[enigma2.git] / lib / python / Components / FileList.py
1 from re import compile as re_compile
2 from os import path as os_path, listdir
3 from MenuList import MenuList
4 from Components.Harddisk import harddiskmanager
5
6 from Tools.Directories import SCOPE_SKIN_IMAGE, resolveFilename, fileExists
7
8 from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, \
9         eServiceReference, eServiceCenter, gFont
10 from Tools.LoadPixmap import LoadPixmap
11
12 EXTENSIONS = {
13                 "m4a": "music",
14                 "mp2": "music",
15                 "mp3": "music",
16                 "wav": "music",
17                 "ogg": "music",
18                 "flac": "music",
19                 "jpg": "picture",
20                 "jpeg": "picture",
21                 "png": "picture",
22                 "bmp": "picture",
23                 "ts": "movie",
24                 "avi": "movie",
25                 "divx": "movie",
26                 "m4v": "movie",
27                 "mpg": "movie",
28                 "mpeg": "movie",
29                 "mkv": "movie",
30                 "mp4": "movie",
31                 "mov": "movie"
32         }
33
34 def FileEntryComponent(name, absolute = None, isDir = False):
35         res = [ (absolute, isDir) ]
36         res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 470, 20, 0, RT_HALIGN_LEFT, name))
37         if isDir:
38                 png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "extensions/directory.png"))
39         else:
40                 extension = name.split('.')
41                 extension = extension[-1].lower()
42                 if EXTENSIONS.has_key(extension):
43                         png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "extensions/" + EXTENSIONS[extension] + ".png"))
44                 else:
45                         png = None
46         if png is not None:
47                 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
48         
49         return res
50
51 class FileList(MenuList):
52         def __init__(self, directory, showDirectories = True, showFiles = True, showMountpoints = True, matchingPattern = None, useServiceRef = False, inhibitDirs = False, inhibitMounts = False, isTop = False, enableWrapAround = False, additionalExtensions = None):
53                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
54                 self.additional_extensions = additionalExtensions
55                 self.mountpoints = []
56                 self.current_directory = None
57                 self.current_mountpoint = None
58                 self.useServiceRef = useServiceRef
59                 self.showDirectories = showDirectories
60                 self.showMountpoints = showMountpoints
61                 self.showFiles = showFiles
62                 self.isTop = isTop
63                 # example: matching .nfi and .ts files: "^.*\.(nfi|ts)"
64                 self.matchingPattern = matchingPattern
65                 self.inhibitDirs = inhibitDirs or []
66                 self.inhibitMounts = inhibitMounts or []
67
68                 self.refreshMountpoints()
69                 self.changeDir(directory)
70                 self.l.setFont(0, gFont("Regular", 18))
71                 self.l.setItemHeight(23)
72                 self.serviceHandler = eServiceCenter.getInstance()
73
74         def refreshMountpoints(self):
75                 self.mountpoints = [os_path.join(p.mountpoint, "") for p in harddiskmanager.getMountedPartitions()]
76                 self.mountpoints.sort(reverse = True)
77
78         def getMountpoint(self, file):
79                 file = os_path.join(os_path.realpath(file), "")
80                 for m in self.mountpoints:
81                         if file.startswith(m):
82                                 return m
83                 return False
84
85         def getMountpointLink(self, file):
86                 if os_path.realpath(file) == file:
87                         return self.getMountpoint(file)
88                 else:
89                         if file[-1] == "/":
90                                 file = file[:-1]
91                         mp = self.getMountpoint(file)
92                         last = file
93                         file = os_path.dirname(file)
94                         while last != "/" and mp == self.getMountpoint(file):
95                                 last = file
96                                 file = os_path.dirname(file)
97                         return os_path.join(last, "")
98
99         def getSelection(self):
100                 if self.l.getCurrentSelection() is None:
101                         return None
102                 return self.l.getCurrentSelection()[0]
103
104         def getCurrentEvent(self):
105                 l = self.l.getCurrentSelection()
106                 if not l or l[0][1] == True:
107                         return None
108                 else:
109                         return self.serviceHandler.info(l[0][0]).getEvent(l[0][0])
110
111         def getFileList(self):
112                 return self.list
113
114         def inParentDirs(self, dir, parents):
115                 dir = os_path.realpath(dir)
116                 for p in parents:
117                         if dir.startswith(p):
118                                 return True
119                 return False
120
121         def changeDir(self, directory, select = None):
122                 self.list = []
123
124                 # if we are just entering from the list of mount points:
125                 if self.current_directory is None:
126                         if directory and self.showMountpoints:
127                                 self.current_mountpoint = self.getMountpointLink(directory)
128                         else:
129                                 self.current_mountpoint = None
130                 self.current_directory = directory
131                 directories = []
132                 files = []
133
134                 if directory is None and self.showMountpoints: # present available mountpoints
135                         for p in harddiskmanager.getMountedPartitions():
136                                 path = os_path.join(p.mountpoint, "")
137                                 if path not in self.inhibitMounts and not self.inParentDirs(path, self.inhibitDirs):
138                                         self.list.append(FileEntryComponent(name = p.description, absolute = path, isDir = True))
139                         files = [ ]
140                         directories = [ ]
141                 elif directory is None:
142                         files = [ ]
143                         directories = [ ]
144                 elif self.useServiceRef:
145                         root = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + directory)
146                         if self.additional_extensions:
147                                 root.setName(self.additional_extensions)
148                         serviceHandler = eServiceCenter.getInstance()
149                         list = serviceHandler.list(root)
150
151                         while 1:
152                                 s = list.getNext()
153                                 if not s.valid():
154                                         del list
155                                         break
156                                 if s.flags & s.mustDescent:
157                                         directories.append(s.getPath())
158                                 else:
159                                         files.append(s)
160                         directories.sort()
161                         files.sort()
162                 else:
163                         if fileExists(directory):
164                                 try:
165                                         files = listdir(directory)
166                                 except:
167                                         files = []
168                                 files.sort()
169                                 tmpfiles = files[:]
170                                 for x in tmpfiles:
171                                         if os_path.isdir(directory + x):
172                                                 directories.append(directory + x + "/")
173                                                 files.remove(x)
174
175                 if directory is not None and self.showDirectories and not self.isTop:
176                         if directory == self.current_mountpoint and self.showMountpoints:
177                                 self.list.append(FileEntryComponent(name = "<" +_("List of Storage Devices") + ">", absolute = None, isDir = True))
178                         elif (directory != "/") and not (self.inhibitMounts and self.getMountpoint(directory) in self.inhibitMounts):
179                                 self.list.append(FileEntryComponent(name = "<" +_("Parent Directory") + ">", absolute = '/'.join(directory.split('/')[:-2]) + '/', isDir = True))
180
181                 if self.showDirectories:
182                         for x in directories:
183                                 if not (self.inhibitMounts and self.getMountpoint(x) in self.inhibitMounts) and not self.inParentDirs(x, self.inhibitDirs):
184                                         name = x.split('/')[-2]
185                                         self.list.append(FileEntryComponent(name = name, absolute = x, isDir = True))
186
187                 if self.showFiles:
188                         for x in files:
189                                 if self.useServiceRef:
190                                         path = x.getPath()
191                                         name = path.split('/')[-1]
192                                 else:
193                                         path = directory + x
194                                         name = x
195
196                                 if (self.matchingPattern is None) or re_compile(self.matchingPattern).search(path):
197                                         self.list.append(FileEntryComponent(name = name, absolute = x , isDir = False))
198
199                 self.l.setList(self.list)
200
201                 if select is not None:
202                         i = 0
203                         self.moveToIndex(0)
204                         for x in self.list:
205                                 p = x[0][0]
206                                 
207                                 if isinstance(p, eServiceReference):
208                                         p = p.getPath()
209                                 
210                                 if p == select:
211                                         self.moveToIndex(i)
212                                 i += 1
213
214         def getCurrentDirectory(self):
215                 return self.current_directory
216
217         def canDescent(self):
218                 if self.getSelection() is None:
219                         return False
220                 return self.getSelection()[1]
221
222         def descent(self):
223                 if self.getSelection() is None:
224                         return
225                 self.changeDir(self.getSelection()[0], select = self.current_directory)
226
227         def getFilename(self):
228                 if self.getSelection() is None:
229                         return None
230                 x = self.getSelection()[0]
231                 if isinstance(x, eServiceReference):
232                         x = x.getPath()
233                 return x
234
235         def getServiceRef(self):
236                 if self.getSelection() is None:
237                         return None
238                 x = self.getSelection()[0]
239                 if isinstance(x, eServiceReference):
240                         return x
241                 return None
242
243         def execBegin(self):
244                 harddiskmanager.on_partition_list_change.append(self.partitionListChanged)
245
246         def execEnd(self):
247                 harddiskmanager.on_partition_list_change.remove(self.partitionListChanged)
248
249         def refresh(self):
250                 self.changeDir(self.current_directory, self.getFilename())
251
252         def partitionListChanged(self, action, device):
253                 self.refreshMountpoints()
254                 if self.current_directory is None:
255                         self.refresh()
256
257
258 def MultiFileSelectEntryComponent(name, absolute = None, isDir = False, selected = False):
259         res = [ (absolute, isDir, selected, name) ]
260         res.append((eListboxPythonMultiContent.TYPE_TEXT, 55, 1, 470, 20, 0, RT_HALIGN_LEFT, name))
261         if isDir:
262                 png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "extensions/directory.png"))
263         else:
264                 extension = name.split('.')
265                 extension = extension[-1].lower()
266                 if EXTENSIONS.has_key(extension):
267                         png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "extensions/" + EXTENSIONS[extension] + ".png"))
268                 else:
269                         png = None
270         if png is not None:
271                 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 30, 2, 20, 20, png))
272
273         if not name.startswith('<'):
274                 if selected is False:
275                         icon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_off.png"))
276                         res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 2, 0, 25, 25, icon))
277                 else:
278                         icon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_on.png"))
279                         res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 2, 0, 25, 25, icon))
280         
281         return res
282
283
284 class MultiFileSelectList(FileList):
285         def __init__(self, preselectedFiles, directory, showMountpoints = False, matchingPattern = None, showDirectories = True, showFiles = True,  useServiceRef = False, inhibitDirs = False, inhibitMounts = False, isTop = False, enableWrapAround = False, additionalExtensions = None):
286                 self.selectedFiles = preselectedFiles
287                 if self.selectedFiles is None:
288                         self.selectedFiles = []
289                 FileList.__init__(self, directory, showMountpoints = showMountpoints, matchingPattern = matchingPattern, showDirectories = showDirectories, showFiles = showFiles,  useServiceRef = useServiceRef, inhibitDirs = inhibitDirs, inhibitMounts = inhibitMounts, isTop = isTop, enableWrapAround = enableWrapAround, additionalExtensions = additionalExtensions)
290                 self.changeDir(directory)                       
291                 self.l.setItemHeight(25)
292                 self.l.setFont(0, gFont("Regular", 20))
293                 self.onSelectionChanged = [ ]
294
295         def selectionChanged(self):
296                 for f in self.onSelectionChanged:
297                         f()
298
299         def changeSelectionState(self):
300                 idx = self.l.getCurrentSelectionIndex()
301                 count = 0
302                 newList = []
303                 for x in self.list:
304                         if idx == count:
305                                 if x[0][3].startswith('<'):
306                                         newList.append(x)
307                                 else:
308                                         if x[0][1] is True:
309                                                 realPathname = x[0][0]
310                                         else:
311                                                 realPathname = self.current_directory + x[0][0]
312                                         if x[0][2] == True:
313                                                 SelectState = False
314                                                 for entry in self.selectedFiles:
315                                                         if entry == realPathname:
316                                                                 self.selectedFiles.remove(entry)
317         
318                                         else:
319                                                 SelectState = True
320                                                 alreadyinList = False   
321                                                 for entry in self.selectedFiles:
322                                                         if entry == realPathname:
323                                                                 alreadyinList = True
324                                                 if not alreadyinList:
325                                                         self.selectedFiles.append(realPathname)
326                                         newList.append(MultiFileSelectEntryComponent(name = x[0][3], absolute = x[0][0], isDir = x[0][1], selected = SelectState ))
327                         else:
328                                 newList.append(x)
329                         
330                         count += 1
331                 
332                 self.list = newList
333                 self.l.setList(self.list)
334         
335         def getSelectedList(self):
336                 return self.selectedFiles
337
338         def changeDir(self, directory, select = None):
339                 self.list = []
340
341                 # if we are just entering from the list of mount points:
342                 if self.current_directory is None:
343                         if directory and self.showMountpoints:
344                                 self.current_mountpoint = self.getMountpointLink(directory)
345                         else:
346                                 self.current_mountpoint = None
347                 self.current_directory = directory
348                 directories = []
349                 files = []
350
351                 if directory is None and self.showMountpoints: # present available mountpoints
352                         for p in harddiskmanager.getMountedPartitions():
353                                 path = os_path.join(p.mountpoint, "")
354                                 if path not in self.inhibitMounts and not self.inParentDirs(path, self.inhibitDirs):
355                                         self.list.append(MultiFileSelectEntryComponent(name = p.description, absolute = path, isDir = True))
356                         files = [ ]
357                         directories = [ ]
358                 elif directory is None:
359                         files = [ ]
360                         directories = [ ]
361                 elif self.useServiceRef:
362                         root = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + directory)
363                         if self.additional_extensions:
364                                 root.setName(self.additional_extensions)
365                         serviceHandler = eServiceCenter.getInstance()
366                         list = serviceHandler.list(root)
367
368                         while 1:
369                                 s = list.getNext()
370                                 if not s.valid():
371                                         del list
372                                         break
373                                 if s.flags & s.mustDescent:
374                                         directories.append(s.getPath())
375                                 else:
376                                         files.append(s)
377                         directories.sort()
378                         files.sort()
379                 else:
380                         if fileExists(directory):
381                                 try:
382                                         files = listdir(directory)
383                                 except:
384                                         files = []
385                                 files.sort()
386                                 tmpfiles = files[:]
387                                 for x in tmpfiles:
388                                         if os_path.isdir(directory + x):
389                                                 directories.append(directory + x + "/")
390                                                 files.remove(x)
391
392                 if directory is not None and self.showDirectories and not self.isTop:
393                         if directory == self.current_mountpoint and self.showMountpoints:
394                                 self.list.append(MultiFileSelectEntryComponent(name = "<" +_("List of Storage Devices") + ">", absolute = None, isDir = True))
395                         elif (directory != "/") and not (self.inhibitMounts and self.getMountpoint(directory) in self.inhibitMounts):
396                                 self.list.append(MultiFileSelectEntryComponent(name = "<" +_("Parent Directory") + ">", absolute = '/'.join(directory.split('/')[:-2]) + '/', isDir = True))
397
398                 if self.showDirectories:
399                         for x in directories:
400                                 if not (self.inhibitMounts and self.getMountpoint(x) in self.inhibitMounts) and not self.inParentDirs(x, self.inhibitDirs):
401                                         name = x.split('/')[-2]
402                                         alreadySelected = False
403                                         for entry in self.selectedFiles:
404                                                 if entry  == x:
405                                                         alreadySelected = True                                  
406                                         if alreadySelected:             
407                                                 self.list.append(MultiFileSelectEntryComponent(name = name, absolute = x, isDir = True, selected = True))
408                                         else:
409                                                 self.list.append(MultiFileSelectEntryComponent(name = name, absolute = x, isDir = True, selected = False))
410                                                 
411                 if self.showFiles:
412                         for x in files:
413                                 if self.useServiceRef:
414                                         path = x.getPath()
415                                         name = path.split('/')[-1]
416                                 else:
417                                         path = directory + x
418                                         name = x
419
420                                 if (self.matchingPattern is None) or re_compile(self.matchingPattern).search(path):
421                                         alreadySelected = False
422                                         for entry in self.selectedFiles:
423                                                 if os_path.basename(entry)  == x:
424                                                         alreadySelected = True  
425                                         if alreadySelected:
426                                                 self.list.append(MultiFileSelectEntryComponent(name = name, absolute = x , isDir = False, selected = True))
427                                         else:
428                                                 self.list.append(MultiFileSelectEntryComponent(name = name, absolute = x , isDir = False, selected = False))
429
430                 self.l.setList(self.list)
431
432                 if select is not None:
433                         i = 0
434                         self.moveToIndex(0)
435                         for x in self.list:
436                                 p = x[0][0]
437                                 
438                                 if isinstance(p, eServiceReference):
439                                         p = p.getPath()
440                                 
441                                 if p == select:
442                                         self.moveToIndex(i)
443                                 i += 1
444