Update copyright years for 2013
[gpodder.git] / src / gpodder / gtkui / desktop / channel.py
blob0822858aa55431a39fcbfdb19a324fbcfa260834
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2013 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/>.
20 import gtk
21 import gtk.gdk
23 import gpodder
25 _ = gpodder.gettext
27 from gpodder import util
29 from gpodder.gtkui.interface.common import BuilderWidget
32 class gPodderChannel(BuilderWidget):
33 MAX_SIZE = 120
35 def new(self):
36 self.gPodderChannel.set_title( self.channel.title)
37 self.entryTitle.set_text( self.channel.title)
38 self.labelURL.set_text(self.channel.url)
39 self.cbSkipFeedUpdate.set_active(self.channel.pause_subscription)
40 self.cbEnableDeviceSync.set_active(self.channel.sync_to_mp3_player)
42 self.section_list = gtk.ListStore(str)
43 active_index = 0
44 for index, section in enumerate(sorted(self.sections)):
45 self.section_list.append([section])
46 if section == self.channel.section:
47 active_index = index
48 self.combo_section.set_model(self.section_list)
49 cell_renderer = gtk.CellRendererText()
50 self.combo_section.pack_start(cell_renderer)
51 self.combo_section.add_attribute(cell_renderer, 'text', 0)
52 self.combo_section.set_active(active_index)
54 self.strategy_list = gtk.ListStore(str, int)
55 active_index = 0
56 for index, (checked, strategy_id, strategy) in \
57 enumerate(self.channel.get_download_strategies()):
58 self.strategy_list.append([strategy, strategy_id])
59 if checked:
60 active_index = index
61 self.combo_strategy.set_model(self.strategy_list)
62 cell_renderer = gtk.CellRendererText()
63 self.combo_strategy.pack_start(cell_renderer)
64 self.combo_strategy.add_attribute(cell_renderer, 'text', 0)
65 self.combo_strategy.set_active(active_index)
67 self.LabelDownloadTo.set_text( self.channel.save_dir)
68 self.LabelWebsite.set_text( self.channel.link)
70 if self.channel.auth_username:
71 self.FeedUsername.set_text( self.channel.auth_username)
72 if self.channel.auth_password:
73 self.FeedPassword.set_text( self.channel.auth_password)
75 self.cover_downloader.register('cover-available', self.cover_download_finished)
76 self.cover_downloader.request_cover(self.channel)
78 # Hide the website button if we don't have a valid URL
79 if not self.channel.link:
80 self.btn_website.hide_all()
82 b = gtk.TextBuffer()
83 b.set_text( self.channel.description)
84 self.channel_description.set_buffer( b)
86 #Add Drag and Drop Support
87 flags = gtk.DEST_DEFAULT_ALL
88 targets = [('text/uri-list', 0, 2), ('text/plain', 0, 4)]
89 actions = gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY
90 self.imgCover.drag_dest_set(flags, targets, actions)
91 self.imgCover.connect('drag_data_received', self.drag_data_received)
92 border = 6
93 self.imgCover.set_size_request(*((self.MAX_SIZE+border*2,)*2))
94 self.imgCoverEventBox.connect('button-press-event',
95 self.on_cover_popup_menu)
97 def on_button_add_section_clicked(self, widget):
98 text = self.show_text_edit_dialog(_('Add section'), _('New section:'),
99 affirmative_text=gtk.STOCK_ADD)
101 if text is not None:
102 for index, (section,) in enumerate(self.section_list):
103 if text == section:
104 self.combo_section.set_active(index)
105 return
107 self.section_list.append([text])
108 self.combo_section.set_active(len(self.section_list)-1)
110 def on_cover_popup_menu(self, widget, event):
111 if event.button != 3:
112 return
114 menu = gtk.Menu()
116 item = gtk.ImageMenuItem(gtk.STOCK_OPEN)
117 item.connect('activate', self.on_btnDownloadCover_clicked)
118 menu.append(item)
120 item = gtk.ImageMenuItem(gtk.STOCK_REFRESH)
121 item.connect('activate', self.on_btnClearCover_clicked)
122 menu.append(item)
124 menu.show_all()
125 menu.popup(None, None, None, event.button, event.time, None)
127 def on_btn_website_clicked(self, widget):
128 util.open_website(self.channel.link)
130 def on_btnDownloadCover_clicked(self, widget):
131 dlg = gtk.FileChooserDialog(title=_('Select new podcast cover artwork'), parent=self.gPodderChannel, action=gtk.FILE_CHOOSER_ACTION_OPEN)
132 dlg.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
133 dlg.add_button(gtk.STOCK_OPEN, gtk.RESPONSE_OK)
135 if dlg.run() == gtk.RESPONSE_OK:
136 url = dlg.get_uri()
137 self.clear_cover_cache(self.channel.url)
138 self.cover_downloader.replace_cover(self.channel, custom_url=url)
140 dlg.destroy()
142 def on_btnClearCover_clicked(self, widget):
143 self.clear_cover_cache(self.channel.url)
144 self.cover_downloader.replace_cover(self.channel, custom_url=False)
146 def cover_download_finished(self, channel, pixbuf):
147 def set_cover(channel, pixbuf):
148 if self.channel == channel:
149 self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf))
150 self.gPodderChannel.show()
152 util.idle_add(set_cover, channel, pixbuf)
154 def drag_data_received( self, widget, content, x, y, sel, ttype, time):
155 files = sel.data.strip().split('\n')
156 if len(files) != 1:
157 self.show_message( _('You can only drop a single image or URL here.'), _('Drag and drop'))
158 return
160 file = files[0]
162 if file.startswith('file://') or file.startswith('http://'):
163 self.clear_cover_cache(self.channel.url)
164 self.cover_downloader.replace_cover(self.channel, custom_url=file)
165 return
167 self.show_message( _('You can only drop local files and http:// URLs here.'), _('Drag and drop'))
169 def on_gPodderChannel_destroy(self, widget, *args):
170 self.cover_downloader.unregister('cover-available', self.cover_download_finished)
172 def scale_pixbuf(self, pixbuf):
174 # Resize if width is too large
175 if pixbuf.get_width() > self.MAX_SIZE:
176 f = float(self.MAX_SIZE)/pixbuf.get_width()
177 (width, height) = (int(pixbuf.get_width()*f), int(pixbuf.get_height()*f))
178 pixbuf = pixbuf.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
180 # Resize if height is too large
181 if pixbuf.get_height() > self.MAX_SIZE:
182 f = float(self.MAX_SIZE)/pixbuf.get_height()
183 (width, height) = (int(pixbuf.get_width()*f), int(pixbuf.get_height()*f))
184 pixbuf = pixbuf.scale_simple(width, height, gtk.gdk.INTERP_BILINEAR)
186 return pixbuf
188 def on_btnOK_clicked(self, widget, *args):
189 self.channel.pause_subscription = self.cbSkipFeedUpdate.get_active()
190 self.channel.sync_to_mp3_player = self.cbEnableDeviceSync.get_active()
191 self.channel.rename(self.entryTitle.get_text())
192 self.channel.auth_username = self.FeedUsername.get_text().strip()
193 self.channel.auth_password = self.FeedPassword.get_text()
195 self.clear_cover_cache(self.channel.url)
196 self.cover_downloader.request_cover(self.channel)
198 new_section = self.section_list[self.combo_section.get_active()][0]
199 if self.channel.section != new_section:
200 self.channel.section = new_section
201 section_changed = True
202 else:
203 section_changed = False
205 new_strategy = self.strategy_list[self.combo_strategy.get_active()][1]
206 self.channel.set_download_strategy(new_strategy)
208 self.channel.save()
210 self.gPodderChannel.destroy()
212 self.update_podcast_list_model(selected=True,
213 sections_changed=section_changed)