Fri, 02 May 2008 17:28:22 +0200 <thp@perli.net>

Change "Channel" to "Podcast"; new main menu; URL entry updated; +niceties

	* data/gpodder.glade: Change "Channel" to "Podcast"; re-structure main
	menu in gPodder window
	* src/gpodder/config.py: Add "show_podcast_url_entry" configuration
	option that controls whether the podcast url entry box is shown in the
	main window or not; add observer functionality to the configuration
	manager, so UI elements can "watch" the configuration manager for
	changes of UI-related configuration options
	* src/gpodder/console.py: Change "Channel" to "Podcast"
	* src/gpodder/gui.py: Hildon-specific file open/save dialogs; default
	"Enter podcast URL..." test for the URL entry box; size-dependent
	showing and hiding of podcast icon and downloaded count pixmap also
	for the Desktop version; change "Channel" to "Podcast"; offer
	first-time users to see a list of example podcasts to subscribe to;
	dynamic main menu; code supporting the main menu changes; add code for
	sending the subscription list via e-mail; import from OPML file in
	addition to import from OPML URL; remove unneeded callbacks (wishlist,
	select all, ...); optionally set title and hide url entry in the
	gPodderOpmlLister (OPML import GUI); Add Frank Harper to list of
	contributors (initial reporter of bug #82)
	* src/gpodder/libgpodder.py: Add "send_subscriptions" function that
	sends the user's channels.opml file via E-Mail (using xdg-email);
	rename "Channel" to "Podcast"
	(Closes: http://bugs.gpodder.org/show_bug.cgi?id=82)
	(Closes: http://bugs.gpodder.org/show_bug.cgi?id=103)



git-svn-id: svn://svn.berlios.de/gpodder/trunk@700 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
Thomas Perl 2008-05-02 15:36:43 +00:00
parent 42a3b5be44
commit 40cef59a49
6 changed files with 570 additions and 506 deletions

View file

@ -1,3 +1,31 @@
Fri, 02 May 2008 17:28:22 +0200 <thp@perli.net>
Change "Channel" to "Podcast"; new main menu; URL entry updated; +niceties
* data/gpodder.glade: Change "Channel" to "Podcast"; re-structure main
menu in gPodder window
* src/gpodder/config.py: Add "show_podcast_url_entry" configuration
option that controls whether the podcast url entry box is shown in the
main window or not; add observer functionality to the configuration
manager, so UI elements can "watch" the configuration manager for
changes of UI-related configuration options
* src/gpodder/console.py: Change "Channel" to "Podcast"
* src/gpodder/gui.py: Hildon-specific file open/save dialogs; default
"Enter podcast URL..." test for the URL entry box; size-dependent
showing and hiding of podcast icon and downloaded count pixmap also
for the Desktop version; change "Channel" to "Podcast"; offer
first-time users to see a list of example podcasts to subscribe to;
dynamic main menu; code supporting the main menu changes; add code for
sending the subscription list via e-mail; import from OPML file in
addition to import from OPML URL; remove unneeded callbacks (wishlist,
select all, ...); optionally set title and hide url entry in the
gPodderOpmlLister (OPML import GUI); Add Frank Harper to list of
contributors (initial reporter of bug #82)
* src/gpodder/libgpodder.py: Add "send_subscriptions" function that
sends the user's channels.opml file via E-Mail (using xdg-email);
rename "Channel" to "Podcast"
(Closes: http://bugs.gpodder.org/show_bug.cgi?id=82)
(Closes: http://bugs.gpodder.org/show_bug.cgi?id=103)
Fri, 02 May 2008 15:52:31 +0200 <thp@perli.net>
Updated Portuguese translation by João Trindade

File diff suppressed because it is too large Load diff

View file

@ -106,6 +106,7 @@ gPodderSettings = {
'create_m3u_playlists': (bool, False),
'max_episodes_per_feed': (int, 200),
'mp3_player_use_scrobbler_log': (bool, False),
'show_podcast_url_entry': (bool, True),
# Window and paned positions
'main_window_x': ( int, 100 ),
@ -127,6 +128,7 @@ class Config(dict):
self.__filename = filename
self.__section = 'gpodder-conf-1'
self.__ignore_window_events = False
self.__observers = []
# Name, Type, Value, Type(python type), Editable?, Font weight
self.__model = gtk.ListStore(str, str, str, object, bool, int)
@ -141,6 +143,22 @@ class Config(dict):
else:
raise AttributeError
def add_observer(self, callback):
"""
Add a callback function as observer. This callback
will be called when a setting changes. It should
have this signature:
observer(name, old_value, new_value)
The "name" is the setting name, the "old_value" is
the value that has been overwritten with "new_value".
"""
if callback not in self.__observers:
self.__observers.append(callback)
else:
log('Observer already added: %s', repr(callback), sender=self)
def connect_gtk_editable( self, name, editable):
if name in self.Settings:
editable.delete_text( 0, -1)
@ -326,7 +344,14 @@ class Config(dict):
try:
if self[name] != fieldtype(value):
log( 'Update: %s = %s', name, value, sender = self)
old_value = self[name]
self[name] = fieldtype(value)
for observer in self.__observers:
try:
# Notify observer about config change
observer(name, old_value, self[name])
except:
log('Error while calling observer: %s', repr(observer), sender=self)
for row in self.__model:
if row[0] == name:
row[2] = str(fieldtype(value))

View file

@ -33,8 +33,8 @@ import urllib
def list_channels():
for channel in load_channels( load_items = False):
msg( 'channel', urllib.unquote( channel.url))
for channel in load_channels(load_items=False):
msg('podcast', urllib.unquote(channel.url))
def add_channel( url):
@ -56,7 +56,7 @@ def add_channel( url):
save_channels( channels)
msg( 'add', urllib.unquote( url))
else:
msg( 'error', _('Could not add channel.'))
msg('error', _('Could not add podcast.'))
def del_channel( url):
@ -73,7 +73,7 @@ def del_channel( url):
if len(keep_channels) < len(channels):
save_channels( keep_channels)
else:
msg( 'error', _('Could not remove channel.'))
msg('error', _('Could not remove podcast.'))
def update():
@ -111,7 +111,7 @@ def sync_device():
for channel in load_channels():
if not channel.sync_to_devices:
msg('info', _('Skipping channel: %s') % channel.title)
msg('info', _('Skipping podcast: %s') % channel.title)
continue
episodes_to_sync = []

View file

@ -78,8 +78,8 @@ app_authors = [
'Antonio Roversi', 'Aravind Seshadri', 'Atte André Jensen',
'Bernd Schlapsi', 'Bill Barnard', 'Bjørn Rasmussen', 'Camille Moncelier',
'Carlos Moffat', 'Chris', 'Chris Arnold', 'Clark Burbidge',
'Doug Hellmann', 'FFranci72',
'Florian Richter', 'FriedBunny', 'Gerrit Sangel', 'Götz Waschk',
'Doug Hellmann', 'FFranci72', 'Florian Richter', 'Frank Harper',
'FriedBunny', 'Gerrit Sangel', 'Götz Waschk',
'Haim Roitgrund', 'Hex', 'Holger Bauer', 'Holger Leskien', 'Jens Thiele',
'Jérôme Chabod', 'Jessica Henline', 'João Trindade', 'Joel Calado', 'John Ferguson',
'José Luis Fustel', 'Joseph Bleau', 'Julio Acuña', 'Junio C Hamano',
@ -221,15 +221,17 @@ class GladeWidget(SimpleGladeApp.SimpleGladeApp):
if not dst_filename.endswith( extension):
dst_filename += extension
dlg = gtk.FileChooserDialog( title = title, parent = GladeWidget.gpodder_main_window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
dlg.set_do_overwrite_confirmation( True)
if gpodder.interface == gpodder.GUI:
dlg = gtk.FileChooserDialog(title=title, parent=GladeWidget.gpodder_main_window, action=gtk.FILE_CHOOSER_ACTION_SAVE)
dlg.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
dlg.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_OK)
elif gpodder.interface == gpodder.MAEMO:
dlg = hildon.FileChooserDialog(GladeWidget.gpodder_main_window, gtk.FILE_CHOOSER_ACTION_SAVE)
dlg.set_do_overwrite_confirmation( True)
dlg.set_current_name( os.path.basename( dst_filename))
dlg.set_current_folder( dst_directory)
dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
dlg.add_button( gtk.STOCK_SAVE, gtk.RESPONSE_OK)
if dlg.run() == gtk.RESPONSE_OK:
dst_filename = dlg.get_filename()
if not dst_filename.endswith( extension):
@ -248,6 +250,7 @@ class GladeWidget(SimpleGladeApp.SimpleGladeApp):
class gPodder(GladeWidget):
finger_friendly_widgets = ['btnUpdateFeeds', 'btnCancelFeedUpdate', 'treeAvailable', 'label2', 'labelDownloads']
ENTER_URL_TEXT = _('Enter podcast URL...')
def new(self):
if gpodder.interface == gpodder.MAEMO:
@ -288,15 +291,27 @@ class gPodder(GladeWidget):
# do some widget hiding
self.toolbar.remove(self.toolTransfer)
self.itemTransferSelected.hide_all()
self.separator11.hide_all()
self.hboxAddChannel.hide_all()
self.item_show_url_entry.hide_all()
# Feed cache update button
self.label120.set_text(_('Update'))
self.treeChannels.connect('size-allocate', self.on_tree_channels_resize)
# get screen real estate
self.hboxContainer.set_border_width(0)
self.treeChannels.connect('size-allocate', self.on_tree_channels_resize)
if gpodder.interface == gpodder.MAEMO or not gl.config.show_podcast_url_entry:
self.hboxAddChannel.hide_all()
if not gl.config.show_toolbar:
self.toolbar.hide_all()
gl.config.add_observer(self.on_config_changed)
self.default_entry_text_color = self.entryAddChannel.get_style().text[gtk.STATE_NORMAL]
self.entryAddChannel.connect('focus-in-event', self.entry_add_channel_focus)
self.entryAddChannel.connect('focus-out-event', self.entry_add_channel_unfocus)
self.entry_add_channel_unfocus(self.entryAddChannel, None)
self.uar = None
self.tray_icon = None
@ -307,11 +322,11 @@ class gPodder(GladeWidget):
self.already_notified_new_episodes = []
self.show_hide_tray_icon()
self.no_episode_selected.set_sensitive(False)
self.episode_description_shown = gl.config.episode_list_descriptions
self.itemShowToolbar.set_active(gl.config.show_toolbar)
self.itemShowDescription.set_active(gl.config.episode_list_descriptions)
self.update_view_settings()
self.item_show_url_entry.set_active(gl.config.show_podcast_url_entry)
if self.tray_icon:
if gl.config.start_iconified:
@ -344,7 +359,7 @@ class gPodder(GladeWidget):
gtk.about_dialog_set_url_hook(lambda dlg, link, data: util.open_website(link), None)
# cell renderers for channel tree
namecolumn = gtk.TreeViewColumn( _('Channel'))
namecolumn = gtk.TreeViewColumn( _('Podcast'))
iconcell = gtk.CellRendererPixbuf()
namecolumn.pack_start( iconcell, False)
@ -479,13 +494,43 @@ class gPodder(GladeWidget):
self.delete_episode_list(old_episodes, confirm=False)
self.updateComboBox()
# First-time users should be asked if they want to see the OPML
if len(self.channels) == 0:
util.idle_add(self.on_itemUpdate_activate, None)
def on_tree_channels_resize(self, widget, allocation):
window_allocation = self.gPodder.get_allocation()
percentage = 100. * float(allocation.width) / float(window_allocation.width)
if hasattr(self, 'cell_channel_icon'):
self.cell_channel_icon.set_property('visible', bool(percentage > 24.))
self.cell_channel_icon.set_property('visible', bool(percentage > 22.))
if hasattr(self, 'cell_channel_pill'):
self.cell_channel_pill.set_property('visible', bool(percentage > 28.))
self.cell_channel_pill.set_property('visible', bool(percentage > 25.))
def entry_add_channel_focus(self, widget, event):
widget.modify_text(gtk.STATE_NORMAL, self.default_entry_text_color)
if widget.get_text() == self.ENTER_URL_TEXT:
widget.set_text('')
def entry_add_channel_unfocus(self, widget, event):
if widget.get_text() == '':
widget.set_text(self.ENTER_URL_TEXT)
widget.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse('#aaaaaa'))
def on_config_changed(self, name, old_value, new_value):
if name == 'show_toolbar':
if new_value:
self.toolbar.show_all()
else:
self.toolbar.hide_all()
elif name == 'episode_list_descriptions':
for channel in self.channels:
channel.force_update_tree_model()
self.updateTreeView()
elif name == 'show_podcast_url_entry' and gpodder.interface != gpodder.MAEMO:
if new_value:
self.hboxAddChannel.show_all()
else:
self.hboxAddChannel.hide_all()
def read_apps(self):
time.sleep(3) # give other parts of gpodder a chance to start up
@ -590,7 +635,10 @@ class gPodder(GladeWidget):
def on_itemClose_activate(self, widget):
if self.tray_icon is not None:
self.iconify_main_window()
if gpodder.interface == gpodder.MAEMO:
self.gPodder.set_property('visible', False)
else:
self.iconify_main_window()
else:
self.on_gPodder_delete_event(widget)
@ -832,12 +880,20 @@ class gPodder(GladeWidget):
return False
return True
def change_menu_item(self, menuitem, icon=None, label=None):
(label_widget, icon_widget) = menuitem.get_children()
if icon is not None:
icon_widget.set_from_icon_name(icon, gtk.ICON_SIZE_MENU)
if label is not None:
label_widget.set_text(label)
def play_or_download( self):
if self.wNotebook.get_current_page() > 0:
return
( can_play, can_download, can_transfer, can_cancel ) = (False,)*4
(is_played, is_locked) = (False,)*2
selection = self.treeAvailable.get_selection()
if selection.count_selected_rows() > 0:
@ -849,6 +905,8 @@ class gPodder(GladeWidget):
if os.path.exists( local_filename):
can_play = True
is_played = gl.history_is_played(url)
is_locked = gl.history_is_locked(url)
else:
if services.download_status_manager.is_download_in_progress( url):
can_cancel = True
@ -867,6 +925,43 @@ class gPodder(GladeWidget):
self.toolTransfer.set_sensitive( can_transfer)
self.toolCancel.set_sensitive( can_cancel)
if can_cancel:
self.item_cancel_download.show_all()
else:
self.item_cancel_download.hide_all()
if can_download:
self.itemDownloadSelected.show_all()
else:
self.itemDownloadSelected.hide_all()
if can_play:
self.itemPlaySelected.show_all()
self.itemDeleteSelected.show_all()
self.item_toggle_played.show_all()
self.item_toggle_lock.show_all()
self.separator9.show_all()
if is_played:
self.change_menu_item(self.item_toggle_played, gtk.STOCK_CANCEL, _('Mark as unplayed'))
else:
self.change_menu_item(self.item_toggle_played, gtk.STOCK_APPLY, _('Mark as played'))
if is_locked:
self.change_menu_item(self.item_toggle_lock, gtk.STOCK_DIALOG_AUTHENTICATION, _('Allow deletion'))
else:
self.change_menu_item(self.item_toggle_lock, gtk.STOCK_DIALOG_AUTHENTICATION, _('Prohibit deletion'))
else:
self.itemPlaySelected.hide_all()
self.itemDeleteSelected.hide_all()
self.item_toggle_played.hide_all()
self.item_toggle_lock.hide_all()
self.separator9.hide_all()
if can_play or can_download or can_cancel:
self.item_episode_details.show_all()
self.separator16.show_all()
self.no_episode_selected.hide_all()
else:
self.item_episode_details.hide_all()
self.separator16.hide_all()
self.no_episode_selected.show_all()
return ( can_play, can_download, can_transfer, can_cancel )
def download_status_updated( self):
@ -927,7 +1022,7 @@ class gPodder(GladeWidget):
if result:
for old_channel in self.channels:
if old_channel.url == result:
self.show_message( _('You have already subscribed to this channel: %s') % ( saxutils.escape( old_channel.title), ), _('Already added'))
self.show_message( _('You have already subscribed to this podcast: %s') % ( saxutils.escape( old_channel.title), ), _('Already added'))
log( 'Channel already exists: %s', result)
# Select the existing channel in combo box
for i in range( len( self.channels)):
@ -961,8 +1056,8 @@ class gPodder(GladeWidget):
if ask_download_new:
self.on_btnDownloadNewer_clicked( None)
else:
title = _('Error adding channel')
message = _('The channel could not be added. Please check the spelling of the URL or try again later.')
title = _('Error adding podcast')
message = _('The podcast could not be added. Please check the spelling of the URL or try again later.')
self.show_message( message, title)
else:
if result:
@ -1067,7 +1162,7 @@ class gPodder(GladeWidget):
self.playback_episode( current_channel, current_podcast)
return
if widget.get_name() == 'treeAvailable':
if widget.get_name() == 'treeAvailable' or widget.get_name() == 'item_episode_details':
play_callback = lambda: self.playback_episode( current_channel, current_podcast)
download_callback = lambda: self.download_podcast_by_url( url, want_message_dialog, None)
gpe = gPodderEpisode( episode = current_podcast, channel = current_channel, download_callback = download_callback, play_callback = play_callback)
@ -1142,7 +1237,7 @@ class gPodder(GladeWidget):
"""
if self.channels:
if not save_channels(self.channels):
self.show_message(_('Please check your permissions and free disk space.'), _('Error saving channel list'))
self.show_message(_('Please check your permissions and free disk space.'), _('Error saving podcast list'))
services.download_status_manager.cancel_all()
@ -1189,7 +1284,7 @@ class gPodder(GladeWidget):
def on_itemRemoveOldEpisodes_activate( self, widget):
columns = (
('title', _('Episode')),
('channel_prop', _('Channel')),
('channel_prop', _('Podcast')),
('filesize_prop', _('Size')),
('pubdate_prop', _('Released')),
('played_prop', _('Status')),
@ -1240,13 +1335,23 @@ class gPodder(GladeWidget):
self.for_each_selected_episode_url(callback)
def on_item_email_subscriptions_activate(self, widget):
if not self.channels:
self.show_message(_('Your subscription list is empty.'), _('Could not send list'))
elif not gl.send_subscriptions():
self.show_message(_('There was an error sending your subscription list via e-mail.'), _('Could not send list'))
def on_item_show_url_entry_activate(self, widget):
gl.config.show_podcast_url_entry = self.item_show_url_entry.get_active()
def on_itemUpdate_activate(self, widget, notify_no_new_episodes=False):
if self.channels:
self.update_feed_cache(notify_no_new_episodes=notify_no_new_episodes)
else:
title = _('No channels available')
message = _('You need to subscribe to some podcast feeds before you can start downloading podcasts. Use your favorite search engine to look for interesting podcasts.')
self.show_message( message, title)
title = _('Import podcasts from the web')
message = _('Your podcast list is empty. Do you want to see a list of example podcasts you can subscribe to?')
if self.show_confirmation(message, title):
self.on_itemImportChannels_activate(self, widget)
def download_episode_list( self, episodes):
for episode in episodes:
@ -1258,7 +1363,7 @@ class gPodder(GladeWidget):
def new_episodes_show(self, episodes):
columns = (
('title', _('Episode')),
('channel_prop', _('Channel')),
('channel_prop', _('Podcast')),
('filesize_prop', _('Size')),
('pubdate_prop', _('Released')),
)
@ -1404,31 +1509,17 @@ class gPodder(GladeWidget):
elif self.tray_icon:
self.tray_icon.set_visible(True)
def update_view_settings(self):
if gl.config.show_toolbar:
self.toolbar.show_all()
else:
self.toolbar.hide_all()
if self.episode_description_shown != gl.config.episode_list_descriptions:
for channel in self.channels:
channel.force_update_tree_model()
self.updateTreeView()
self.episode_description_shown = gl.config.episode_list_descriptions
def on_itemShowToolbar_activate(self, widget):
gl.config.show_toolbar = self.itemShowToolbar.get_active()
self.update_view_settings()
def on_itemShowDescription_activate(self, widget):
gl.config.episode_list_descriptions = self.itemShowDescription.get_active()
self.update_view_settings()
def update_item_device( self):
if gl.config.device_type != 'none':
self.itemDevice.show_all()
( label, image ) = self.itemDevice.get_children()
label.set_text( gl.get_device_name())
(label,) = self.itemDevice.get_children()
label.set_text(gl.get_device_name())
else:
self.itemDevice.hide_all()
@ -1444,18 +1535,17 @@ class gPodder(GladeWidget):
gPodderMaemoPreferences()
def on_itemAddChannel_activate(self, widget, *args):
if gpodder.interface == gpodder.MAEMO:
if gpodder.interface == gpodder.MAEMO or not gl.config.show_podcast_url_entry:
gPodderAddPodcastDialog(url_callback=self.add_new_channel)
else:
if self.channelPaned.get_position() < 200:
self.channelPaned.set_position( 200)
self.entryAddChannel.set_text( _('Enter podcast URL'))
self.entryAddChannel.grab_focus()
def on_itemEditChannel_activate(self, widget, *args):
if self.active_channel is None:
title = _('No channel selected')
message = _('Please select a channel in the channels list to edit.')
title = _('No podcast selected')
message = _('Please select a podcast in the podcasts list to edit.')
self.show_message( message, title)
return
@ -1500,7 +1590,7 @@ class gPodder(GladeWidget):
dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
dialog.add_button(gtk.STOCK_YES, gtk.RESPONSE_YES)
title = _('Remove channel and episodes?')
title = _('Remove podcast and episodes?')
message = _('Do you really want to remove <b>%s</b> and all downloaded episodes?') % saxutils.escape(self.active_channel.title)
dialog.set_title(title)
@ -1512,7 +1602,7 @@ class gPodder(GladeWidget):
affirmative = gtk.RESPONSE_YES
elif gpodder.interface == gpodder.MAEMO:
cb_ask = gtk.CheckButton('') # dummy check button
dialog = hildon.Note('confirmation', (self.gPodder, _('Do you really want to remove this channel and all downloaded episodes?')))
dialog = hildon.Note('confirmation', (self.gPodder, _('Do you really want to remove this podcast and all downloaded episodes?')))
affirmative = gtk.RESPONSE_OK
result = dialog.run()
@ -1537,16 +1627,43 @@ class gPodder(GladeWidget):
except:
log('There has been an error removing the channel.', traceback=True, sender=self)
def get_opml_filter(self):
filter = gtk.FileFilter()
filter.add_pattern('*.opml')
filter.add_pattern('*.xml')
filter.set_name(_('OPML files')+' (*.opml, *.xml)')
return filter
def on_item_import_from_file_activate(self, widget):
if gpodder.interface == gpodder.GUI:
dlg = gtk.FileChooserDialog(title=_('Import from OPML'), parent=None, action=gtk.FILE_CHOOSER_ACTION_OPEN)
dlg.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
dlg.add_button(gtk.STOCK_OPEN, gtk.RESPONSE_OK)
elif gpodder.interface == gpodder.MAEMO:
dlg = hildon.FileChooserDialog(self.gPodder, gtk.FILE_CHOOSER_ACTION_OPEN)
dlg.set_filter(self.get_opml_filter())
response = dlg.run()
filename = None
if response == gtk.RESPONSE_OK:
filename = dlg.get_filename()
dlg.destroy()
if filename is not None:
gPodderOpmlLister(custom_title=_('Import podcasts from OPML file'), hide_url_entry=True).get_channels_from_url(filename, lambda url: self.add_new_channel(url,False), lambda: self.on_itemDownloadAllNew_activate(self.gPodder))
def on_itemExportChannels_activate(self, widget, *args):
if not self.channels:
title = _('Nothing to export')
message = _('Your list of channel subscriptions is empty. Please subscribe to some podcasts first before trying to export your subscription list.')
message = _('Your list of podcast subscriptions is empty. Please subscribe to some podcasts first before trying to export your subscription list.')
self.show_message( message, title)
return
dlg = gtk.FileChooserDialog( title=_("Export to OPML"), parent = None, action = gtk.FILE_CHOOSER_ACTION_SAVE)
dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
dlg.add_button( gtk.STOCK_SAVE, gtk.RESPONSE_OK)
if gpodder.interface == gpodder.GUI:
dlg = gtk.FileChooserDialog(title=_('Export to OPML'), parent=self.gPodder, action=gtk.FILE_CHOOSER_ACTION_SAVE)
dlg.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
dlg.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_OK)
elif gpodder.interface == gpodder.MAEMO:
dlg = hildon.FileChooserDialog(self.gPodder, gtk.FILE_CHOOSER_ACTION_SAVE)
dlg.set_filter(self.get_opml_filter())
response = dlg.run()
if response == gtk.RESPONSE_OK:
filename = dlg.get_filename()
@ -1565,9 +1682,6 @@ class gPodder(GladeWidget):
def on_homepage_activate(self, widget, *args):
util.open_website(app_website)
def on_wishlist_activate(self, widget, *args):
util.open_website('http://www.amazon.de/gp/registry/2PD2MYGHE6857')
def on_wiki_activate(self, widget, *args):
util.open_website('http://wiki.gpodder.org/')
@ -1635,7 +1749,7 @@ class gPodder(GladeWidget):
self.updateTreeView()
def on_entryAddChannel_changed(self, widget, *args):
active = self.entryAddChannel.get_text() not in ('', _('Enter podcast URL'))
active = self.entryAddChannel.get_text() not in ('', self.ENTER_URL_TEXT)
self.btnAddChannel.set_sensitive( active)
def on_btnAddChannel_clicked(self, widget, *args):
@ -1688,11 +1802,6 @@ class gPodder(GladeWidget):
def on_btnDownloadNewer_clicked(self, widget, *args):
self.new_episodes_show(self.active_channel.get_new_episodes())
def on_btnSelectAllAvailable_clicked(self, widget, *args):
self.treeAvailable.get_selection().select_all()
self.on_treeAvailable_row_activated( self.toolDownload, args)
self.treeAvailable.get_selection().unselect_all()
def auto_update_procedure(self, first_run=False):
log('auto_update_procedure() got called', sender=self)
if not first_run and gl.config.auto_update_feeds and self.minimized:
@ -1806,11 +1915,6 @@ class gPodder(GladeWidget):
self.active_channel.force_update_tree_model()
self.updateTreeView()
def on_btnDeleteAll_clicked(self, widget, *args):
self.treeAvailable.get_selection().select_all()
self.on_btnDownloadedDelete_clicked( widget, args)
self.treeAvailable.get_selection().unselect_all()
def on_key_press(self, widget, event):
# Currently, we only handle Maemo hardware keys here,
# so if we are not a Maemo app, we don't do anything!
@ -1961,7 +2065,7 @@ class gPodderChannel(GladeWidget):
channel_url = self.channel.url
if entered_url != channel_url:
if self.show_confirmation(_('Do you really want to move this channel to <b>%s</b>?') % (saxutils.escape(entered_url),), _('Really change URL?')):
if self.show_confirmation(_('Do you really want to move this podcast to <b>%s</b>?') % (saxutils.escape(entered_url),), _('Really change URL?')):
if hasattr(self, 'callback_change_url'):
self.gPodderChannel.hide_all()
self.callback_change_url(channel_url, entered_url)
@ -2507,13 +2611,18 @@ class gPodderOpmlLister(GladeWidget):
self.callback_for_channel = None
self.callback_finished = None
if hasattr(self, 'custom_title'):
self.gPodderOpmlLister.set_title(self.custom_title)
if hasattr(self, 'hide_url_entry'):
self.hbox25.hide_all()
togglecell = gtk.CellRendererToggle()
togglecell.set_property( 'activatable', True)
togglecell.connect( 'toggled', self.callback_edited)
togglecolumn = gtk.TreeViewColumn( '', togglecell, active=0)
titlecell = gtk.CellRendererText()
titlecolumn = gtk.TreeViewColumn( _('Channel'), titlecell, markup=1)
titlecolumn = gtk.TreeViewColumn(_('Podcast'), titlecell, markup=1)
for itemcolumn in ( togglecolumn, titlecolumn ):
self.treeviewChannelChooser.append_column( itemcolumn)

View file

@ -199,6 +199,15 @@ class gPodderLib(object):
def history_is_locked( self, url):
return (url in self.__locked_history)
def send_subscriptions(self):
try:
subprocess.Popen(['xdg-email', '--subject', _('My podcast subscriptions'),
'--attach', self.channel_opml_file])
except:
return False
return True
def playback_episode( self, channel, episode):
self.history_mark_played( episode.url)
@ -234,7 +243,7 @@ class gPodderLib(object):
def image_download_thread( self, url, callback_pixbuf = None, callback_status = None, callback_finished = None, cover_file = None):
if callback_status is not None:
util.idle_add(callback_status, _('Downloading channel cover...'))
util.idle_add(callback_status, _('Downloading podcast cover...'))
pixbuf = gtk.gdk.PixbufLoader()
if cover_file is None: