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