gpodder/src/gpodder/gpodder.py

1459 lines
58 KiB
Python
Raw Normal View History

# -*- coding: UTF8 -*-
# Python module src/gpodder/gpodder.py
# Autogenerated from gpodder.glade
# Warning: Do not modify any context comment such as #--
# They are required to keep user's code
#
# gPodder (a media aggregator / podcast client)
# Copyright (C) 2005-2007 Thomas Perl <thp at perli.net>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
import os
import gtk
import gtk.gdk
import gobject
import pango
import sys
from threading import Event
from threading import Thread
from string import strip
from SimpleGladeApp import SimpleGladeApp
from SimpleGladeApp import bindtextdomain
from libpodcasts import podcastChannel
from libpodcasts import podcastItem
from libpodcasts import channelsToModel
from librssreader import rssReader
from libopmlwriter import opmlWriter
from libopmlreader import opmlReader
from libwget import downloadThread
from libwget import downloadStatusManager
from libgpodder import gPodderLib
from libgpodder import gPodderChannelReader
from libgpodder import gPodderChannelWriter
from liblogger import log
from liblocaldb import localDB
from libplayers import UserAppsReader
from libipodsync import gPodder_iPodSync
from libipodsync import gPodder_FSSync
from libipodsync import ipod_supported
app_name = "gpodder"
app_version = "unknown" # will be set in main() call
app_authors = [
'Thomas Perl <thp@perli.net>', '',
_('Contributors / patch writers:'),
'Peter Hoffmann <tosh@cs.tu-berlin.de>',
'Adrien Beaucreux <informancer@web.de>',
'Alain Tauch <contrib@maisondubonheur.com>', '',
_('See the AUTHORS file for all contributors')
]
app_copyright = 'Copyright (c) 2005-2007 Thomas Perl'
app_website = 'http://gpodder.berlios.de/'
glade_dir = '/usr/share/gpodder/'
icon_dir = '/usr/share/pixmaps/gpodder.png'
locale_dir = '/usr/share/locale/'
class Gpodder(SimpleGladeApp):
# Local DB
ldb = None
# User Apps Reader
uar = None
def __init__(self, path="gpodder.glade",
root="gPodder",
domain=app_name, **kwargs):
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
#-- Gpodder.new {
def new(self):
if app_version.rfind( "svn") != -1:
self.gPodder.set_title( 'gPodder %s' % ( app_version, ))
# set up the rendering of the comboAvailable combobox
cellrenderer = gtk.CellRendererText()
self.comboAvailable.pack_start( cellrenderer, True)
self.comboAvailable.add_attribute( cellrenderer, 'text', 1)
# See http://www.pygtk.org/pygtk2tutorial/sec-CellRenderers.html
namecell = gtk.CellRendererText()
namecell.set_property('cell-background', 'white')
namecell.set_property('ellipsize', pango.ELLIPSIZE_END)
namecolumn = gtk.TreeViewColumn( _("Episode"), namecell, text=1)
namecolumn.add_attribute(namecell, "cell-background", 4)
sizecell = gtk.CellRendererText()
sizecell.set_property('cell-background', 'white')
sizecolumn = gtk.TreeViewColumn( _("Size"), sizecell, text=2)
sizecolumn.add_attribute(sizecell, "cell-background", 4)
releasecell = gtk.CellRendererText()
releasecell.set_property('cell-background', 'white')
releasecolumn = gtk.TreeViewColumn( _("Released"), releasecell, text=5)
releasecolumn.add_attribute(releasecell, "cell-background", 4)
desccell = gtk.CellRendererText()
desccell.set_property('cell-background', 'white')
desccell.set_property('ellipsize', pango.ELLIPSIZE_END)
desccolumn = gtk.TreeViewColumn( _("Description"), desccell, text=6)
desccolumn.add_attribute(desccell, "cell-background", 4)
for itemcolumn in ( namecolumn, sizecolumn, releasecolumn, desccolumn ):
itemcolumn.set_resizable( True)
itemcolumn.set_reorderable( True)
self.treeAvailable.append_column( itemcolumn)
# enable multiple selection support
self.treeAvailable.get_selection().set_mode( gtk.SELECTION_MULTIPLE)
self.treeDownloads.get_selection().set_mode( gtk.SELECTION_MULTIPLE)
# columns and renderers for "download progress" tab
episodecell = gtk.CellRendererText()
episodecolumn = gtk.TreeViewColumn( _("Episode"), episodecell, text=0)
speedcell = gtk.CellRendererText()
speedcolumn = gtk.TreeViewColumn( _("Speed"), speedcell, text=1)
progresscell = gtk.CellRendererProgress()
progresscolumn = gtk.TreeViewColumn( _("Progress"), progresscell, value=2)
for itemcolumn in ( episodecolumn, speedcolumn, progresscolumn ):
self.treeDownloads.append_column( itemcolumn)
self.download_status_manager = downloadStatusManager( main_window = self.gPodder, change_notification = self.updateTreeView)
self.treeDownloads.set_model( self.download_status_manager.getModel())
# tooltips :)
self.tooltips = gtk.Tooltips()
self.tooltips.set_tip( self.btnEditChannel, _("Channel Info"))
#Add Drag and Drop Support
targets = [("text/plain", 0, 2), ('STRING', 0, 3), ('TEXT', 0, 4)]
self.main_widget.drag_dest_set(gtk.DEST_DEFAULT_ALL, targets, \
gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY | \
gtk.gdk.ACTION_DEFAULT)
self.main_widget.connect("drag_data_received", self.drag_data_received)
self.wNotebook.connect("switch-page", self.switched_notebook)
gl = gPodderLib()
# Subscribed channels
self.active_channel = None
self.channels = gPodderChannelReader().read( force_update = False)
self.update_feed_cache( force_update = gl.update_on_startup)
# create a localDB object
self.ldb = localDB()
# load list of user applications
self.user_apps_reader = UserAppsReader()
self.user_apps_reader.read()
# Clean up old, orphaned download files
gl.clean_up_downloads( delete_partial = True)
#-- Gpodder.new }
#-- Gpodder custom methods {
def play_or_download( self):
is_download_button = False
gl = gPodderLib()
try:
selection = self.treeAvailable.get_selection()
selection_tuple = selection.get_selected_rows()
for apath in selection_tuple[1]:
selection_iter = self.treeAvailable.get_model().get_iter( apath)
url = self.treeAvailable.get_model().get_value( selection_iter, 0)
filename = self.active_channel.getPodcastFilename( url)
if not os.path.exists( filename):
is_download_button = True
break
except:
is_download_button = True
if is_download_button:
self.btnPlay.hide_all()
self.btnDownload.show_all()
else:
self.btnPlay.show_all()
self.btnDownload.hide_all()
def updateComboBox( self):
try:
old_active = self.comboAvailable.get_active()
if old_active < 0:
old_active = 0
elif old_active > len( self.channels)-1:
old_active = len(self.channels)-1
self.comboAvailable.set_model( channelsToModel( self.channels))
self.comboAvailable.set_active( old_active)
except:
pass
def updateTreeView( self):
rect = self.treeAvailable.get_visible_rect()
if self.channels:
self.treeAvailable.set_model( self.active_channel.items_liststore( downloading_callback = self.download_status_manager.is_download_in_progress))
# now, reset the scrolling position
self.treeAvailable.scroll_to_point( rect.x, rect.y)
while gtk.events_pending():
gtk.main_iteration( False)
self.treeAvailable.scroll_to_point( rect.x, rect.y)
else:
if self.treeAvailable.get_model():
self.treeAvailable.get_model().clear()
def showMessage( self, message, title = _('gPodder message')):
dlg = gtk.MessageDialog( self.gPodder, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK)
dlg.set_title( title)
dlg.set_markup( message)
dlg.run()
dlg.destroy()
def showConfirmation( self, message = _('Do you really want to do this?'), title = _('gPodder confirmation')):
myresult = False
dlg = gtk.MessageDialog( self.gPodder, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO)
dlg.set_title( title)
dlg.set_markup( message)
if gtk.RESPONSE_YES == dlg.run():
myresult = True
dlg.destroy()
log( "I Asked: %s\nUser answered: %s", message, str( myresult))
return myresult
def set_icon(self):
icon = self.get_icon('gpodder')
self.main_widget.set_icon(icon)
def get_icon(self, entry, size=48):
path = icon_dir
if path == None:
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, size, size)
pb.fill(0x00000000)
else:
try:
pb = gtk.gdk.pixbuf_new_from_file_at_size(path, size, size)
except:
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, size, size)
pb.fill(0x00000000)
return pb
def switched_notebook( self, notebook, page, page_num):
if page_num == 0:
self.updateTreeView()
def drag_data_received(self, widget, context, x, y, sel, ttype, time):
result = sel.data
self.add_new_channel( result)
def refetch_channel_list( self):
channels_should_be = len( self.channels)
gPodderChannelWriter().write( self.channels)
self.update_feed_cache( force_update = False)
if channels_should_be > len( self.channels):
self.showMessage( _("There has been an error adding the channel.\nMaybe the URL is wrong?"))
def add_new_channel( self, result = None):
gl = gPodderLib()
result = gl.sanitize_feed_url( result)
if result:
for old_channel in self.channels:
if old_channel.url == result:
log( 'Channel already exists: %s', result)
# Select the existing channel in combo box
for i in range( len( self.channels)):
if self.channels[i] == old_channel:
self.comboAvailable.set_active( i)
return
log( 'Adding new channel: %s', result)
channel = podcastChannel( url = result)
channel.remove_cache_file()
num_channels_before = len(self.channels)
self.channels.append( channel)
# download changed channels
self.refetch_channel_list()
if num_channels_before < len(self.channels):
# ask user to download some new episodes
self.comboAvailable.set_active( len( self.channels)-1)
self.on_btnDownloadNewer_clicked( None)
else:
if result:
self.showMessage( _('Could not add new channel.\n\nThe URL must start with <b>http://</b>, <b>feed://</b> or <b>ftp://</b>.'))
def sync_to_ipod_proc( self, sync_win):
gpl = gPodderLib()
gpl.loadConfig()
sync = gPodder_iPodSync( ipod_mount = gpl.ipod_mount, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close)
if not sync.open():
gobject.idle_add( self.showMessage, _('Cannot access iPod.\nMake sure your iPod is connected and mounted.'))
sync.close()
return False
for channel in self.ldb.channel_list:
channel.set_metadata_from_localdb()
sync.sync_channel( channel)
sync.close()
def sync_to_fs_proc( self, sync_win):
gpl = gPodderLib()
gpl.loadConfig()
if not gpl.can_write_directory( gpl.mp3_player_folder):
gobject.idle_add( self.showMessage, _('Cannot write to %s.\nMake sure your MP3 player is connected.') % ( gpl.mp3_player_folder, ))
if sync_win.close:
sync_win.close()
return False
sync = gPodder_FSSync( destination = gpl.mp3_player_folder, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close)
for channel in self.ldb.channel_list:
channel.set_metadata_from_localdb()
sync.sync_channel( channel)
sync.close()
def ipod_cleanup_proc( self, sync_win):
gpl = gPodderLib()
gpl.loadConfig()
sync = gPodder_iPodSync( ipod_mount = gpl.ipod_mount, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close)
if not sync.open():
gobject.idle_add( self.showMessage, _('Cannot access iPod.\nMake sure your iPod is connected.'))
sync.close()
return False
sync.clean_playlist()
sync.close()
def fs_cleanup_proc( self, sync_win):
gpl = gPodderLib()
gpl.loadConfig()
if not gpl.can_write_directory( gpl.mp3_player_folder):
gobject.idle_add( self.showMessage, _('Cannot write to %s.\nMake sure your MP3 player is connected.') % ( gpl.mp3_player_folder, ))
if sync_win.close:
sync_win.close()
return False
sync = gPodder_FSSync( destination = gpl.mp3_player_folder, callback_status = sync_win.set_status, callback_progress = sync_win.set_progress, callback_done = sync_win.close)
sync.clean_playlist()
sync.close()
def update_feed_cache_callback( self, label, progressbar, position, count):
title = _('Please wait...')
if len(self.channels) > position:
title = _('Updating %s') % self.channels[position].title
label.set_markup( '<i>%s</i>' % title)
progressbar.set_text( _('%d of %d channels updated') % ( position, count ))
progressbar.set_fraction( ((1.00*position) / (1.00*count)))
def update_feed_cache_proc( self, reader, force_update, callback_proc, callback_error, finish_proc):
self.channels = reader.read( force_update, callback_proc = callback_proc, callback_error = callback_error)
finish_proc()
def update_feed_cache(self, force_update = True):
title = _('Downloading podcast feeds')
heading = _('Downloading feeds')
body = _('Podcast feeds contain channel metadata and information about current episodes.')
if not force_update:
title = _('Reading podcast feeds')
heading = _('Reading feeds')
please_wait = gtk.Dialog( title, self.gPodder, gtk.DIALOG_MODAL, ( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, ))
please_wait.set_transient_for( self.gPodder)
please_wait.set_position( gtk.WIN_POS_CENTER_ON_PARENT)
please_wait.vbox.set_spacing( 5)
please_wait.set_border_width( 10)
please_wait.set_resizable( False)
label_heading = gtk.Label()
label_heading.set_alignment( 0.0, 0.5)
label_heading.set_markup( '<span weight="bold" size="larger">%s</span>' % heading)
label_body = gtk.Label()
label_body.set_text( body)
label_body.set_alignment( 0.0, 0.5)
label_body.set_line_wrap( True)
myprogressbar = gtk.ProgressBar()
mylabel = gtk.Label()
mylabel.set_alignment( 0.0, 0.5)
mylabel.set_ellipsize( pango.ELLIPSIZE_END)
# put it all together
please_wait.vbox.pack_start( label_heading)
please_wait.vbox.pack_start( label_body)
please_wait.vbox.pack_start( myprogressbar)
please_wait.vbox.pack_end( mylabel)
please_wait.show_all()
# hide separator line
please_wait.set_has_separator( False)
# let's get down to business..
callback_proc = lambda pos, count: gobject.idle_add( self.update_feed_cache_callback, mylabel, myprogressbar, pos, count)
callback_error = lambda x: gobject.idle_add( self.showMessage( x))
finish_proc = lambda: gobject.idle_add( please_wait.destroy)
reader = gPodderChannelReader()
args = ( reader, force_update, callback_proc, callback_error, finish_proc, )
thread = Thread( target = self.update_feed_cache_proc, args = args)
thread.start()
if please_wait.run() == gtk.RESPONSE_CANCEL:
reader.cancel()
please_wait.destroy()
thread.join( 0.5)
self.updateComboBox()
# download all new?
if force_update and gPodderLib().download_after_update:
self.on_itemDownloadAllNew_activate( self.gPodder)
def download_podcast_by_url( self, url, want_message_dialog = True, widget = None):
current_channel = self.active_channel
current_podcast = current_channel.find_episode( url)
filename = current_channel.getPodcastFilename( current_podcast.url)
if widget:
if widget.get_name() == 'itemPlaySelected' or widget.get_name() == 'btnPlay':
gPodderLib().openFilename( filename)
return
if widget.get_name() == 'treeAvailable':
gpe = Gpodderepisode( gpodderwindow = self.gPodder)
gpe.set_episode( current_podcast, current_channel)
if os.path.exists( filename):
gpe.set_play_callback( lambda: gPodderLib().openFilename( filename))
else:
gpe.set_download_callback( lambda: self.download_podcast_by_url( url, want_message_dialog, None))
return
if not os.path.exists( filename) and not self.download_status_manager.is_download_in_progress( current_podcast.url):
downloadThread( current_podcast.url, filename, None, self.download_status_manager, current_podcast.title, current_channel, current_podcast, self.ldb).download()
else:
if want_message_dialog and os.path.exists( filename):
self.showMessage( _("You have already downloaded this episode,"))
elif want_message_dialog:
self.showMessage( _("This file is already being downloaded."))
if os.path.exists( filename):
log( 'Episode has already been downloaded.')
if current_channel.addDownloadedItem( current_podcast):
self.ldb.clear_cache()
# update tree view to mark the episode as being downloaded
self.updateTreeView()
#-- Gpodder custom methods }
#-- Gpodder.close_gpodder {
def close_gpodder(self, widget, *args):
if self.channels:
gPodderChannelWriter().write( self.channels)
if self.download_status_manager:
self.download_status_manager.cancelAll()
self.gtk_main_quit()
#-- Gpodder.close_gpodder }
#-- Gpodder.on_itemUpdate_activate {
def on_itemUpdate_activate(self, widget, *args):
if self.channels:
self.update_feed_cache()
else:
self.showMessage( _('Subscribe to some channels first.'))
#-- Gpodder.on_itemUpdate_activate }
#-- Gpodder.on_itemDownloadAllNew_activate {
def on_itemDownloadAllNew_activate(self, widget, *args):
gl = gPodderLib()
to_download = []
message_part = ''
for channel in self.channels:
s = 0
last_pubdate = channel.newest_pubdate_downloaded()
if not last_pubdate:
log( 'Downloading newest three episodes.')
for episode in channel[0:min(len(channel),3)]:
to_download.append( ( channel, episode ))
s = s + 1
else:
for episode in channel:
if episode.compare_pubdate( last_pubdate) >= 0 and not channel.is_downloaded( episode) and not gl.history_is_downloaded( episode.url):
log( 'Episode "%s" is newer.', episode.title)
to_download.append( ( channel, episode ))
s = s + 1
if s:
message_part = message_part + (_('%d new in %s') % ( s, channel.title, )) + "\n"
if to_download:
if self.showConfirmation( _("New episodes:\n\n%s\nDo you want to download them now?") % ( message_part, )):
for channel, episode in to_download:
filename = channel.getPodcastFilename( episode.url)
if not os.path.exists( filename) and not self.download_status_manager.is_download_in_progress( episode.url):
downloadThread( episode.url, filename, None, self.download_status_manager, episode.title, channel, episode, self.ldb).download()
else:
self.showMessage( _('No new episodes.'))
self.updateTreeView()
#-- Gpodder.on_itemDownloadAllNew_activate }
#-- Gpodder.on_sync_to_ipod_activate {
def on_sync_to_ipod_activate(self, widget, *args):
gl = gPodderLib()
if gl.device_type == 'none':
self.showMessage( _('Configure your device in the preferences dialog first.'))
elif gl.device_type == 'ipod':
if not ipod_supported():
self.showMessage( _('Please install python-gpod and pymad libraries.\nMore information on the gPodder homepage.'))
return
sync_win = Gpoddersync( gpodderwindow = self.gPodder)
while gtk.events_pending():
gtk.main_iteration( False)
args = ( sync_win, )
thread = Thread( target = self.sync_to_ipod_proc, args = args)
thread.start()
elif gl.device_type == 'filesystem':
sync_win = Gpoddersync( gpodderwindow = self.gPodder)
while gtk.events_pending():
gtk.main_iteration( False)
args = ( sync_win, )
thread = Thread( target = self.sync_to_fs_proc, args = args)
thread.start()
#-- Gpodder.on_sync_to_ipod_activate }
#-- Gpodder.on_cleanup_ipod_activate {
def on_cleanup_ipod_activate(self, widget, *args):
gl = gPodderLib()
target_function = None
if gl.device_type == 'none':
self.showMessage( _('Configure your device in the preferences dialog first.'))
elif gl.device_type == 'ipod':
if self.showConfirmation( _('Do you really want to truncate the Podcasts playlist on your iPod?')):
target_function = self.ipod_cleanup_proc
elif gl.device_type == 'filesystem':
if self.showConfirmation( _('Do you really want to delete all Podcasts from your MP3 player?')):
target_function = self.fs_cleanup_proc
if target_function:
sync_win = Gpoddersync( gpodderwindow = self.gPodder)
while gtk.events_pending():
gtk.main_iteration( False)
args = ( sync_win, )
thread = Thread( target = target_function, args = args)
thread.start()
#-- Gpodder.on_cleanup_ipod_activate }
#-- Gpodder.on_itemPreferences_activate {
def on_itemPreferences_activate(self, widget, *args):
prop = Gpodderproperties( gpodderwindow = self.gPodder)
prop.set_uar( self.user_apps_reader)
prop.set_callback_finished( self.updateTreeView)
#-- Gpodder.on_itemPreferences_activate }
#-- Gpodder.on_itemAddChannel_activate {
def on_itemAddChannel_activate(self, widget, *args):
self.add_new_channel( Gpodderchannel( gpodderwindow = self.gPodder).requestURL())
#-- Gpodder.on_itemAddChannel_activate }
#-- Gpodder.on_itemEditChannel_activate {
def on_itemEditChannel_activate(self, widget, *args):
if not self.active_channel:
self.showMessage( _('Please select a channel to edit.'))
return
result = Gpodderchannel( gpodderwindow = self.gPodder).requestURL( self.active_channel)
self.updateComboBox()
active = self.comboAvailable.get_active()
if result != self.active_channel.url and result != None and result != "" and (result[:4] == "http" or result[:3] == "ftp"):
log( 'Changing channel #%d from "%s" to "%s"', active, self.active_channel.url, result)
self.channels = self.channels[0:active] + [ podcastChannel( url = result) ] + self.channels[active+1:]
self.refetch_channel_list()
#-- Gpodder.on_itemEditChannel_activate }
#-- Gpodder.on_itemRemoveChannel_activate {
def on_itemRemoveChannel_activate(self, widget, *args):
try:
if self.showConfirmation( _("Do you really want to remove this channel and downloaded episodes?\n\n %s") % self.active_channel.title):
self.active_channel.remove_cache_file()
self.active_channel.remove_downloaded()
# only delete partial files if we do not have any downloads in progress
delete_partial = not self.download_status_manager.has_items()
gPodderLib().clean_up_downloads( delete_partial)
self.channels.remove( self.active_channel)
gPodderChannelWriter().write( self.channels)
self.update_feed_cache( force_update = False)
except:
pass
#-- Gpodder.on_itemRemoveChannel_activate }
#-- Gpodder.on_itemExportChannels_activate {
def on_itemExportChannels_activate(self, widget, *args):
if not self.channels:
self.showMessage( _("Your channel list is empty. Nothing to export."))
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)
response = dlg.run()
if response == gtk.RESPONSE_OK:
foutname = dlg.get_filename()
if foutname[-5:] != ".opml" and foutname[-4:] != ".xml":
foutname = foutname + ".opml"
log( 'Exporting channel list to: %s', foutname)
w = opmlWriter( foutname)
for ch in self.channels:
w.addChannel( ch)
w.close()
dlg.destroy()
#-- Gpodder.on_itemExportChannels_activate }
#-- Gpodder.on_itemImportChannels_activate {
def on_itemImportChannels_activate(self, widget, *args):
Gpodderopmllister( gpodderwindow = self.gPodder).get_channels_from_url( gPodderLib().opml_url, self.add_new_channel)
#-- Gpodder.on_itemImportChannels_activate }
#-- Gpodder.on_homepage_activate {
def on_homepage_activate(self, widget, *args):
os.system( 'gnome-open ' + app_website)
#-- Gpodder.on_homepage_activate }
#-- Gpodder.on_wishlist_activate {
def on_wishlist_activate(self, widget, *args):
os.system( 'gnome-open http://www.amazon.de/gp/registry/2PD2MYGHE6857')
#-- Gpodder.on_wishlist_activate }
#-- Gpodder.on_mailinglist_activate {
def on_mailinglist_activate(self, widget, *args):
os.system( 'gnome-open http://lists.berlios.de/mailman/listinfo/gpodder-devel')
#-- Gpodder.on_mailinglist_activate }
#-- Gpodder.on_itemAbout_activate {
def on_itemAbout_activate(self, widget, *args):
dlg = gtk.AboutDialog()
dlg.set_name( app_name)
dlg.set_version( app_version)
dlg.set_authors( app_authors)
dlg.set_copyright( app_copyright)
dlg.set_website( app_website)
dlg.set_translator_credits( _('translator-credits'))
dlg.connect("response", self.on_aboutDialog_response)
try:
dlg.set_logo( gtk.gdk.pixbuf_new_from_file_at_size( icon_dir, 200, 200))
except:
pass
dlg.run()
#-- Gpodder.on_itemAbout_activate }
def on_aboutDialog_response(self, dialog, response):
dialog.destroy()
#-- Gpodder.on_wNotebook_switch_page {
def on_wNotebook_switch_page(self, widget, *args):
pass
#-- Gpodder.on_wNotebook_switch_page }
#-- Gpodder.on_comboAvailable_changed {
def on_comboAvailable_changed(self, widget, *args):
try:
self.active_channel = self.channels[self.comboAvailable.get_active()]
except:
self.active_channel = None
if self.active_channel:
self.itemEditChannel.get_child().set_text( _('Edit "%s"') % ( self.active_channel.title,))
self.itemRemoveChannel.get_child().set_text( _('Remove "%s"') % ( self.active_channel.title,))
self.itemEditChannel.show_all()
self.itemRemoveChannel.show_all()
else:
self.itemEditChannel.hide_all()
self.itemRemoveChannel.hide_all()
self.updateTreeView()
#-- Gpodder.on_comboAvailable_changed }
#-- Gpodder.on_btnEditChannel_clicked {
def on_btnEditChannel_clicked(self, widget, *args):
self.on_itemEditChannel_activate( widget, args)
#-- Gpodder.on_btnEditChannel_clicked }
#-- Gpodder.on_treeAvailable_row_activated {
def on_treeAvailable_row_activated(self, widget, *args):
try:
selection = self.treeAvailable.get_selection()
selection_tuple = selection.get_selected_rows()
if selection.count_selected_rows() > 1:
widget_to_send = None
show_message_dialog = False
else:
widget_to_send = widget
show_message_dialog = True
for apath in selection_tuple[1]:
selection_iter = self.treeAvailable.get_model().get_iter( apath)
url = self.treeAvailable.get_model().get_value( selection_iter, 0)
self.download_podcast_by_url( url, show_message_dialog, widget_to_send)
except:
self.showMessage( _("You have not selected an episode to download."))
#-- Gpodder.on_treeAvailable_row_activated }
#-- Gpodder.on_btnDownload_clicked {
def on_btnDownload_clicked(self, widget, *args):
self.on_treeAvailable_row_activated( widget, args)
#-- Gpodder.on_btnDownload_clicked }
#-- Gpodder.on_treeAvailable_button_release_event {
def on_treeAvailable_button_release_event(self, widget, *args):
self.play_or_download()
#-- Gpodder.on_treeAvailable_button_release_event }
#-- Gpodder.on_btnDownloadNewer_clicked {
def on_btnDownloadNewer_clicked(self, widget, *args):
channel = self.active_channel
episodes_to_download = []
gl = gPodderLib()
last_pubdate = channel.newest_pubdate_downloaded()
if not last_pubdate:
if self.showConfirmation( _('Would you like to download the three newest episodes in this channel?')):
episodes_to_download = channel[0:min(len(channel),3)]
else:
for episode in channel:
if episode.compare_pubdate( last_pubdate) >= 0 and not channel.is_downloaded( episode) and not gl.history_is_downloaded( episode.url):
log( 'Episode "%s" is newer.', episode.title)
episodes_to_download.append( episode)
if not episodes_to_download:
self.showMessage( _('You have already downloaded the most recent episode.'))
else:
e_str = '\n'.join( [ e.title for e in episodes_to_download ] )
if not self.showConfirmation( _('Do you want to download these episodes?\n\n%s') % ( e_str, )):
return
for episode in episodes_to_download:
self.download_podcast_by_url( episode.url, False)
#-- Gpodder.on_btnDownloadNewer_clicked }
#-- Gpodder.on_btnSelectAllAvailable_clicked {
def on_btnSelectAllAvailable_clicked(self, widget, *args):
self.treeAvailable.get_selection().select_all()
self.on_treeAvailable_row_activated( self.btnDownload, args)
self.treeAvailable.get_selection().unselect_all()
#-- Gpodder.on_btnSelectAllAvailable_clicked }
#-- Gpodder.on_treeDownloads_row_activated {
def on_treeDownloads_row_activated(self, widget, *args):
selection = self.treeDownloads.get_selection()
selection_tuple = selection.get_selected_rows()
if selection.count_selected_rows() == 0:
log( 'Nothing selected to cancel.')
return
if selection.count_selected_rows() == 1:
msg = _("Do you really want to cancel this download?")
else:
msg = _("Do you really want to cancel %d downloads?") % selection.count_selected_rows()
if self.showConfirmation( msg):
# cancel downloads one by one
try:
for apath in selection_tuple[1]:
selection_iter = self.treeDownloads.get_model().get_iter( apath)
url = self.download_status_manager.get_url_by_iter( selection_iter)
self.download_status_manager.cancel_by_url( url)
except:
log( 'Error while cancelling downloads.')
#-- Gpodder.on_treeDownloads_row_activated }
#-- Gpodder.on_btnCancelDownloadStatus_clicked {
def on_btnCancelDownloadStatus_clicked(self, widget, *args):
self.on_treeDownloads_row_activated( widget, None)
#-- Gpodder.on_btnCancelDownloadStatus_clicked }
#-- Gpodder.on_btnCancelAll_clicked {
def on_btnCancelAll_clicked(self, widget, *args):
self.treeDownloads.get_selection().select_all()
self.on_treeDownloads_row_activated( self.btnCancelDownloadStatus, None)
self.treeDownloads.get_selection().unselect_all()
#-- Gpodder.on_btnCancelAll_clicked }
#-- Gpodder.on_btnDownloadedExecute_clicked {
def on_btnDownloadedExecute_clicked(self, widget, *args):
self.on_treeAvailable_row_activated( widget, args)
#-- Gpodder.on_btnDownloadedExecute_clicked }
#-- Gpodder.on_btnDownloadedDelete_clicked {
def on_btnDownloadedDelete_clicked(self, widget, *args):
channel_url = self.active_channel.url
selection = self.treeAvailable.get_selection()
selection_tuple = selection.get_selected_rows()
model = self.treeAvailable.get_model()
if selection.count_selected_rows() == 0:
log( 'Nothing selected - will not remove any downloaded episode.')
return
if selection.count_selected_rows() == 1:
msg = _("Do you really want to remove this episode?")
else:
msg = _("Do you really want to remove %d episodes?") % ( selection.count_selected_rows() )
# if user confirms deletion, let's remove some stuff ;)
if self.showConfirmation( msg):
try:
# iterate over the selection, see also on_treeDownloads_row_activated
for apath in selection_tuple[1]:
selection_iter = model.get_iter( apath)
url = model.get_value( selection_iter, 0)
episode_filename = self.ldb.get_filename_by_podcast( channel_url, url)
if episode_filename:
self.active_channel.delete_episode_by_url( url)
gPodderLib().deleteFilename( episode_filename)
# now, clear local db cache so we can re-read it
self.ldb.clear_cache()
self.updateComboBox()
except:
log( 'Error while deleting (some) downloads.')
# only delete partial files if we do not have any downloads in progress
delete_partial = not self.download_status_manager.has_items()
gPodderLib().clean_up_downloads( delete_partial)
#-- Gpodder.on_btnDownloadedDelete_clicked }
#-- Gpodder.on_btnDeleteAll_clicked {
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()
#-- Gpodder.on_btnDeleteAll_clicked }
class Gpodderchannel(SimpleGladeApp):
event = None
channel = None
podcast = None
thread = None
def __init__(self, path="gpodder.glade",
root="gPodderChannel",
domain=app_name, **kwargs):
waiting = None
url = ""
result = False
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
if 'gpodderwindow' in kwargs:
self.gPodderChannel.set_transient_for( kwargs['gpodderwindow'])
self.gPodderChannel.set_position( gtk.WIN_POS_CENTER_ON_PARENT)
#-- Gpodderchannel.new {
def new(self):
pass
#-- Gpodderchannel.new }
#-- Gpodderchannel custom methods {
def requestURL( self, channel = None):
if channel:
self.gPodderChannel.set_title( _('Channel: %s') % channel.title)
self.entryURL.set_text( channel.url)
self.entryTitle.set_text( channel.title)
self.LabelDownloadTo.set_text( channel.save_dir)
self.LabelWebsite.set_text( channel.link)
channel.set_metadata_from_localdb()
self.cbNoSync.set_active( not channel.sync_to_devices)
self.musicPlaylist.set_text( channel.device_playlist_name)
self.cbMusicChannel.set_active( channel.is_music_channel)
description = channel.description
if channel.image != None:
# load image in background
gPodderLib().get_image_from_url( channel.image, self.imgCover.set_from_pixbuf, self.labelCoverStatus.set_text, self.labelCoverStatus.hide, channel.cover_file)
else:
# Remove all tabs except for the first one
while self.notebookChannelEditor.get_n_pages() > 1:
self.notebookChannelEditor.remove_page( -1)
for widget in ( self.labelDescription, self.scrolledwindow, self.expander, self.labelTitle, self.entryTitle ):
widget.hide_all()
self.gPodderChannel.set_title( _('Add a new channel'))
self.gPodderChannel.queue_resize()
description = _("(unknown)")
b = gtk.TextBuffer()
b.set_text( description)
self.channel_description.set_buffer( b)
self.waiting = Event()
while self.waiting.isSet() == False:
self.waiting.wait( 0.01)
while gtk.events_pending():
gtk.main_iteration( False)
if self.result == True:
if channel != None:
channel.sync_to_devices = not self.cbNoSync.get_active()
channel.is_music_channel = self.cbMusicChannel.get_active()
channel.device_playlist_name = self.musicPlaylist.get_text()
channel.set_custom_title( self.entryTitle.get_text())
channel.save_metadata_to_localdb()
return self.url
else:
return None
#-- Gpodderchannel custom methods }
#-- Gpodderchannel.on_gPodderChannel_destroy {
def on_gPodderChannel_destroy(self, widget, *args):
self.result = False
#-- Gpodderchannel.on_gPodderChannel_destroy }
#-- Gpodderchannel.on_cbMusicChannel_toggled {
def on_cbMusicChannel_toggled(self, widget, *args):
self.musicPlaylist.set_sensitive( self.cbMusicChannel.get_active())
#-- Gpodderchannel.on_cbMusicChannel_toggled }
#-- Gpodderchannel.on_btnOK_clicked {
def on_btnOK_clicked(self, widget, *args):
self.url = self.entryURL.get_text()
self.gPodderChannel.destroy()
self.result = True
if self.waiting != None:
self.waiting.set()
#-- Gpodderchannel.on_btnOK_clicked }
#-- Gpodderchannel.on_btnCancel_clicked {
def on_btnCancel_clicked(self, widget, *args):
self.gPodderChannel.destroy()
self.result = False
if self.waiting != None:
self.waiting.set()
#-- Gpodderchannel.on_btnCancel_clicked }
class Gpodderproperties(SimpleGladeApp):
def __init__(self, path="gpodder.glade",
root="gPodderProperties",
domain=app_name, **kwargs):
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
if 'gpodderwindow' in kwargs:
self.gPodderProperties.set_transient_for( kwargs['gpodderwindow'])
self.gPodderProperties.set_position( gtk.WIN_POS_CENTER_ON_PARENT)
#-- Gpodderproperties.new {
def new(self):
self.callback_finished = None
gl = gPodderLib()
self.httpProxy.set_text( gl.http_proxy)
self.ftpProxy.set_text( gl.ftp_proxy)
self.openApp.set_text( gl.open_app)
self.iPodMountpoint.set_label( gl.ipod_mount)
self.ipodIcon.set_from_icon_name( 'gnome-dev-ipod', gtk.ICON_SIZE_BUTTON)
self.filesystemMountpoint.set_label( gl.mp3_player_folder)
self.opmlURL.set_text( gl.opml_url)
if gl.downloaddir:
self.chooserDownloadTo.set_filename( gl.downloaddir)
self.updateonstartup.set_active(gl.update_on_startup)
self.downloadnew.set_active(gl.download_after_update)
# colors
self.reload_colors()
# device type
self.comboboxDeviceType.set_active( 0)
if gl.device_type == 'ipod':
self.comboboxDeviceType.set_active( 1)
elif gl.device_type == 'filesystem':
self.comboboxDeviceType.set_active( 2)
# the use proxy env vars check box
self.cbEnvironmentVariables.set_active( gl.proxy_use_environment)
# if the symlink exists, set the checkbox active
self.cbDesktopSymlink.set_active( gl.getDesktopSymlink())
# setup cell renderers
cellrenderer = gtk.CellRendererPixbuf()
self.comboPlayerApp.pack_start( cellrenderer, False)
self.comboPlayerApp.add_attribute( cellrenderer, 'pixbuf', 2)
cellrenderer = gtk.CellRendererText()
self.comboPlayerApp.pack_start( cellrenderer, True)
self.comboPlayerApp.add_attribute( cellrenderer, 'markup', 0)
# end setup cell renderers
self.on_close = None
#-- Gpodderproperties.new }
#-- Gpodderproperties custom methods {
def on_btnRevertToDefault_clicked( self, widget, *args):
gl = gPodderLib()
gl.set_default_colors()
self.reload_colors()
def reload_colors( self):
gl = gPodderLib()
try:
self.colorDefault.set_color( gtk.gdk.color_parse( gl.colors['default']))
self.colorDownloading.set_color( gtk.gdk.color_parse( gl.colors['downloading']))
self.colorDownloaded.set_color( gtk.gdk.color_parse( gl.colors['downloaded']))
self.colorDeleted.set_color( gtk.gdk.color_parse( gl.colors['deleted']))
except:
log( '(gPodderProperties) Could not parse color strings.')
def update_mountpoint( self, ipod):
if ipod == None or ipod.mount_point == None:
self.iPodMountpoint.set_label( '')
else:
self.iPodMountpoint.set_label( ipod.mount_point)
def set_uar( self, uar):
self.comboPlayerApp.set_model( uar.get_applications_as_model())
# try to activate an item
index = self.find_active()
self.comboPlayerApp.set_active( index)
def set_callback_finished( self, cb):
self.callback_finished = cb
# end set_uar
def find_active( self):
model = self.comboPlayerApp.get_model()
iter = model.get_iter_first()
index = 0
while iter != None:
command = model.get_value( iter, 1)
if command == self.openApp.get_text():
return index
iter = model.iter_next( iter)
index = index + 1
# return last item = custom command
return index-1
# end find_active
def set_download_dir( self, new_download_dir, event = None):
gl = gPodderLib()
gl.downloaddir = self.chooserDownloadTo.get_filename()
if event:
event.set()
#-- Gpodderproperties custom methods }
#-- Gpodderproperties.on_gPodderProperties_destroy {
def on_gPodderProperties_destroy(self, widget, *args):
if self.on_close != None:
self.on_close()
#-- Gpodderproperties.on_gPodderProperties_destroy }
#-- Gpodderproperties.on_comboPlayerApp_changed {
def on_comboPlayerApp_changed(self, widget, *args):
# find out which one
iter = self.comboPlayerApp.get_active_iter()
model = self.comboPlayerApp.get_model()
command = model.get_value( iter, 1)
if command == '':
self.openApp.set_sensitive( True)
self.openApp.show()
self.labelCustomCommand.show()
else:
self.openApp.set_text( command)
self.openApp.set_sensitive( False)
self.openApp.hide()
self.labelCustomCommand.hide()
#-- Gpodderproperties.on_comboPlayerApp_changed }
#-- Gpodderproperties.on_comboboxDeviceType_changed {
def on_comboboxDeviceType_changed(self, widget, *args):
active_item = self.comboboxDeviceType.get_active()
# iPod
if active_item == 1:
self.ipodLabel.show()
self.btn_iPodMountpoint.set_sensitive( True)
self.btn_iPodMountpoint.show_all()
else:
self.ipodLabel.hide()
self.btn_iPodMountpoint.set_sensitive( False)
self.btn_iPodMountpoint.hide()
# filesystem-based MP3 player
if active_item == 2:
self.filesystemLabel.show()
self.btn_filesystemMountpoint.set_sensitive( True)
self.btn_filesystemMountpoint.show_all()
else:
self.filesystemLabel.hide()
self.btn_filesystemMountpoint.set_sensitive( False)
self.btn_filesystemMountpoint.hide()
#-- Gpodderproperties.on_comboboxDeviceType_changed }
#-- Gpodderproperties.on_btn_iPodMountpoint_clicked {
def on_btn_iPodMountpoint_clicked(self, widget, *args):
fs = gtk.FileChooserDialog( title = _('Select iPod mountpoint'), action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
fs.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
fs.add_button( gtk.STOCK_OPEN, gtk.RESPONSE_OK)
gl = gPodderLib()
fs.set_filename( self.iPodMountpoint.get_label())
if fs.run() == gtk.RESPONSE_OK:
self.iPodMountpoint.set_label( fs.get_filename())
fs.destroy()
#-- Gpodderproperties.on_btn_iPodMountpoint_clicked }
#-- Gpodderproperties.on_btn_FilesystemMountpoint_clicked {
def on_btn_FilesystemMountpoint_clicked(self, widget, *args):
fs = gtk.FileChooserDialog( title = _('Select folder for MP3 player'), action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
fs.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
fs.add_button( gtk.STOCK_OPEN, gtk.RESPONSE_OK)
gl = gPodderLib()
fs.set_filename( self.filesystemMountpoint.get_label())
if fs.run() == gtk.RESPONSE_OK:
self.filesystemMountpoint.set_label( fs.get_filename())
fs.destroy()
#-- Gpodderproperties.on_btn_FilesystemMountpoint_clicked }
#-- Gpodderproperties.on_cbEnvironmentVariables_toggled {
def on_cbEnvironmentVariables_toggled(self, widget, *args):
sens = not self.cbEnvironmentVariables.get_active()
self.httpProxy.set_sensitive( sens)
self.ftpProxy.set_sensitive( sens)
#-- Gpodderproperties.on_cbEnvironmentVariables_toggled }
#-- Gpodderproperties.on_btnOK_clicked {
def on_btnOK_clicked(self, widget, *args):
gl = gPodderLib()
gl.http_proxy = self.httpProxy.get_text()
gl.ftp_proxy = self.ftpProxy.get_text()
gl.open_app = self.openApp.get_text()
gl.proxy_use_environment = self.cbEnvironmentVariables.get_active()
gl.ipod_mount = self.iPodMountpoint.get_label()
gl.mp3_player_folder = self.filesystemMountpoint.get_label()
gl.opml_url = self.opmlURL.get_text()
try:
gl.set_color( 'default', self.colorDefault.get_color())
gl.set_color( 'downloading', self.colorDownloading.get_color())
gl.set_color( 'downloaded', self.colorDownloaded.get_color())
gl.set_color( 'deleted', self.colorDeleted.get_color())
except:
log('(gPodderProperties) Could not parse and save color values.')
if gl.downloaddir != self.chooserDownloadTo.get_filename():
new_download_dir = self.chooserDownloadTo.get_filename()
download_dir_size = gl.get_size( gl.downloaddir)
download_dir_size_string = gl.size_to_string( download_dir_size, 'MB')
event = Event()
dlg = gtk.Dialog( _('Moving downloads folder'), self.gPodderProperties)
dlg.vbox.set_spacing( 5)
dlg.set_border_width( 5)
label = gtk.Label()
label.set_line_wrap( True)
label.set_markup( _('Moving downloads from <b>%s</b> to <b>%s</b>...') % ( gl.downloaddir, new_download_dir, ))
myprogressbar = gtk.ProgressBar()
# put it all together
dlg.vbox.pack_start( label)
dlg.vbox.pack_end( myprogressbar)
# switch windows
dlg.show_all()
self.gPodderProperties.hide_all()
# hide action area and separator line
dlg.action_area.hide()
dlg.set_has_separator( False)
args = ( new_download_dir, event, )
thread = Thread( target = self.set_download_dir, args = args)
thread.start()
while not event.isSet():
new_download_dir_size = gl.get_size( new_download_dir)
fract = (1.00*new_download_dir_size) / (1.00*download_dir_size)
if fract < 0.99:
myprogressbar.set_text( _('%s of %s') % ( gl.size_to_string( new_download_dir_size, 'MB'), download_dir_size_string, ))
else:
myprogressbar.set_text( _('Finishing... please wait.'))
myprogressbar.set_fraction( fract)
event.wait( 0.1)
while gtk.events_pending():
gtk.main_iteration( False)
dlg.destroy()
gl.update_on_startup = self.updateonstartup.get_active()
gl.download_after_update = self.downloadnew.get_active()
device_type = self.comboboxDeviceType.get_active()
if device_type == 0:
gl.device_type = 'none'
elif device_type == 1:
gl.device_type = 'ipod'
elif device_type == 2:
gl.device_type = 'filesystem'
gl.propertiesChanged()
# create or remove symlink to download dir on desktop
if self.cbDesktopSymlink.get_active():
gl.createDesktopSymlink()
else:
gl.removeDesktopSymlink()
self.gPodderProperties.destroy()
if self.callback_finished:
self.callback_finished()
#-- Gpodderproperties.on_btnOK_clicked }
#-- Gpodderproperties.on_btnCancel_clicked {
def on_btnCancel_clicked(self, widget, *args):
self.gPodderProperties.destroy()
#-- Gpodderproperties.on_btnCancel_clicked }
class Gpodderepisode(SimpleGladeApp):
def __init__(self, path="gpodder.glade",
root="gPodderEpisode",
domain=app_name, **kwargs):
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
if 'gpodderwindow' in kwargs:
self.gPodderEpisode.set_transient_for( kwargs['gpodderwindow'])
self.gPodderEpisode.set_position( gtk.WIN_POS_CENTER_ON_PARENT)
#-- Gpodderepisode.new {
def new(self):
pass
#-- Gpodderepisode.new }
#-- Gpodderepisode custom methods {
# Write your own methods here
def set_episode( self, episode, channel = None):
self.episode_title.set_markup( '<big><b>%s</b></big>' % episode.title)
b = gtk.TextBuffer()
b.set_text( strip( episode.description))
self.episode_description.set_buffer( b)
self.LabelDownloadLink.set_text(episode.url)
self.LabelWebsiteLink.set_text(episode.link)
self.gPodderEpisode.set_title( episode.title)
if not episode.link and channel:
self.LabelWebsiteLink.set_text( channel.link)
if channel:
smalltext = _('from %s') % ( channel.title )
self.channel_title.set_markup( '<small>%s</small>' % smalltext)
self.labelPubDate.set_markup( '<b>%s</b>' % ( episode.pubDate ))
self.download_callback = None
self.play_callback = None
def set_download_callback( self, callback = None):
self.download_callback = callback
if callback:
self.btnDownload.show_all()
def set_play_callback( self, callback = None):
self.play_callback = callback
if callback:
self.btnPlay.show_all()
#-- Gpodderepisode custom methods }
#-- Gpodderepisode.on_btnCloseWindow_clicked {
def on_btnCloseWindow_clicked(self, widget, *args):
self.gPodderEpisode.destroy()
#-- Gpodderepisode.on_btnCloseWindow_clicked }
#-- Gpodderepisode.on_btnDownload_clicked {
def on_btnDownload_clicked(self, widget, *args):
# if we have a callback, .. well.. call it back! ;)
if self.download_callback:
self.download_callback()
self.gPodderEpisode.destroy()
#-- Gpodderepisode.on_btnDownload_clicked }
#-- Gpodderepisode.on_btnPlay_clicked {
def on_btnPlay_clicked(self, widget, *args):
if self.play_callback:
self.play_callback()
self.gPodderEpisode.destroy()
#-- Gpodderepisode.on_btnPlay_clicked }
class Gpoddersync(SimpleGladeApp):
def __init__(self, path="gpodder.glade",
root="gPodderSync",
domain=app_name, **kwargs):
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
if 'gpodderwindow' in kwargs:
self.gPodderSync.set_transient_for( kwargs['gpodderwindow'])
self.gPodderSync.set_position( gtk.WIN_POS_CENTER_ON_PARENT)
#-- Gpoddersync.new {
def new(self):
self.imageSyncServer.set_from_icon_name( 'gnome-fs-client', gtk.ICON_SIZE_DIALOG)
self.imageSyncAnimation.set_from_stock( gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
self.imageSyncClient.set_from_icon_name( 'gnome-dev-ipod', gtk.ICON_SIZE_DIALOG)
#-- Gpoddersync.new }
#-- Gpoddersync custom methods {
def set_progress( self, pos, max):
self.pbSync.set_fraction( 1.0*pos/max)
percent = _('%d of %d') % ( pos, max )
self.pbSync.set_text( percent)
def set_status( self, episode = None, channel = None, progressbar = None):
if episode != None:
self.labelEpisode.set_text( episode)
if channel != None:
self.labelChannel.set_text( channel)
if progressbar != None:
self.pbSync.set_text( progressbar)
def close( self):
self.gPodderSync.destroy()
#-- Gpoddersync custom methods }
#-- Gpoddersync.on_gPodderSync_destroy {
def on_gPodderSync_destroy(self, widget, *args):
pass
#-- Gpoddersync.on_gPodderSync_destroy }
class Gpodderopmllister(SimpleGladeApp):
def __init__(self, path="gpodder.glade",
root="gPodderOpmlLister",
domain=app_name, **kwargs):
path = os.path.join(glade_dir, path)
SimpleGladeApp.__init__(self, path, root, domain, **kwargs)
if 'gpodderwindow' in kwargs:
self.gPodderOpmlLister.set_transient_for( kwargs['gpodderwindow'])
self.gPodderOpmlLister.set_position( gtk.WIN_POS_CENTER_ON_PARENT)
#-- Gpodderopmllister.new {
def new(self):
# initiate channels list
self.channels = []
self.callback_for_channel = None
togglecell = gtk.CellRendererToggle()
togglecell.set_property( 'activatable', True)
togglecell.connect( 'toggled', self.callback_edited)
togglecolumn = gtk.TreeViewColumn( _("Subscribe"), togglecell, active=0)
titlecell = gtk.CellRendererText()
titlecolumn = gtk.TreeViewColumn( _("Channel name"), titlecell, text=1)
for itemcolumn in ( togglecolumn, titlecolumn ):
self.treeviewChannelChooser.append_column( itemcolumn)
#-- Gpodderopmllister.new }
#-- Gpodderopmllister custom methods {
# Write your own methods here
def callback_edited( self, cell, path):
model = self.treeviewChannelChooser.get_model()
activated = not model[path][0]
url = model[path][2]
model[path][0] = activated
if activated:
self.channels.append( url)
else:
self.channels.remove( url)
log( 'Edited: %s', url)
def get_channels_from_url( self, url, callback):
reader = opmlReader()
reader.parseXML( url)
self.treeviewChannelChooser.set_model( reader.get_model())
self.callback_for_channel = callback
#-- Gpodderopmllister custom methods }
#-- Gpodderopmllister.on_gPodderOpmlLister_destroy {
def on_gPodderOpmlLister_destroy(self, widget, *args):
pass
#-- Gpodderopmllister.on_gPodderOpmlLister_destroy }
#-- Gpodderopmllister.on_btnOK_clicked {
def on_btnOK_clicked(self, widget, *args):
self.gPodderOpmlLister.destroy()
# add channels that have been selected
for url in self.channels:
if self.callback_for_channel != None:
self.callback_for_channel (url)
#-- Gpodderopmllister.on_btnOK_clicked }
#-- Gpodderopmllister.on_btnCancel_clicked {
def on_btnCancel_clicked(self, widget, *args):
self.gPodderOpmlLister.destroy()
#-- Gpodderopmllister.on_btnCancel_clicked }
#-- main {
def main( __version__ = None):
global app_version
gobject.threads_init()
bindtextdomain( app_name, locale_dir)
app_version = __version__
g_podder = Gpodder()
g_podder.set_icon()
g_podder.run()
#-- main }