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