From 77875ee3d3363dc525166f2a320ad3c968b0cfde Mon Sep 17 00:00:00 2001 From: nikosapi Date: Sat, 6 Sep 2008 16:34:35 -0400 Subject: [PATCH] First step in reducing unneeded full refreshes of treeChannels libpodcasts.py: Moved a bunch of code from channels_to_model to update_channel_model_by_iter, a new method which allows updating of individual iters in a model. gui.py: Added only_selected_channel option to updateComboBox which makes it only update the selected channel's iter. This saves a bit of time when doing simple tasks like marking an episode as played. So far only playback_episode and for_each_selected_episode_url take advantage of this option. --- src/gpodder/gui.py | 66 ++++++++++++++++++-------------- src/gpodder/libpodcasts.py | 94 ++++++++++++++++++++++++---------------------- 2 files changed, 87 insertions(+), 73 deletions(-) diff --git a/src/gpodder/gui.py b/src/gpodder/gui.py index fd9c43a5..040307fb 100644 --- a/src/gpodder/gui.py +++ b/src/gpodder/gui.py @@ -60,6 +60,7 @@ from libpodcasts import podcastChannel from libpodcasts import LocalDBReader from libpodcasts import podcastItem from libpodcasts import channels_to_model +from libpodcasts import update_channel_model_by_iter from libpodcasts import load_channels from libpodcasts import update_channels from libpodcasts import save_channels @@ -1028,7 +1029,7 @@ class gPodder(GladeWidget): (success, application) = gl.playback_episode(episode) if not success: self.show_message( _('The selected player application cannot be found. Please check your media player settings in the preferences dialog.'), _('Error opening player: %s') % ( saxutils.escape( application), )) - self.download_status_updated() + self.updateComboBox(only_selected_channel=True) def treeAvailable_search_equal( self, model, column, key, iter, data = None): if model is None: @@ -1159,38 +1160,46 @@ class gPodder(GladeWidget): def on_cbMaxDownloads_toggled(self, widget, *args): self.spinMaxDownloads.set_sensitive(self.cbMaxDownloads.get_active()) - + def on_cbLimitDownloads_toggled(self, widget, *args): self.spinLimitDownloads.set_sensitive(self.cbLimitDownloads.get_active()) - def updateComboBox(self, selected_url=None): + def updateComboBox(self, selected_url=None, only_selected_channel=False): (model, iter) = self.treeChannels.get_selection().get_selected() - if model and iter and selected_url is None: - # Get the URL of the currently-selected podcast - selected_url = model.get_value(iter, 0) - - rect = self.treeChannels.get_visible_rect() - self.treeChannels.set_model(channels_to_model(self.channels, self.channel_colors, self.cover_cache, gl.config.podcast_list_icon_size, gl.config.podcast_list_icon_size)) - util.idle_add(self.treeChannels.scroll_to_point, rect.x, rect.y) + if only_selected_channel: + if iter and self.active_channel is not None: + update_channel_model_by_iter( self.treeChannels.get_model(), + iter, self.active_channel, self.channel_colors, + self.cover_cache, *(gl.config.podcast_list_icon_size,)*2 ) + else: + if model and iter and selected_url is None: + # Get the URL of the currently-selected podcast + selected_url = model.get_value(iter, 0) - try: - selected_path = (0,) - # Find the previously-selected URL in the new - # model if we have an URL (else select first) - if selected_url is not None: - model = self.treeChannels.get_model() - pos = model.get_iter_first() - while pos is not None: - url = model.get_value(pos, 0) - if url == selected_url: - selected_path = model.get_path(pos) - break - pos = model.iter_next(pos) + rect = self.treeChannels.get_visible_rect() + self.treeChannels.set_model( channels_to_model( self.channels, + self.channel_colors, self.cover_cache, + *(gl.config.podcast_list_icon_size,)*2 )) + util.idle_add(self.treeChannels.scroll_to_point, rect.x, rect.y) - self.treeChannels.get_selection().select_path(selected_path) - except: - log( 'Cannot set selection on treeChannels', sender = self) + try: + selected_path = (0,) + # Find the previously-selected URL in the new + # model if we have an URL (else select first) + if selected_url is not None: + model = self.treeChannels.get_model() + pos = model.get_iter_first() + while pos is not None: + url = model.get_value(pos, 0) + if url == selected_url: + selected_path = model.get_path(pos) + break + pos = model.iter_next(pos) + + self.treeChannels.get_selection().select_path(selected_path) + except: + log( 'Cannot set selection on treeChannels', sender = self) self.on_treeChannels_cursor_changed( self.treeChannels) def updateTreeView( self): @@ -1526,12 +1535,13 @@ class gPodder(GladeWidget): callback( url) except Exception, e: log( 'Warning: Error in for_each_selected_episode_url for URL %s: %s', url, e, sender = self) - self.updateComboBox() + + self.updateComboBox(only_selected_channel=True) def delete_episode_list( self, episodes, confirm = True): if len(episodes) == 0: return - + if len(episodes) == 1: message = _('Do you really want to delete this episode?') else: diff --git a/src/gpodder/libpodcasts.py b/src/gpodder/libpodcasts.py index 527eadbc..b1fb119f 100644 --- a/src/gpodder/libpodcasts.py +++ b/src/gpodder/libpodcasts.py @@ -693,58 +693,62 @@ class podcastItem(object): +def update_channel_model_by_iter( model, iter, channel, color_dict, + cover_cache=None, max_width=0, max_height=0 ): + + count_downloaded = channel.stat(state=db.STATE_DOWNLOADED) + count_new = channel.stat(state=db.STATE_NORMAL, is_played=False) + count_unplayed = channel.stat(state=db.STATE_DOWNLOADED, is_played=False) + + channel.iter = iter + model.set(iter, 0, channel.url) + model.set(iter, 1, channel.title) + + title_markup = saxutils.escape(channel.title) + description_markup = saxutils.escape(util.get_first_line(channel.description) or _('No description available')) + d = [] + if count_new: + d.append('') + d.append(title_markup) + if count_new: + d.append('') + + description = ''.join(d+['\n', '', description_markup, '']) + model.set(iter, 2, description) + + if channel.parse_error is not None: + model.set(iter, 6, channel.parse_error) + color = color_dict['parse_error'] + else: + color = color_dict['default'] + + if channel.update_flag: + color = color_dict['updating'] + + model.set(iter, 8, color) + + if count_unplayed > 0 or count_downloaded > 0: + model.set(iter, 3, draw.draw_pill_pixbuf(str(count_unplayed), str(count_downloaded))) + model.set(iter, 7, True) + else: + model.set(iter, 7, False) + + # Load the cover if we have it, but don't download + # it if it's not available (to avoid blocking here) + pixbuf = services.cover_downloader.get_cover(channel, avoid_downloading=True) + new_pixbuf = None + if pixbuf is not None: + new_pixbuf = util.resize_pixbuf_keep_ratio(pixbuf, max_width, max_height, channel.url, cover_cache) + model.set(iter, 5, new_pixbuf or pixbuf) def channels_to_model(channels, color_dict, cover_cache=None, max_width=0, max_height=0): new_model = gtk.ListStore( str, str, str, gtk.gdk.Pixbuf, int, gtk.gdk.Pixbuf, str, bool, str ) for channel in channels: - count_downloaded = channel.stat(state=db.STATE_DOWNLOADED) - count_new = channel.stat(state=db.STATE_NORMAL, is_played=False) - count_unplayed = channel.stat(state=db.STATE_DOWNLOADED, is_played=False) - - new_iter = new_model.append() - channel.iter = new_iter - new_model.set(new_iter, 0, channel.url) - new_model.set(new_iter, 1, channel.title) - - title_markup = saxutils.escape(channel.title) - description_markup = saxutils.escape(util.get_first_line(channel.description) or _('No description available')) - d = [] - if count_new: - d.append('') - d.append(title_markup) - if count_new: - d.append('') - - description = ''.join(d+['\n', '', description_markup, '']) - new_model.set(new_iter, 2, description) - - if channel.parse_error is not None: - new_model.set(new_iter, 6, channel.parse_error) - color = color_dict['parse_error'] - else: - color = color_dict['default'] - - if channel.update_flag: - color = color_dict['updating'] - - new_model.set(new_iter, 8, color) + update_channel_model_by_iter( new_model, new_model.append(), channel, + color_dict, cover_cache, max_width, max_height ) - if count_unplayed > 0 or count_downloaded > 0: - new_model.set(new_iter, 3, draw.draw_pill_pixbuf(str(count_unplayed), str(count_downloaded))) - new_model.set(new_iter, 7, True) - else: - new_model.set(new_iter, 7, False) - - # Load the cover if we have it, but don't download - # it if it's not available (to avoid blocking here) - pixbuf = services.cover_downloader.get_cover(channel, avoid_downloading=True) - new_pixbuf = None - if pixbuf is not None: - new_pixbuf = util.resize_pixbuf_keep_ratio(pixbuf, max_width, max_height, channel.url, cover_cache) - new_model.set(new_iter, 5, new_pixbuf or pixbuf) - return new_model -- 2.11.4.GIT