Improve the Maemo 5 / Fremantle user experience
[gpodder.git] / src / gpodder / gtkui / frmntl / podcastdirectory.py
blobd38748df46dd717cfd1fd2a3e1c289bb749b4bbd
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2009 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 import os
21 import gtk
22 import pango
23 import urllib
24 import threading
25 import hildon
27 import gpodder
29 _ = gpodder.gettext
31 from gpodder import util
32 from gpodder import opml
33 from gpodder import youtube
35 from gpodder.gtkui.frmntl.opml import OpmlListModel
37 from gpodder.gtkui.interface.common import BuilderWidget
39 from gpodder.gtkui.frmntl.widgets import EditToolbarDeluxe
41 from gpodder.gtkui.draw import draw_text_box_centered
43 class gPodderPodcastDirectory(BuilderWidget):
44 def new(self):
45 self._is_updating = False
47 if hasattr(self, 'custom_title'):
48 self.main_window.set_title(self.custom_title)
50 if not hasattr(self, 'add_urls_callback'):
51 self.add_urls_callback = None
53 titlecell = gtk.CellRendererText()
54 titlecell.set_property('ellipsize', pango.ELLIPSIZE_END)
55 titlecolumn = gtk.TreeViewColumn('', titlecell, markup=OpmlListModel.C_DESCRIPTION_MARKUP)
56 self.treeview.append_column(titlecolumn)
58 selection = self.treeview.get_selection()
59 selection.connect('changed', self.on_selection_changed)
60 selection.set_mode(gtk.SELECTION_MULTIPLE)
61 selection.unselect_all()
62 self.app_menu = hildon.AppMenu()
63 for action in (self.action_load_toplist, \
64 self.action_load_opml, \
65 self.action_load_search, \
66 self.action_load_youtube, \
67 self.action_select_all, \
68 self.action_select_none):
69 button = gtk.Button()
70 action.connect_proxy(button)
71 self.app_menu.append(button)
72 self.main_window.set_app_menu(self.app_menu)
74 self.edit_toolbar = EditToolbarDeluxe(self.main_window.get_title(), \
75 _('Subscribe'))
76 self.edit_toolbar.connect('arrow-clicked', \
77 self.on_close_button_clicked)
78 self.edit_toolbar.connect('button-clicked', \
79 self.on_subscribe_button_clicked)
80 self.edit_toolbar.show_all()
82 # This method needs a EditToolbarDeluxe to work
83 self.edit_toolbar.set_button_sensitive(False)
85 self.main_window.set_edit_toolbar(self.edit_toolbar)
86 self.main_window.fullscreen()
87 self.main_window.show()
89 self.app_menu.popup(self.main_window)
91 def on_treeview_expose_event(self, treeview, event):
92 if event.window == treeview.get_bin_window():
93 model = treeview.get_model()
94 if (model is not None and model.get_iter_first() is not None):
95 return False
97 ctx = event.window.cairo_create()
98 ctx.rectangle(event.area.x, event.area.y,
99 event.area.width, event.area.height)
100 ctx.clip()
101 x, y, width, height, depth = event.window.get_geometry()
103 if self._is_updating:
104 text = _('Downloading podcast list, please wait...')
105 else:
106 text = _('No podcasts')
108 from gpodder.gtkui.frmntl import style
109 font_desc = style.get_font_desc('LargeSystemFont')
110 draw_text_box_centered(ctx, treeview, width, height, text, font_desc)
112 return False
115 def on_selection_changed(self, selection):
116 self.set_subscribe_button_sensitive()
118 def get_selected_channels(self):
119 selection = self.treeview.get_selection()
120 model, paths = selection.get_selected_rows()
121 return [model.get_value(model.get_iter(path), \
122 OpmlListModel.C_URL) for path in paths]
124 def on_load_opml_button_clicked(self, widget):
125 url = self.show_text_edit_dialog(_('Load OPML file from the web'), _('URL:'))
126 if url is not None:
127 self.download_opml_file(url)
129 def on_load_toplist_button_clicked(self, widget):
130 self.download_opml_file(self._config.toplist_url)
132 def on_load_search_button_clicked(self, widget):
133 search_term = self.show_text_edit_dialog(_('Search podcast.de'), \
134 _('Search for:'))
135 if search_term is not None:
136 url = 'http://api.podcast.de/opml/podcasts/suche/%s' % \
137 (urllib.quote(search_term),)
138 self.download_opml_file(url)
140 def on_load_youtube_button_clicked(self, widget):
141 search_term = self.show_text_edit_dialog(\
142 _('Search YouTube user channels'), \
143 _('Search for:'))
144 if search_term is not None:
145 self.download_opml_file(search_term, use_youtube=True)
147 def download_opml_file(self, url, use_youtube=False):
148 selection = self.treeview.get_selection()
149 selection.unselect_all()
150 self.treeview.set_model(None)
151 self._is_updating = True
152 self.treeview.queue_draw()
153 hildon.hildon_gtk_window_set_progress_indicator(self.main_window, True)
155 def download_thread_func():
156 if use_youtube:
157 importer = youtube.find_youtube_channels(url)
158 else:
159 importer = opml.Importer(url)
161 if importer.items:
162 model = OpmlListModel(importer)
163 else:
164 model = None
165 def download_thread_finished():
166 self._is_updating = False
167 self.treeview.queue_draw()
168 hildon.hildon_gtk_window_set_progress_indicator(\
169 self.main_window, False)
170 self.action_select_all.set_property('visible', \
171 model is not None)
172 self.action_select_none.set_property('visible', \
173 model is not None)
174 self.treeview.set_model(model)
175 self.set_subscribe_button_sensitive()
177 if model is None:
178 self.show_message(_('No podcasts found. Try another source.'), \
179 important=True)
180 self.app_menu.popup(self.main_window)
182 util.idle_add(download_thread_finished)
184 threading.Thread(target=download_thread_func).start()
186 def on_select_all_button_clicked(self, widget):
187 selection = self.treeview.get_selection()
188 selection.select_all()
190 def on_select_none_button_clicked(self, widget):
191 selection = self.treeview.get_selection()
192 selection.unselect_all()
194 def set_subscribe_button_sensitive(self):
195 selection = self.treeview.get_selection()
196 count = selection.count_selected_rows()
197 title = self.main_window.get_title()
198 if count == 1:
199 title += ' - %s' % (_('1 podcast selected'),)
200 elif count > 1:
201 title += ' - %s' % (_('%d podcasts selected') % count,)
202 self.edit_toolbar.set_label(title)
203 self.edit_toolbar.set_button_sensitive(count > 0)
205 def on_subscribe_button_clicked(self, widget, *args):
206 channel_urls = self.get_selected_channels()
207 self.main_window.destroy()
209 # add channels that have been selected
210 if self.add_urls_callback is not None:
211 self.add_urls_callback(channel_urls)
213 def on_close_button_clicked(self, widget):
214 self.main_window.destroy()