new opml importer dialog, fixed stuff :)

git-svn-id: svn://svn.berlios.de/gpodder/trunk@348 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
Thomas Perl 2007-07-11 18:12:02 +00:00
parent 45a99ffb92
commit 9171cf5051
7 changed files with 288 additions and 71 deletions

View File

@ -1,3 +1,17 @@
Wed, 11 Jul 2007 20:09:03 +0200 <thp@perli.net>
* src/gpodder/libpodcasts.py: Add description field to opmlChannel
* src/gpodder/libgpodder.py: Default OPML directory URL changed from
Opml.org's top Podcasts to gPodder's own podcast directory :)
* src/gpodder/libopmlreader.py: Add description of channel to the
data model if possible, so we can display it in the new chooser
* src/gpodder/gpodder.py: Improved the OPML channel importer and
added the ability to directly load another OPML URL into the
importer; make the OPML URL reading threaded, so we have a non-
blocking GUI; only ask for new episodes once (after all OPML channels
have been added)
* data/gpodder.glade: Re-designed the OPML import dialog and moved
around the "Import OPML from web" menu item
Wed, 11 Jul 2007 12:59:53 +0200 <thp@perli.net>
* src/gpodder/libgpodder.py: New configuration defaults for new
installations: Use environment for proxy, download new episodes

View File

@ -41,7 +41,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
<widget class="GtkImage" id="image2305">
<widget class="GtkImage" id="image2502">
<property name="visible">True</property>
<property name="stock">gtk-cdrom</property>
<property name="icon_size">1</property>
@ -64,7 +64,7 @@
<accelerator key="R" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2306">
<widget class="GtkImage" id="image2503">
<property name="visible">True</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">1</property>
@ -86,7 +86,7 @@
<accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2307">
<widget class="GtkImage" id="image2504">
<property name="visible">True</property>
<property name="stock">gtk-about</property>
<property name="icon_size">1</property>
@ -113,7 +113,7 @@
<signal name="activate" handler="on_itemAddChannel_activate" last_modification_time="Sat, 29 Oct 2005 11:33:59 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2308">
<widget class="GtkImage" id="image2505">
<property name="visible">True</property>
<property name="stock">gtk-add</property>
<property name="icon_size">1</property>
@ -134,7 +134,7 @@
<signal name="activate" handler="on_itemEditChannel_activate" last_modification_time="Sat, 29 Oct 2005 11:34:38 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2309">
<widget class="GtkImage" id="image2506">
<property name="visible">True</property>
<property name="stock">gtk-edit</property>
<property name="icon_size">1</property>
@ -155,7 +155,7 @@
<signal name="activate" handler="on_itemRemoveChannel_activate" last_modification_time="Sat, 29 Oct 2005 11:35:16 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2310">
<widget class="GtkImage" id="image2507">
<property name="visible">True</property>
<property name="stock">gtk-remove</property>
<property name="icon_size">1</property>
@ -168,6 +168,33 @@
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator10">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="itemImportChannels">
<property name="visible">True</property>
<property name="label" translatable="yes">_Import channels from web</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_itemImportChannels_activate" last_modification_time="Tue, 13 Jun 2006 19:39:42 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2508">
<property name="visible">True</property>
<property name="stock">gtk-redo</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator7">
<property name="visible">True</property>
@ -181,7 +208,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
<widget class="GtkImage" id="image2311">
<widget class="GtkImage" id="image2509">
<property name="visible">True</property>
<property name="stock">gtk-connect</property>
<property name="icon_size">1</property>
@ -204,7 +231,7 @@
<accelerator key="S" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2312">
<widget class="GtkImage" id="image2510">
<property name="visible">True</property>
<property name="stock">gtk-refresh</property>
<property name="icon_size">1</property>
@ -225,7 +252,7 @@
<signal name="activate" handler="on_cleanup_ipod_activate" last_modification_time="Wed, 05 Apr 2006 22:14:51 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2313">
<widget class="GtkImage" id="image2511">
<property name="visible">True</property>
<property name="stock">gtk-delete</property>
<property name="icon_size">1</property>
@ -249,7 +276,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
<widget class="GtkImage" id="image2314">
<widget class="GtkImage" id="image2512">
<property name="visible">True</property>
<property name="stock">gtk-justify-left</property>
<property name="icon_size">1</property>
@ -271,7 +298,7 @@
<signal name="activate" handler="on_itemExportChannels_activate" last_modification_time="Sat, 29 Oct 2005 11:37:45 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2315">
<widget class="GtkImage" id="image2513">
<property name="visible">True</property>
<property name="stock">gtk-save-as</property>
<property name="icon_size">1</property>
@ -283,27 +310,6 @@
</child>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="itemImportChannels">
<property name="visible">True</property>
<property name="label" translatable="yes">_Import from web</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_itemImportChannels_activate" last_modification_time="Tue, 13 Jun 2006 19:39:42 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2316">
<property name="visible">True</property>
<property name="stock">gtk-redo</property>
<property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
@ -324,7 +330,7 @@
<accelerator key="P" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2317">
<widget class="GtkImage" id="image2514">
<property name="visible">True</property>
<property name="stock">gtk-preferences</property>
<property name="icon_size">1</property>
@ -352,7 +358,7 @@
<accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2318">
<widget class="GtkImage" id="image2515">
<property name="visible">True</property>
<property name="stock">gtk-quit</property>
<property name="icon_size">1</property>
@ -376,7 +382,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
<widget class="GtkImage" id="image2319">
<widget class="GtkImage" id="image2516">
<property name="visible">True</property>
<property name="stock">gtk-justify-left</property>
<property name="icon_size">1</property>
@ -399,7 +405,7 @@
<accelerator key="N" modifiers="GDK_CONTROL_MASK | GDK_MOD1_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2320">
<widget class="GtkImage" id="image2517">
<property name="visible">True</property>
<property name="stock">gtk-about</property>
<property name="icon_size">1</property>
@ -420,7 +426,7 @@
<signal name="activate" handler="on_btnSelectAllAvailable_clicked" last_modification_time="Fri, 08 Dec 2006 23:50:54 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2321">
<widget class="GtkImage" id="image2518">
<property name="visible">True</property>
<property name="stock">gtk-sort-ascending</property>
<property name="icon_size">1</property>
@ -441,7 +447,7 @@
<signal name="activate" handler="on_btnDownload_clicked" last_modification_time="Fri, 08 Dec 2006 23:50:54 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2322">
<widget class="GtkImage" id="image2519">
<property name="visible">True</property>
<property name="stock">gtk-goto-bottom</property>
<property name="icon_size">1</property>
@ -469,7 +475,7 @@
<accelerator key="Delete" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2323">
<widget class="GtkImage" id="image2520">
<property name="visible">True</property>
<property name="stock">gtk-clear</property>
<property name="icon_size">1</property>
@ -491,7 +497,7 @@
<accelerator key="Delete" modifiers="0" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2324">
<widget class="GtkImage" id="image2521">
<property name="visible">True</property>
<property name="stock">gtk-delete</property>
<property name="icon_size">1</property>
@ -519,7 +525,7 @@
<accelerator key="Return" modifiers="GDK_SHIFT_MASK" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="image2325">
<widget class="GtkImage" id="image2522">
<property name="visible">True</property>
<property name="stock">gtk-media-play</property>
<property name="icon_size">1</property>
@ -546,7 +552,7 @@
<signal name="activate" handler="on_btnTransfer_clicked" last_modification_time="Sat, 17 Mar 2007 12:59:55 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2407">
<widget class="GtkImage" id="image2523">
<property name="visible">True</property>
<property name="stock">gtk-network</property>
<property name="icon_size">1</property>
@ -570,7 +576,7 @@
<property name="use_underline">True</property>
<child internal-child="image">
<widget class="GtkImage" id="image2326">
<widget class="GtkImage" id="image2524">
<property name="visible">True</property>
<property name="stock">gtk-help</property>
<property name="icon_size">1</property>
@ -592,7 +598,7 @@
<signal name="activate" handler="on_homepage_activate" last_modification_time="Mon, 04 Dec 2006 12:08:55 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2327">
<widget class="GtkImage" id="image2525">
<property name="visible">True</property>
<property name="stock">gtk-home</property>
<property name="icon_size">1</property>
@ -619,7 +625,7 @@
<signal name="activate" handler="on_wishlist_activate" last_modification_time="Mon, 04 Dec 2006 12:06:32 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2328">
<widget class="GtkImage" id="image2526">
<property name="visible">True</property>
<property name="stock">gtk-edit</property>
<property name="icon_size">1</property>
@ -640,7 +646,7 @@
<signal name="activate" handler="on_mailinglist_activate" last_modification_time="Mon, 04 Dec 2006 12:12:24 GMT"/>
<child internal-child="image">
<widget class="GtkImage" id="image2329">
<widget class="GtkImage" id="image2527">
<property name="visible">True</property>
<property name="stock">gtk-find</property>
<property name="icon_size">1</property>
@ -4628,7 +4634,7 @@ Filesystem-based MP3 player</property>
<widget class="GtkWindow" id="gPodderOpmlLister">
<property name="visible">True</property>
<property name="title" translatable="yes">Select channels to subscribe to</property>
<property name="title" translatable="yes">Import channels from web</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
<property name="modal">False</property>
@ -4652,6 +4658,142 @@ Filesystem-based MP3 player</property>
<property name="homogeneous">False</property>
<property name="spacing">5</property>
<child>
<widget class="GtkHBox" id="hbox25">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">5</property>
<child>
<widget class="GtkLabel" id="label92">
<property name="visible">True</property>
<property name="label" translatable="yes">OPML:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entryURL">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">●</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="btnDownloadOpml">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_btnDownloadOpml_clicked" last_modification_time="Wed, 11 Jul 2007 14:53:46 GMT"/>
<child>
<widget class="GtkAlignment" id="alignment15">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">0</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkHBox" id="hbox26">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image2426">
<property name="visible">True</property>
<property name="stock">gtk-goto-bottom</property>
<property name="icon_size">4</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label91">
<property name="visible">True</property>
<property name="label" translatable="yes">Download</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow5">
<property name="visible">True</property>
@ -4692,7 +4834,7 @@ Filesystem-based MP3 player</property>
<widget class="GtkButton" id="btnOK">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-ok</property>
<property name="label">gtk-add</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
@ -4707,14 +4849,35 @@ Filesystem-based MP3 player</property>
</child>
<child>
<placeholder/>
<widget class="GtkLabel" id="labelStatus">
<property name="visible">True</property>
<property name="label"></property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="btnCancel">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>

View File

@ -399,7 +399,7 @@ class Gpodder(SimpleGladeApp):
return True
def add_new_channel( self, result = None):
def add_new_channel( self, result = None, ask_download_new = True):
gl = gPodderLib()
result = gl.sanitize_feed_url( result)
if result:
@ -424,7 +424,8 @@ class Gpodder(SimpleGladeApp):
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)
if ask_download_new:
self.on_btnDownloadNewer_clicked( None)
else:
if result:
title = _('URL scheme not supported')
@ -822,7 +823,7 @@ class Gpodder(SimpleGladeApp):
#-- 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)
Gpodderopmllister( gpodderwindow = self.gPodder).get_channels_from_url( gPodderLib().opml_url, lambda url: self.add_new_channel(url,False), lambda: self.on_itemDownloadAllNew_activate( self.gPodder))
#-- Gpodder.on_itemImportChannels_activate }
#-- Gpodder.on_btnTransfer_clicked {
@ -1707,14 +1708,15 @@ class Gpodderopmllister(SimpleGladeApp):
# initiate channels list
self.channels = []
self.callback_for_channel = None
self.callback_finished = None
togglecell = gtk.CellRendererToggle()
togglecell.set_property( 'activatable', True)
togglecell.connect( 'toggled', self.callback_edited)
togglecolumn = gtk.TreeViewColumn( _("Subscribe"), togglecell, active=0)
togglecolumn = gtk.TreeViewColumn( '', togglecell, active=0)
titlecell = gtk.CellRendererText()
titlecolumn = gtk.TreeViewColumn( _("Channel name"), titlecell, text=1)
titlecolumn = gtk.TreeViewColumn( _('Channel'), titlecell, markup=1)
for itemcolumn in ( togglecolumn, titlecolumn ):
self.treeviewChannelChooser.append_column( itemcolumn)
@ -1724,23 +1726,39 @@ class Gpodderopmllister(SimpleGladeApp):
# 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:
model[path][0] = not model[path][0]
if model[path][0]:
self.channels.append( url)
else:
self.channels.remove( url)
log( 'Edited: %s', url)
def get_channels_from_url( self, url, callback):
self.btnOK.set_sensitive( bool(len(self.channels)))
def thread_func( self):
reader = opmlReader()
reader.parseXML( url)
self.treeviewChannelChooser.set_model( reader.get_model())
self.callback_for_channel = callback
reader.parseXML( self.entryURL.get_text())
gobject.idle_add( self.treeviewChannelChooser.set_model, reader.get_model())
gobject.idle_add( self.labelStatus.set_label, '')
gobject.idle_add( self.btnDownloadOpml.set_sensitive, True)
gobject.idle_add( self.entryURL.set_sensitive, True)
gobject.idle_add( self.treeviewChannelChooser.set_sensitive, True)
self.channels = []
def get_channels_from_url( self, url, callback_for_channel = None, callback_finished = None):
if callback_for_channel:
self.callback_for_channel = callback_for_channel
if callback_finished:
self.callback_finished = callback_finished
self.labelStatus.set_label( _('Downloading, please wait...'))
self.entryURL.set_text( url)
self.btnDownloadOpml.set_sensitive( False)
self.entryURL.set_sensitive( False)
self.btnOK.set_sensitive( False)
self.treeviewChannelChooser.set_sensitive( False)
Thread( target = self.thread_func).start()
#-- Gpodderopmllister custom methods }
#-- Gpodderopmllister.on_gPodderOpmlLister_destroy {
@ -1748,13 +1766,22 @@ class Gpodderopmllister(SimpleGladeApp):
pass
#-- Gpodderopmllister.on_gPodderOpmlLister_destroy }
#-- Gpodderopmllister.on_btnDownloadOpml_clicked {
def on_btnDownloadOpml_clicked(self, widget, *args):
self.get_channels_from_url( self.entryURL.get_text())
#-- Gpodderopmllister.on_btnDownloadOpml_clicked }
#-- 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)
if self.callback_for_channel:
self.callback_for_channel( url)
if self.callback_finished:
self.callback_finished()
#-- Gpodderopmllister.on_btnOK_clicked }
#-- Gpodderopmllister.on_btnCancel_clicked {

View File

@ -395,6 +395,11 @@ class Gpodderopmllister(SimpleGladeApp):
print "on_gPodderOpmlLister_destroy called with self.%s" % widget.get_name()
#-- Gpodderopmllister.on_gPodderOpmlLister_destroy }
#-- Gpodderopmllister.on_btnDownloadOpml_clicked {
def on_btnDownloadOpml_clicked(self, widget, *args):
print "on_btnDownloadOpml_clicked called with self.%s" % widget.get_name()
#-- Gpodderopmllister.on_btnDownloadOpml_clicked }
#-- Gpodderopmllister.on_btnOK_clicked {
def on_btnOK_clicked(self, widget, *args):
print "on_btnOK_clicked called with self.%s" % widget.get_name()

View File

@ -88,7 +88,7 @@ globalLock = threading.RLock()
g_podder_lib = None
# default url to use for opml directory on the web
default_opml_directory = 'http://share.opml.org/opml/topPodcasts.opml'
default_opml_directory = 'http://gpodder.berlios.de/directory.opml'
def getLock():
globalLock.acquire()
@ -353,6 +353,8 @@ class gPodderLibClass( object):
ftp = self.get_from_parser( parser, 'ftp_proxy')
app = self.get_from_parser( parser, 'player', 'gnome-open')
opml_url = self.get_from_parser( parser, 'opml_url', default_opml_directory)
if opml_url == 'http://share.opml.org/opml/topPodcasts.opml':
opml_url = 'http://gpodder.berlios.de/directory.opml'
self.proxy_use_environment = self.get_boolean_from_parser( parser, 'proxy_use_env', True)
self.ipod_mount = self.get_from_parser( parser, 'ipod_mount', '/media/ipod')
self.update_on_startup = self.get_boolean_from_parser(parser, 'update_on_startup', default=False)

View File

@ -35,6 +35,7 @@ from liblogger import log
from xml.sax.saxutils import DefaultHandler
from xml.sax.handler import ErrorHandler
from xml.sax import make_parser
from xml.sax import saxutils
from string import strip
from urllib import unquote_plus
@ -65,7 +66,7 @@ class opmlReader( DefaultHandler, ErrorHandler):
for channel in self.channels:
new_iter = new_model.append()
new_model.set( new_iter, 0, False)
new_model.set( new_iter, 1, channel.title)
new_model.set( new_iter, 1, '<b>%s</b>\n<span size="small">%s</span>' % ( saxutils.escape( channel.title), saxutils.escape( channel.description), ))
new_model.set( new_iter, 2, channel.xmlurl)
return new_model
@ -97,9 +98,13 @@ class opmlReader( DefaultHandler, ErrorHandler):
if title == '':
title = 'Unknown (%s)' % ( xmlurl )
description = attrs.get( 'text', xmlurl)
if description == title:
description = xmlurl
# otype = 'link' to support odeo.com feeds
if name == 'outline' and (otype == 'rss' or otype == 'link') and xmlurl != '':
self.channels.append( opmlChannel( xmlurl, title))
self.channels.append( opmlChannel( xmlurl, title, description))
def endElement( self, name):
if name == 'title':

View File

@ -606,9 +606,10 @@ class podcastItem(object):
class opmlChannel(object):
def __init__( self, xmlurl, title = 'Unknown OPML Channel'):
def __init__( self, xmlurl, title = 'Unknown OPML Channel', description = ''):
self.title = title
self.xmlurl = xmlurl
self.description = description
class DownloadHistory( ListType):