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/>.
27 from gpodder
import util
29 from gpodder
.gtkui
.interface
.common
import BuilderWidget
32 class gPodderChannel(BuilderWidget
):
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)
44 for index
, section
in enumerate(sorted(self
.sections
)):
45 self
.section_list
.append([section
])
46 if section
== self
.channel
.section
:
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)
56 for index
, (checked
, strategy_id
, strategy
) in \
57 enumerate(self
.channel
.get_download_strategies()):
58 self
.strategy_list
.append([strategy
, strategy_id
])
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()
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
)
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
)
102 for index
, (section
,) in enumerate(self
.section_list
):
104 self
.combo_section
.set_active(index
)
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:
116 item
= gtk
.ImageMenuItem(gtk
.STOCK_OPEN
)
117 item
.connect('activate', self
.on_btnDownloadCover_clicked
)
120 item
= gtk
.ImageMenuItem(gtk
.STOCK_REFRESH
)
121 item
.connect('activate', self
.on_btnClearCover_clicked
)
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
:
137 self
.clear_cover_cache(self
.channel
.url
)
138 self
.cover_downloader
.replace_cover(self
.channel
, custom_url
=url
)
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')
157 self
.show_message( _('You can only drop a single image or URL here.'), _('Drag and drop'))
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)
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
)
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
203 section_changed
= False
205 new_strategy
= self
.strategy_list
[self
.combo_strategy
.get_active()][1]
206 self
.channel
.set_download_strategy(new_strategy
)
210 self
.gPodderChannel
.destroy()
212 self
.update_podcast_list_model(selected
=True,
213 sections_changed
=section_changed
)