Make DownloadTask a child of PodcastEpisode
This commit is contained in:
parent
7ddb2eb354
commit
d714be329e
|
@ -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
|
||||
|
|
|
@ -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"""
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue