=== modified file 'xl/library.py' --- xl/library.py 2008-02-12 18:02:21 +0000 +++ xl/library.py 2008-03-24 20:24:16 +0000 @@ -93,6 +93,21 @@ for track in tracks: self.append(track) + def sort(self, bys=()): + if not bys: + self._inner.sort() + else: + tmp = [] + lwr = lambda s: type(s) is not int and s.lower() or s + for track in self._inner: + tmp.append(([lwr(getattr(track,by)) for by in bys], track)) + tmp.sort() + self._inner = [t[1] for t in tmp] + self.paths = dict((t.loc, (t,i)) for (i,t) in enumerate(self._inner)) + + def __contains__(self, value): + return value.loc in self.paths + def __getitem__(self, index): return self._inner[index] @@ -102,21 +117,24 @@ del self.paths[old.loc] except KeyError: pass - self.paths[value.loc] = value + self.paths[value.loc] = (value,index) self._inner[index] = value def __len__(self): return len(self._inner) def index(self, item): - return self._inner.index(item) + try: + return self.paths[item.loc][1] + except KeyError: + raise ValueError, "list.index(x): x not in list" def append(self, track): """ Adds a track to the list """ if not track: return - self.paths[track.loc] = track + self.paths[track.loc] = (track, len(self._inner)) self._inner.append(track) self.update_total_length(track.get_duration(), appending=True) @@ -126,11 +144,12 @@ """ if not track: return try: + i = self.paths[track.loc][1] del self.paths[track.loc] except KeyError: return else: - self._inner.remove(track) + del self._inner[i] self.update_total_length(track.get_duration(), appending=False) def update_total_length(self, track_duration, appending): @@ -173,7 +192,9 @@ """ Returns the track associated with the path, or None """ - return self.paths.get(path) + pair = self.paths.get(path) + if pair: return pair[0] + return None def search(exaile, all, keyword=None, custom=True): """ @@ -200,9 +221,10 @@ items = [] args = [] where = "" - if keyword != None and w: + if w and keyword: regex = re.compile("\s+WHERE\s", re.DOTALL) w = regex.sub(" AND ", w) + if keyword != None: tokens = keyword.lower().split(' ') anditems = [] @@ -396,7 +418,7 @@ db._close_thread() return tracks -def scan_dir(dir, files=None, skip=(), exts=(), scanned=None): +def scan_dir(dir, skip=(), exts=(), scanned=None): """ Scans a directory recursively """ @@ -404,8 +426,6 @@ if skip: match_string = r"^.*(" + r"|".join(skip) + r").*$" regex = re.compile(match_string) - if files is None: - files = [] if scanned is None: scanned = set() @@ -413,9 +433,9 @@ dir = os.path.realpath(dir) to_scan = os.listdir(dir) except OSError: - return files + return - if dir in scanned: return files + if dir in scanned: return scanned.add(dir) for file in to_scan: @@ -429,33 +449,29 @@ continue try: - if os.path.isdir(file): - if regex and regex.match(file): continue - scan_dir(file, files=files, skip=skip, exts=exts, scanned=scanned) + if regex and regex.match(file): continue + for p in scan_dir(file, skip=skip, exts=exts, scanned=scanned): + yield p except: xlmisc.log("Error scanning %s" % file) traceback.print_exc() try: (stuff, ext) = os.path.splitext(file) - if ext.lower() in exts and not file in files: - files.append(file) + if ext.lower() in exts: + yield file except: traceback.print_exc() continue - return files - def count_files(directories, skip=()): """ Recursively counts the number of supported files in the specified directories """ - paths = [] for dir in directories: - paths.extend(scan_dir(dir, skip=skip, exts=media.SUPPORTED_MEDIA)) - - return paths + for p in scan_dir(dir, skip=skip, exts=media.SUPPORTED_MEDIA): + yield p @common.threaded def get_cddb_info(songs, disc_info, exaile): @@ -697,7 +713,7 @@ skip = self.exaile.settings.get_list('scan_ignore', default=['incomplete']) - paths = count_files(directories, skip) + paths = list(count_files(directories, skip)) total = len(paths) xlmisc.log("File count: %d" % total) @@ -992,7 +1008,7 @@ if not updating: xlmisc.log("loading songs") gobject.idle_add(self.exaile.playlists_panel.load_playlists) - gobject.idle_add(self.exaile.collection_panel.load_tree, True) + gobject.idle_add(self.exaile.collection_panel.load_tree_reload, True) if first_run: gobject.idle_add(self.exaile.initialize) === modified file 'xl/panels/collection.py' --- xl/panels/collection.py 2008-02-14 15:17:07 +0000 +++ xl/panels/collection.py 2008-03-24 06:29:48 +0000 @@ -66,6 +66,14 @@ self.connect_id = None self.setup_widgets() playlist.create_rating_images(self) + self.image_map = { + "album": self.album_image, + "artist": self.artist_image, + "genre": self.genre_image, + "title": self.track_image, + "year": self.year_image, + } + def setup_widgets(self): """ @@ -77,7 +85,7 @@ active = self.exaile.settings.get_int('ui/%s_active_view' % self.name, 0) self.choice.set_active(active) self.xml.get_widget('%s_refresh_button' % self.name).connect('clicked', - self.load_tree) + self.load_tree_reload) self.xml.get_widget('%s_combo_box' % self.name).connect('changed', self.load_tree) self.filter = xlmisc.ClearEntry(self.key_release) @@ -443,7 +451,10 @@ """ return None - def load_tree(self, event=None): + def load_tree_reload(self, event=None): + self.load_tree(event=event, reload=True) + + def load_tree(self, event=None, reload=None): """ Builds the tree. If self.keyword is not None, it will start a timer that will expand each node until a node that matches the keyword @@ -475,24 +486,10 @@ self.tree.set_row_separator_func( lambda m, i: m.get_value(i, 1) is None) - # clear out the tracks if this is a first time load or the refresh - # button is pressed - if event: - xlmisc.log("Clearing tracks cache") - self.track_cache = dict() - self.model.clear() self.tree.set_model(self.model_blank) self.root = self.get_initial_root(self.model) - self.image_map = { - "album": self.album_image, - "artist": self.artist_image, - "genre": self.genre_image, - "title": self.track_image, - "year": self.year_image, - } - if self.keyword == "": self.keyword = None orders = ( @@ -504,34 +501,9 @@ ('year', 'album', 'artist', 'track', 'title'), ('artist', 'year', 'album', 'track', 'title') ) + self.order = orders[self.choice.get_active()] - o_map = { - 'album': 'LSTRIP_SPEC(albums.name), disc_id', - 'artist': 'LSTRIP_SPEC(THE_CUTTER(artists.name))', - 'genre': 'LSTRIP_SPEC(genre)', - 'title': 'LSTRIP_SPEC(title)', - 'track': 'track', - 'year' : 'LSTRIP_SPEC(year)', - } - order_by = ', '.join((o_map[o] for o in self.order)) - - self.where = """ - SELECT - paths.name - FROM tracks, albums, paths, artists - WHERE - blacklisted=0 AND - ( - paths.id=tracks.path AND - albums.id=tracks.album AND - artists.id=tracks.artist - ) - ORDER BY - %s - """ % order_by - - # save the active view setting self.exaile.settings['ui/%s_active_view' % self.name] = self.choice.get_active() @@ -546,24 +518,44 @@ if isinstance(self, device.DevicePanel): self.all = None - songs = None - key = "%s %s" % (self.where, self.keyword) - try: - songs = self.track_cache[key] - except: - pass - - if not songs or self.name== 'device': + # clear out the tracks if this is a first time load or the refresh + # button is pressed + if reload: + xlmisc.log("Clearing tracks cache") + self.track_cache = dict() + self.where = """ + SELECT + paths.name + FROM tracks, albums, paths, artists + WHERE + blacklisted=0 AND + ( + paths.id=tracks.path AND + albums.id=tracks.album AND + artists.id=tracks.artist + ) + """ songs = self.search_tracks(self.keyword, self.all) - self.track_cache[key] = songs - - if self.current_start_count != self.start_count: return - + self.track_cache[self.keyword] = songs + else: + self.where = None + if self.name == 'col' and not self.keyword: + songs = self.all + else: + kwd = self.keywod + songs = self.track_cache.get(kwd, None) + if not songs or self.name == 'device': + songs = self.search_tracks(kwd, self.all) + self.track_cache[kwd] = songs + songs.sort(bys=self.order) + if self.start_count != self.current_start_count: return self.append_info(self.root, songs) - - if self.connect_id: gobject.source_remove(self.connect_id) + if self.connect_id: + gobject.source_remove(self.connect_id) self.connect_id = None self.filter.set_sensitive(True) + return + def search_tracks(self, keyword, all): """ @@ -608,14 +600,12 @@ Only the very last item of self.order will be a child node """ - order_nodes = common.idict() + order_nodes = {} order = [] last_songs = [] for field in self.order: if field == "track": continue order.append(field) - - for field in order: order_nodes[field] = common.idict() expanded_paths = [] @@ -630,17 +620,16 @@ first = True for field in order: node_for = order_nodes[field] - if field == "track": continue info = getattr(track, field) # print separators if first and info and use_alphabet: - temp = library.the_cutter(library.lstrip_special(info).upper()).upper() + temp = library.the_cutter(library.lstrip_special(info)) if not temp: first_char = ' ' else: - first_char = temp[0] + first_char = temp[0].upper() if not last_char: # First row, don't add separator. last_char = first_char if first_char != last_char: