Make DownloadTask a child of PodcastEpisode

This commit is contained in:
Thomas Perl 2011-07-16 18:04:07 +02:00
parent 7ddb2eb354
commit d714be329e
7 changed files with 60 additions and 60 deletions

View File

@ -367,6 +367,7 @@ class DownloadQueueWorker(threading.Thread):
task = self.queue.pop()
logger.info('%s is processing: %s', self.getName(), task)
task.run()
task.recycle()
except IndexError, e:
logger.info('No more tasks for %s to carry out.', self.getName())
break
@ -565,11 +566,16 @@ class DownloadTask(object):
episode = property(fget=__get_episode)
def cancel(self):
if self.status in (self.DOWNLOADING, self.QUEUED):
self.status = self.CANCELLED
def removed_from_list(self):
if self.status != self.DONE:
util.delete_file(self.tempname)
def __init__(self, episode, config):
assert episode.download_task is None
self.__status = DownloadTask.INIT
self.__status_changed = True
self.__episode = episode
@ -613,6 +619,9 @@ class DownloadTask(object):
# files for resuming when the file is queued
open(self.tempname, 'w').close()
# Store a reference to this task in the episode
episode.download_task = self
def notify_as_finished(self):
if self.status == DownloadTask.DONE:
if self._notification_shown:
@ -699,6 +708,10 @@ class DownloadTask(object):
delay = min(10.0, float(should_have_passed-passed))
time.sleep(delay)
def recycle(self):
#FIXME self.__episode.download_task = None
pass
def run(self):
# Speed calculation (re-)starts here
self.__start_time = 0

View File

@ -143,17 +143,6 @@ class DownloadStatusModel(gtk.ListStore):
return False
def cancel_by_url(self, url):
for row in self:
task = row[DownloadStatusModel.C_TASK]
if task is not None and task.url == url and \
task.status in (task.DOWNLOADING, \
task.QUEUED):
task.status = task.CANCELLED
return True
return False
class DownloadTaskMonitor(object):
"""A helper class that abstracts download events"""

View File

@ -110,7 +110,7 @@ class gPodderEpisodeActions(BuilderWidget):
self.main_window.set_title(self.episode.title)
hildon.hildon_gtk_window_set_progress_indicator(self.main_window, False)
self.action_table = self.create_ui_downloaded()
elif self.episode_is_downloading(self.episode):
elif episode.downloading:
self.current_mode = self.MODE_DOWNLOADING
self.main_window.set_title(_('Downloading %s') % self.episode.title)
hildon.hildon_gtk_window_set_progress_indicator(self.main_window, True)

View File

@ -44,7 +44,6 @@ class gPodderEpisodes(BuilderWidget):
self.episode_actions = gPodderEpisodeActions(self.main_window, \
episode_list_status_changed=self.episode_list_status_changed, \
episode_is_downloading=self.episode_is_downloading, \
show_episode_shownotes=self.show_episode_shownotes, \
playback_episodes=self.playback_episodes, \
download_episode_list=self.download_episode_list, \
@ -182,7 +181,7 @@ class gPodderEpisodes(BuilderWidget):
self.action_download.set_property('visible', not episode.was_downloaded(and_exists=True))
else:
self.action_keep.set_property('visible', False)
self.action_download.set_property('visible', not self.episode_is_downloading(episode))
self.action_download.set_property('visible', not episode.downloading)
self.touched_episode = None

View File

@ -340,7 +340,6 @@ class gPodder(BuilderWidget, dbus.service.Object):
delete_episode_list=self.delete_episode_list, \
episode_list_status_changed=self.episode_list_status_changed, \
download_episode_list=self.download_episode_list, \
episode_is_downloading=self.episode_is_downloading, \
show_episode_in_download_manager=self.show_episode_in_download_manager, \
add_download_task_monitor=self.add_download_task_monitor, \
remove_download_task_monitor=self.remove_download_task_monitor, \
@ -1893,7 +1892,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
any_locked = any(e.archive for e in episodes)
any_new = any(e.is_new for e in episodes)
downloaded = all(e.was_downloaded(and_exists=True) for e in episodes)
downloading = any(self.episode_is_downloading(e) for e in episodes)
downloading = any(e.downloading for e in episodes)
menu = gtk.Menu()
@ -2010,23 +2009,21 @@ class gPodder(BuilderWidget, dbus.service.Object):
True (the former updates just the selected
episodes and the latter updates all episodes).
"""
additional_args = (self.episode_is_downloading, \
self.config.episode_list_descriptions and gpodder.ui.desktop)
descriptions = self.config.episode_list_descriptions and gpodder.ui.desktop
if urls is not None:
# We have a list of URLs to walk through
self.episode_list_model.update_by_urls(urls, *additional_args)
self.episode_list_model.update_by_urls(urls, descriptions)
elif selected and not all:
# We should update all selected episodes
selection = self.treeAvailable.get_selection()
model, paths = selection.get_selected_rows()
for path in reversed(paths):
iter = model.get_iter(path)
self.episode_list_model.update_by_filter_iter(iter, \
*additional_args)
self.episode_list_model.update_by_filter_iter(iter, descriptions)
elif all and not selected:
# We update all (even the filter-hidden) episodes
self.episode_list_model.update_all(*additional_args)
self.episode_list_model.update_all(descriptions)
else:
# Wrong/invalid call - have to specify at least one parameter
raise ValueError('Invalid call to update_episode_list_icons')
@ -2270,7 +2267,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
if not can_play:
can_download = True
else:
if self.episode_is_downloading(episode):
if episode.downloading:
can_cancel = True
else:
can_download = True
@ -2383,13 +2380,6 @@ class gPodder(BuilderWidget, dbus.service.Object):
logger.error('Cannot select podcast in list', exc_info=True)
self.channel_list_changed = False
def episode_is_downloading(self, episode):
"""Returns True if the given episode is being downloaded at the moment"""
if episode is None:
return False
return episode.url in (task.url for task in self.download_tasks_seen if task.status in (task.DOWNLOADING, task.QUEUED, task.PAUSED))
def on_episode_list_filter_changed(self, has_episodes):
if gpodder.ui.fremantle:
if has_episodes:
@ -2418,9 +2408,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.episodes_window.empty_label.show()
def update():
additional_args = (self.episode_is_downloading, \
self.config.episode_list_descriptions and gpodder.ui.desktop)
self.episode_list_model.replace_from_channel(self.active_channel, *additional_args)
descriptions = self.config.episode_list_descriptions and gpodder.ui.desktop
self.episode_list_model.replace_from_channel(self.active_channel, descriptions)
self.treeAvailable.get_selection().unselect_all()
self.treeAvailable.scroll_to_point(0, 0)
@ -3249,16 +3238,12 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.show_message(_('Please check for new episodes later.'), \
_('No new episodes available'), widget=self.btnUpdateFeeds)
def episode_is_new(self, episode):
return (episode.state == gpodder.STATE_NORMAL and
episode.is_new and
not self.episode_is_downloading(episode))
def get_new_episodes(self, channels=None):
if channels is None:
channels = self.channels
is_new = lambda e: (e.state == gpodder.STATE_NORMAL and e.is_new and
not e.downloading)
return [e for c in channels for e in filter(self.episode_is_new, c.get_all_episodes())]
return [e for c in channels or self.channels for e in
filter(is_new, c.get_all_episodes())]
def commit_changes_to_database(self):
"""This will be called after the sync process is finished"""
@ -3422,8 +3407,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
# cancel any active downloads from this channel
for episode in channel.get_all_episodes():
util.idle_add(self.download_status_model.cancel_by_url,
episode.url)
if episode.downloading:
episode.download_task.cancel()
if len(channels) == 1:
# get the URL of the podcast we want to select next
@ -3729,10 +3714,9 @@ class gPodder(BuilderWidget, dbus.service.Object):
_delete_episode_list=self.delete_episode_list, \
_episode_list_status_changed=self.episode_list_status_changed, \
_cancel_task_list=self.cancel_task_list, \
_episode_is_downloading=self.episode_is_downloading, \
_streaming_possible=self.streaming_possible())
self.episode_shownotes_window.show(episode)
if self.episode_is_downloading(episode):
if episode.downloading:
self.update_downloads_list()
def restart_auto_update_timer(self):

View File

@ -219,7 +219,7 @@ class EpisodeListModel(gtk.ListStore):
def get_search_term(self):
return self._search_term
def _format_description(self, episode, include_description=False, is_downloading=None):
def _format_description(self, episode, include_description=False):
a, b = '', ''
if episode.state != gpodder.STATE_DELETED and episode.is_new:
a, b = '<b>', '</b>'
@ -232,8 +232,7 @@ class EpisodeListModel(gtk.ListStore):
else:
return ''.join((a, cgi.escape(episode.title), b))
def replace_from_channel(self, channel, downloading=None, \
include_description=False, \
def replace_from_channel(self, channel, include_description=False,
treeview=None):
"""
Add episode from the given channel to this model.
@ -279,28 +278,27 @@ class EpisodeListModel(gtk.ListStore):
episode.total_time, \
episode.archive))
self.update_by_iter(iter, downloading, include_description)
self.update_by_iter(iter, include_description)
self._on_filter_changed(self.has_episodes())
def update_all(self, downloading=None, include_description=False):
def update_all(self, include_description=False):
for row in self:
self.update_by_iter(row.iter, downloading, include_description)
self.update_by_iter(row.iter, include_description)
def update_by_urls(self, urls, downloading=None, include_description=False):
def update_by_urls(self, urls, include_description=False):
for row in self:
if row[self.C_URL] in urls:
self.update_by_iter(row.iter, downloading, include_description)
self.update_by_iter(row.iter, include_description)
def update_by_filter_iter(self, iter, downloading=None, \
include_description=False):
def update_by_filter_iter(self, iter, include_description=False):
# Convenience function for use by "outside" methods that use iters
# from the filtered episode list model (i.e. all UI things normally)
iter = self._sorter.convert_iter_to_child_iter(None, iter)
self.update_by_iter(self._filter.convert_iter_to_child_iter(iter), \
downloading, include_description)
self.update_by_iter(self._filter.convert_iter_to_child_iter(iter),
include_description)
def update_by_iter(self, iter, downloading=None, include_description=False):
def update_by_iter(self, iter, include_description=False):
episode = self.get_value(iter, self.C_EPISODE)
show_bullet = False
@ -313,7 +311,7 @@ class EpisodeListModel(gtk.ListStore):
view_show_unplayed = False
icon_theme = gtk.icon_theme_get_default()
if downloading is not None and downloading(episode):
if episode.downloading:
tooltip.append(_('Downloading'))
status_icon = self.ICON_DOWNLOADING
view_show_downloaded = True
@ -392,7 +390,7 @@ class EpisodeListModel(gtk.ListStore):
tooltip = ', '.join(tooltip)
description = self._format_description(episode, include_description, downloading)
description = self._format_description(episode, include_description)
self.set(iter, \
self.C_STATUS_ICON, status_icon, \
self.C_VIEW_SHOW_UNDELETED, view_show_undeleted, \

View File

@ -274,6 +274,7 @@ class PodcastEpisode(PodcastModelObject):
def __init__(self, channel):
self.parent = channel
self.children = (None, None)
self.id = None
self.url = ''
@ -306,6 +307,22 @@ class PodcastEpisode(PodcastModelObject):
def db(self):
return self.parent.db
def _set_download_task(self, download_task):
self.children = (download_task, self.children[1])
def _get_download_task(self):
return self.children[0]
download_task = property(_get_download_task, _set_download_task)
@property
def downloading(self):
task = self.download_task
if task is None:
return False
return task.status in (task.DOWNLOADING, task.QUEUED, task.PAUSED)
def save(self):
if gpodder.user_hooks is not None:
gpodder.user_hooks.on_episode_save(self)