Add 2010 to the years in copyright notice
[gpodder.git] / src / gpodder / gtkui / download.py
blob2b9321650ce7102e0babc6727c0e37bd9709f70b
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # gpodder.gtkui.download -- Download management in GUIs (2009-08-24)
23 # Based on code from gpodder.services (thp, 2007-08-24)
26 import gpodder
27 from gpodder.liblogger import log
29 from gpodder import util
30 from gpodder import download
32 import gtk
33 import gobject
35 import collections
37 _ = gpodder.gettext
40 class DownloadStatusModel(gtk.ListStore):
41 # Symbolic names for our columns, so we know what we're up to
42 C_TASK, C_NAME, C_URL, C_PROGRESS, C_PROGRESS_TEXT, C_ICON_NAME = range(6)
44 SEARCH_COLUMNS = (C_NAME, C_URL)
46 def __init__(self):
47 gtk.ListStore.__init__(self, object, str, str, int, str, str)
49 # Set up stock icon IDs for tasks
50 self._status_ids = collections.defaultdict(lambda: None)
51 self._status_ids[download.DownloadTask.DOWNLOADING] = gtk.STOCK_GO_DOWN
52 self._status_ids[download.DownloadTask.DONE] = gtk.STOCK_APPLY
53 self._status_ids[download.DownloadTask.FAILED] = gtk.STOCK_STOP
54 self._status_ids[download.DownloadTask.CANCELLED] = gtk.STOCK_CANCEL
55 self._status_ids[download.DownloadTask.PAUSED] = gtk.STOCK_MEDIA_PAUSE
57 def _format_message(self, episode, message, podcast):
58 return '%s\n<small>%s - %s</small>' % (episode, message, podcast)
60 def request_update(self, iter, task=None):
61 if task is None:
62 # Ongoing update request from UI - get task from model
63 task = self.get_value(iter, self.C_TASK)
64 else:
65 # Initial update request - update non-changing fields
66 self.set(iter,
67 self.C_TASK, task,
68 self.C_URL, task.url)
70 if task.status == task.FAILED:
71 status_message = '%s: %s' % (\
72 task.STATUS_MESSAGE[task.status], \
73 task.error_message)
74 elif task.status == task.DOWNLOADING:
75 status_message = '%s (%s, %s/s)' % (\
76 task.STATUS_MESSAGE[task.status], \
77 util.format_filesize(task.total_size), \
78 util.format_filesize(task.speed))
79 else:
80 status_message = '%s (%s)' % (\
81 task.STATUS_MESSAGE[task.status], \
82 util.format_filesize(task.total_size))
84 self.set(iter,
85 self.C_NAME, self._format_message(task.markup_name, \
86 status_message, task.markup_podcast_name),
87 self.C_PROGRESS, 100.*task.progress,
88 self.C_PROGRESS_TEXT, '%.0f%%' % (task.progress*100.,),
89 self.C_ICON_NAME, self._status_ids[task.status])
91 def __add_new_task(self, task):
92 iter = self.append()
93 self.request_update(iter, task)
95 def register_task(self, task):
96 util.idle_add(self.__add_new_task, task)
98 def tell_all_tasks_to_quit(self):
99 for row in self:
100 task = row[DownloadStatusModel.C_TASK]
101 if task is not None:
102 # Pause currently-running (and queued) downloads
103 if task.status in (task.QUEUED, task.DOWNLOADING):
104 task.status = task.PAUSED
106 # Delete cancelled and failed downloads
107 if task.status in (task.CANCELLED, task.FAILED):
108 task.removed_from_list()
110 def are_downloads_in_progress(self):
112 Returns True if there are any downloads in the
113 QUEUED or DOWNLOADING status, False otherwise.
115 for row in self:
116 task = row[DownloadStatusModel.C_TASK]
117 if task is not None and \
118 task.status in (task.DOWNLOADING, \
119 task.QUEUED):
120 return True
122 return False
124 def cancel_by_url(self, url):
125 for row in self:
126 task = row[DownloadStatusModel.C_TASK]
127 if task is not None and task.url == url and \
128 task.status in (task.DOWNLOADING, \
129 task.QUEUED):
130 task.status = task.CANCELLED
131 return True
133 return False
136 class DownloadTaskMonitor(object):
137 """A helper class that abstracts download events"""
138 def __init__(self, episode, on_can_resume, on_can_pause, on_finished):
139 self.episode = episode
140 self._status = None
141 self._on_can_resume = on_can_resume
142 self._on_can_pause = on_can_pause
143 self._on_finished = on_finished
145 def task_updated(self, task):
146 if self.episode.url == task.episode.url and self._status != task.status:
147 if task.status in (task.DONE, task.FAILED, task.CANCELLED):
148 self._on_finished()
149 elif task.status == task.PAUSED:
150 self._on_can_resume()
151 elif task.status in (task.QUEUED, task.DOWNLOADING):
152 self._on_can_pause()
153 self._status = task.status