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