def insertDir(self, trackdir, target=None, drop_mode=None, highlight=False): ''' Insert a directory recursively, return the iter of the first added element ''' model = self.tree.store if trackdir.flat: new = target else: string = trackdir.dirname.replace('_', ' ') string = tools.htmlEscape(string) source_row = (icons.mediaDirMenuIcon(), string, None) new = self.tree.insert(target, source_row, drop_mode) drop_mode = gtk.TREE_VIEW_DROP_INTO_OR_AFTER if highlight: self.tree.select(new) dest = new for index, subdir in enumerate(trackdir.subdirs): drop = drop_mode if index == 0 else gtk.TREE_VIEW_DROP_AFTER dest = self.insertDir(subdir, dest, drop, highlight) dest = new for index, track in enumerate(trackdir.tracks): drop = drop_mode if index == 0 else gtk.TREE_VIEW_DROP_AFTER highlight &= trackdir.flat dest = self.insertTrack(track, dest, drop, highlight) if not trackdir.flat: # Open albums on the first layer if target is None or model.iter_depth(new) == 0: self.tree.expand(new) return new
def insertDir(self, trackdir, target=None, drop_mode=None, highlight=False): ''' Insert a directory recursively, return the iter of the first added element ''' model = self.tree.store if trackdir.flat: new = target else: string = trackdir.dirname.replace('_', ' ') string = tools.htmlEscape(string) source_row = (icons.mediaDirMenuIcon(), string, None) new = self.tree.insert(target, source_row, drop_mode) drop_mode = Gtk.TreeViewDropPosition.INTO_OR_AFTER if highlight: self.tree.select(new) dest = new for index, subdir in enumerate(trackdir.subdirs): drop = drop_mode if index == 0 else Gtk.TreeViewDropPosition.AFTER dest = self.insertDir(subdir, dest, drop, highlight) dest = new for index, track in enumerate(trackdir.tracks): drop = drop_mode if index == 0 else Gtk.TreeViewDropPosition.AFTER highlight &= trackdir.flat dest = self.insertTrack(track, dest, drop, highlight) if not trackdir.flat: # Open albums on the first layer if target is None or model.iter_depth(new) == 0: self.tree.expand(new) return new
def set_track_playing(self, iter, playing): if not iter: return track = self.tree.getTrack(iter) if not track: return for parent in self.tree.get_all_parents(iter): parent_label = self.tree.getLabel(parent) parent_label = tools.htmlUnescape(parent_label) is_bold = parent_label.startswith('<b>') and parent_label.endswith('</b>') if playing and not is_bold: parent_label = tools.htmlEscape(parent_label) self.tree.setLabel(parent, '<b>%s</b>' % parent_label) elif not playing and is_bold: parent_label = tools.htmlEscape(parent_label[3:-4]) self.tree.setLabel(parent, parent_label) parent = self.tree.store.iter_parent(iter) parent_label = self.tree.getLabel(parent) if parent else None label = track.get_label(parent_label=parent_label, playing=playing) if playing: self.tree.setLabel(iter, label) self.tree.setItem(iter, ROW_ICO, icons.playMenuIcon()) self.tree.expand(iter) else: self.tree.setLabel(iter, label) icon = self.tree.getItem(iter, ROW_ICO) has_error = (icon == icons.errorMenuIcon()) is_dir = (icon == icons.mediaDirMenuIcon()) if not is_dir and not has_error: self.tree.setItem(iter, ROW_ICO, icons.nullMenuIcon())
def set_track_playing(self, iter, playing): if not iter: return track = self.tree.getTrack(iter) if not track: return for parent in self.tree.get_all_parents(iter): parent_label = self.tree.getLabel(parent) parent_label = tools.htmlUnescape(parent_label) is_bold = parent_label.startswith('<b>') and parent_label.endswith('</b>') if playing and not is_bold: parent_label = tools.htmlEscape(parent_label) self.tree.setLabel(parent, '<b>%s</b>' % parent_label) elif not playing and is_bold: parent_label = tools.htmlEscape(parent_label[3:-4]) self.tree.setLabel(parent, parent_label) parent = self.tree.store.iter_parent(iter) parent_label = self.tree.getLabel(parent) if parent else None label = track.get_label(parent_label=parent_label, playing=playing) if playing: self.tree.setLabel(iter, label) self.tree.setItem(iter, ROW_ICO, icons.playMenuIcon()) self.tree.expand(iter) else: self.tree.setLabel(iter, label) icon = self.tree.getItem(iter, ROW_ICO) has_error = (icon == icons.errorMenuIcon()) is_dir = (icon == icons.mediaDirMenuIcon()) if not is_dir and not has_error: self.tree.setItem(iter, ROW_ICO, icons.nullMenuIcon())
def loadAlbums(self, tree, node, fakeChild): """ Initial load of the albums of the given node, assuming it is of type TYPE_ARTIST """ rows = [] path = tree.getItem(node, ROW_FULLPATH) artist = tree.getItem(node, ROW_DATA) allAlbums = pickleLoad(os.path.join(tree.getItem(node, ROW_FULLPATH), 'albums')) # Filter albums if only favorites should be shown if self.showOnlyFavs: allAlbums = [album for album in allAlbums if self.isAlbumInFavorites(artist, album[ALB_NAME])] # Filter artists by genre if needed if self.currGenre is not None: allAlbums = [album for album in allAlbums if album[ALB_NAME] in self.allGenres[self.currGenre][artist]] # The icon depends on whether the album is in the favorites for album in allAlbums: if self.isAlbumInFavorites(artist, album[ALB_NAME]): icon = icons.starDirMenuIcon() else: icon = icons.mediaDirMenuIcon() rows.append((icon, '[%s]' % tools.sec2str(album[ALB_LENGTH], True), '%s' % htmlEscape(album[ALB_NAME]), TYPE_ALBUM, os.path.join(path, album[ALB_INDEX]), album[ALB_NAME])) # Add all the rows, and then add a fake child to each of them tree.appendRows(rows, node) tree.removeRow(fakeChild) for child in tree.iterChildren(node): tree.appendRow(FAKE_CHILD, child)
def restoreTreeDump(self, dump, parent=None): """ Recursively restore the dump under the given parent (None for the root of the tree) """ for item in dump: (name, track) = item[0] if track: self.tree.appendRow((icons.nullMenuIcon(), name, track), parent) else: newNode = self.tree.appendRow((icons.mediaDirMenuIcon(), name, None), parent) if item[1] is not None: if len(item[1]) != 0: # We must expand the row before adding the real children, # but this works only if there is already at least one child self.restoreTreeDump(item[1], newNode)
def restoreTreeDump(self, dump, parent=None): """ Recursively restore the dump under the given parent (None for the root of the tree) """ for item in dump: (name, track) = item[0] if track: self.tree.appendRow((icons.nullMenuIcon(), name, track), parent) else: newNode = self.tree.appendRow((icons.mediaDirMenuIcon(), name, None), parent) if item[1] is not None: if len(item[1]) != 0: # We must expand the row before adding the real children, # but this works only if there is already at least one child self.restoreTreeDump(item[1], newNode)
def switchFavoriteStateOfSelectedItems(self, tree): """ Add to/remove from favorites the selected items """ # Go through selected items and switch their state removed = False for path in tree.getSelectedPaths(): if tree.getItem(path, ROW_TYPE) == TYPE_ALBUM: album = tree.getItem(path, ROW_DATA) artist = tree.getItem(path[:-1], ROW_DATA) if self.isAlbumInFavorites(artist, album): removed = True tree.setItem(path, ROW_PIXBUF, icons.mediaDirMenuIcon()) self.removeFromFavorites(artist, album) else: tree.setItem(path, ROW_PIXBUF, icons.starDirMenuIcon()) self.addToFavorites(artist, album) # If some favorites were removed, we may have to reload the tree if self.showOnlyFavs and removed: self.saveTreeState() self.loadArtists(self.tree, self.currLib) self.restoreTreeState()
def showPopupMenu(self, tree, button, time, path): """ Show a popup menu """ popup = gtk.Menu() # Play play = gtk.ImageMenuItem(gtk.STOCK_MEDIA_PLAY) popup.append(play) if path is None: play.set_sensitive(False) else: play.connect('activate', lambda widget: self.playPaths(tree, None, True)) # Add add = gtk.ImageMenuItem(gtk.STOCK_ADD) popup.append(add) if path is None: add.set_sensitive(False) else: add.connect('activate', lambda widget: self.playPaths(tree, None, False)) # Separator popup.append(gtk.SeparatorMenuItem()) # Add to/remove from favorites favCpt = 0 nonFavCpt = 0 for node in tree.getSelectedPaths(): if tree.getItem(node, ROW_TYPE) != TYPE_ALBUM: favCpt = 1 nonFavCpt = 1 break elif tree.getItem(node, ROW_PIXBUF) == icons.mediaDirMenuIcon(): nonFavCpt += 1 else: favCpt += 1 if favCpt == 0: favorite = gtk.ImageMenuItem(_('Add to Favorites')) elif nonFavCpt == 0: favorite = gtk.ImageMenuItem(_('Remove from Favorites')) else: favorite = gtk.ImageMenuItem(_('Favorites')) favorite.get_image().set_from_pixbuf(icons.starMenuIcon()) popup.append(favorite) if TYPE_ALBUM in [tree.getItem(path, ROW_TYPE) for path in tree.getSelectedPaths()]: favorite.connect('activate', lambda widget: self.switchFavoriteStateOfSelectedItems(tree)) else: favorite.set_sensitive(False) # Show only favorites showFavorites = gtk.CheckMenuItem(_('Show Only Favorites')) showFavorites.set_active(self.showOnlyFavs) showFavorites.connect('toggled', lambda widget: self.switchFavoritesView(tree)) popup.append(showFavorites) # Separator popup.append(gtk.SeparatorMenuItem()) # Filter by genre genresMenu = gtk.Menu() filterGenre = gtk.MenuItem(_("Filter by Genre")); filterGenre.set_submenu(genresMenu) popup.append(filterGenre) # Need to keep the mapping widget -> genre to handle activate events self.genreItemToName = {} for genre in sorted(self.allGenres): genreItem = gtk.CheckMenuItem(genre.capitalize()) genreItem.set_active(genre == self.currGenre) self.genreItemToName[genreItem] = genre genreItem.connect('activate', lambda widget: self.filterByGenre(self.genreItemToName[widget])) genresMenu.append(genreItem) genresMenu.append(gtk.SeparatorMenuItem()) genreItem = gtk.CheckMenuItem(_('Unfiltered')) genreItem.set_active(self.currGenre == None) genreItem.connect('activate', lambda widget: self.filterByGenre(None)) genresMenu.append(genreItem) # Separator popup.append(gtk.SeparatorMenuItem()) # Collapse all nodes collapse = gtk.ImageMenuItem(_('Collapse all')) collapse.set_image(gtk.image_new_from_stock(gtk.STOCK_CLEAR, gtk.ICON_SIZE_MENU)) popup.append(collapse) enabled = False for child in self.tree.iterChildren(None): if self.tree.row_expanded(child): enabled = True break if enabled: collapse.connect('activate', lambda widget: self.tree.collapse_all()) else: collapse.set_sensitive(False) # Refresh the library refresh = gtk.ImageMenuItem(gtk.STOCK_REFRESH) refresh.connect('activate', lambda widget: idle_add(self.refreshLibrary(None, self.currLib, self.libraries[self.currLib][LIB_PATH]).next)) popup.append(refresh) # Randomness randomness = gtk.Menu() randomnessItem = gtk.ImageMenuItem(_('Randomness')) randomnessItem.get_image().set_from_icon_name('stock_shuffle', gtk.ICON_SIZE_MENU) randomnessItem.set_submenu(randomness) popup.append(randomnessItem) # Random album of the selected artist if path is not None and tree.getItem(path, ROW_TYPE) == TYPE_ARTIST: album = gtk.MenuItem(_('Pick an album of %(artist)s' % {'artist': tree.getItem(path, ROW_NAME).replace('&', '&')})) album.connect('activate', lambda widget: self.pickAlbumArtist(tree, path)) randomness.append(album) # Random album in the entire library album = gtk.MenuItem(_('Pick an album in the library')) album.connect('activate', lambda widget: self.pickAlbumLibrary(tree)) randomness.append(album) popup.show_all() popup.popup(None, None, None, button, time)