Intermediate work commit.
[straw/fork.git] / straw / feedproperties.py
blobfe618da9e182b8fd2fa51b7ad9840c157291a5a8
1 """ FeedPropertiesDialog.py
3 Provides a module for handling the properties of a feed
4 """
5 __copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc."
6 __license__ = """
7 Straw is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 2 of the License, or (at your option) any later
10 version.
12 Straw is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License along with
17 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 Place - Suite 330, Boston, MA 02111-1307, USA. """
21 import os, os.path
22 import gettext
23 from error import log, logparam, logtb
24 from xml.sax import saxutils
25 import gtk
26 from gtk.glade import XML
27 import gobject
28 import time
30 import Config
31 import SummaryParser
32 import MVP
34 import straw
35 from straw import helpers
37 class FeedPropertyView(MVP.GladeView):
39 COLUMN_NAME = 0
40 COLUMN_MEMBER = 1
41 COLUMN_OBJECT = 2
43 def _initialize(self):
44 self._feed = None
45 self._defaults = {'title':'','url':'','username':'','password':''}
46 self._window = self._widget.get_widget('feed_properties')
47 self._title = self._widget.get_widget('properties_title_entry')
48 self._location = self._widget.get_widget('properties_location_entry')
49 self._username = self._widget.get_widget('properties_username_entry')
50 self._password = self._widget.get_widget('properties_password_entry')
52 self._next_refresh_label = self._widget.get_widget('properties_next_refresh_label')
53 self._previous_refresh_label = self._widget.get_widget('properties_previous_refresh_label')
55 self._restore_button = self._widget.get_widget('properties_reset_button')
56 self._refresh_spin = self._widget.get_widget('properties_refresh_spin')
57 self._articles_spin = self._widget.get_widget('properties_articles_spin')
58 self._refresh_default_check = self._widget.get_widget('properties_keep_refresh_default')
59 self._articles_default_check = self._widget.get_widget('properties_keep_articles_default')
61 self._categories_treeview = self._widget.get_widget('feed_categories_treeview')
63 self._feed_info_description = self._widget.get_widget('feed_info_description')
64 self._feed_info_copyright = self._widget.get_widget('feed_info_copyright')
65 self._feed_info_link_box = self._widget.get_widget('feed_info_link_box')
67 model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN,
68 gobject.TYPE_PYOBJECT)
69 self._categories_treeview.set_model(model)
70 self._categories_treeview.set_rules_hint(True)
72 r = gtk.CellRendererToggle()
73 r.connect('toggled', self.member_toggled)
74 column = gtk.TreeViewColumn(_('Member'), r, active=self.COLUMN_MEMBER)
75 self._categories_treeview.append_column(column)
77 r = gtk.CellRendererText()
78 column = gtk.TreeViewColumn(_('Name'), r, text=self.COLUMN_NAME)
79 self._categories_treeview.append_column(column)
81 def set_feed(self, feed):
82 self._feed = feed.obj
84 def member_toggled(self, cell, path):
85 model = self._categories_treeview.get_model()
86 category = model[path][self.COLUMN_OBJECT]
87 if self._feed in category.feeds:
88 category.remove_feed(self._feed)
89 model[path][self.COLUMN_MEMBER] = False
90 else:
91 category.append_feed(self._feed, False)
92 model[path][self.COLUMN_MEMBER] = True
94 def show(self):
95 self._initializing_window = True
96 self.display_properties()
97 self._window.present()
98 self._initializing_window = False
100 def hide(self, *args):
101 self._presenter.activate_deleter()
102 self._window.hide()
103 self._window.destroy()
105 def _on_feed_properties_delete_event(self, *args):
106 self.hide()
107 return True
109 def _on_properties_close_button_clicked(self, *args):
110 self.hide()
111 return
113 def display_properties(self):
114 """self._defaults['title'] = self._feed.title
115 loc, un, pw = "", "", ""#self._feed.access_info
116 self._defaults['url'] = loc
117 self._defaults['username'] = un
118 self._defaults['password'] = pw
119 self._defaults['frequency'] = self._feed.poll_frequency
120 self._defaults['stored'] = self._feed.number_of_items_stored
122 self._window.set_title(_("%s Properties") % self._feed.title)
123 self._title.set_text(self._feed.title)
124 self._location.set_text(self._feed.access_info[0])
126 config = Config.get_instance()
127 if self._feed.poll_frequency == feeds.Feed.DEFAULT:
128 freq = config.poll_frequency
129 fdefault = True
130 self._refresh_keep = True
131 else:
132 freq = self._feed.poll_frequency
133 fdefault = False
134 self._refresh_keep = False
135 self._refresh_spin.set_value(float(freq / 60))
136 self._refresh_spin.set_sensitive(not fdefault)
137 self._refresh_default_check.set_active(fdefault)
138 if self._feed.number_of_items_stored == feeds.Feed.DEFAULT:
139 nitems = config.number_of_items_stored
140 nidefault = True
141 self._articles_keep = True
142 else:
143 nitems = self._feed.number_of_items_stored
144 nidefault = False
145 self._articles_keep = False
146 self._articles_spin.set_value(float(nitems))
147 self._articles_spin.set_sensitive(not nidefault)
148 self._articles_default_check.set_active(nidefault)
150 if un:
151 self._username.set_text(un)
152 if pw:
153 self._password.set_text(pw)
155 model = self._categories_treeview.get_model()
156 model.clear()
157 fclist = feeds.category_list
158 for c in fclist.user_categories:
159 iter = model.append()
160 model.set(iter,
161 self.COLUMN_NAME, c.title,
162 self.COLUMN_MEMBER, self._feed in c.feeds,
163 self.COLUMN_OBJECT, c)
165 self._previous_refresh_label.set_text(
166 helpers.format_date(time.gmtime(self._feed.last_poll)))
167 next = self._feed.next_refresh
168 if next:
169 self._next_refresh_label.set_text(
170 helpers.format_date(time.gmtime(next)))
171 self._next_refresh_label.show()
172 else:
173 self._next_refresh_label.hide()"""
175 self._display_feed_information(self._feed)
176 self._restore_button.set_sensitive(False)
178 def _display_feed_information(self, feed):
179 #title = helpers.convert_entities(feed.channel_title)
180 #if len(title) == 0:
181 # title = feed.title or feed.channel_link
182 #title = title.strip()
184 #link = feed.channel_link.strip()
185 link = None
186 if not link: link = feed.location
187 print "link = %s" % link
189 if link:
190 link_button = gtk.LinkButton(link, link)
191 self._feed_info_link_box.pack_end(link_button)
192 gtk.link_button_set_uri_hook(self._load_uri, link)
193 self._feed_info_link_box.show_all()
195 description = helpers.convert_entities(feed.channel_description.strip())
196 if description and description != title:
197 description = read_text(description, len(description))
198 self._feed_info_description.set_text(helpers.convert_entities(description))
199 self._feed_info_description.show()
200 else:
201 self._feed_info_description.hide()
203 copyright = helpers.convert_entities(feed.channel_copyright)
204 if copyright:
205 self._feed_info_copyright.set_text(copyright)
206 self._feed_info_copyright.show()
207 else:
208 self._feed_info_copyright.hide()
210 def _load_uri(self, widget, event, data):
211 helpers.url_show(data)
213 def restore_defaults(self):
214 # FIXME: add frequency and number of items and the default flags
215 self._feed.title = self._defaults['title']
216 self._feed.access_info = (
217 self._defaults['url'], self._defaults['username'], self._defaults['password'])
218 self._title.set_text(self._feed.title)
219 self._location.set_text(self._feed.location)
220 self._username.set_text(self._defaults.get('username',''))
221 self._password.set_text(self._defaults.get('password',''))
222 self._refresh_default_check.set_active(self._refresh_keep)
223 if not self._refresh_keep:
224 self._refresh_spin.set_value(float(self._refresh_default))
225 self._articles_default_check.set_active(self._articles_keep)
226 if not self._articles_keep:
227 self._articles_spin.set_value(float(self._articles_default))
228 self._restore_button.set_sensitive(False)
230 def _on_properties_title_entry_insert_text(self, *args):
231 if self._initializing_window:
232 return
233 self._restore_button.set_sensitive(True)
235 def _on_properties_title_entry_delete_text(self, *args):
236 if self._initializing_window:
237 return
238 self._restore_button.set_sensitive(True)
240 def _on_properties_title_entry_focus_out_event(self, widget, *args):
241 self._feed.title = widget.get_text().strip()
243 def _on_properties_location_entry_insert_text(self, *args):
244 if self._initializing_window:
245 return
246 self._restore_button.set_sensitive(True)
248 def _on_properties_location_entry_delete_text(self, *args):
249 if self._initializing_window:
250 return
251 self._restore_button.set_sensitive(True)
253 def _on_properties_location_entry_focus_out_event(self, widget, *args):
254 loc, username, pw = self._feed.access_info
255 self._feed.access_info = (widget.get_text().strip(), username, pw)
257 def _on_properties_username_entry_insert_text(self, *args):
258 if self._initializing_window:
259 return
260 self._restore_button.set_sensitive(True)
262 def _on_properties_username_entry_delete_text(self, *args):
263 if self._initializing_window:
264 return
265 self._restore_button.set_sensitive(False)
267 def _on_properties_username_entry_focus_out_event(self, widget, *args):
268 self._presenter.set_username(widget.get_text().strip())
270 def _on_properties_password_entry_insert_text(self, *args):
271 if self._initializing_window:
272 return
273 self._restore_button.set_sensitive(True)
275 def _on_properties_password_entry_delete_text(self, *args):
276 if self._initializing_window:
277 return
278 self._restore_button.set_sensitive(False)
280 def _on_properties_password_entry_focus_out_event(self, widget, *args):
281 self._presenter.set_password(widget.get_text().strip())
283 def _on_properties_reset_button_clicked(self, *args):
284 self.restore_defaults()
286 def _on_properties_refresh_spin_focus_out_event(self, widget, *args):
287 widget.update()
288 value = widget.get_value_as_int()
289 self._presenter.set_poll_frequency(value)
291 def _on_properties_articles_spin_focus_out_event(self, widget, *args):
292 widget.update()
293 value = widget.get_value_as_int()
294 self._presenter.set_items_stored(value)
296 def _on_properties_articles_spin_value_changed(self, widget, *args):
297 if self._initializing_window:
298 return
299 self._restore_button.set_sensitive(True)
301 def _on_properties_refresh_spin_value_changed(self, widget, *args):
302 if self._initializing_window:
303 return
304 self._restore_button.set_sensitive(True)
306 def _on_properties_keep_refresh_default_toggled(self, widget, *args):
307 if self._initializing_window:
308 return
309 isactive = widget.get_active()
310 if isactive:
311 self._presenter.set_poll_frequency(feeds.Feed.DEFAULT)
312 self._refresh_spin.set_value(float(Config.get_instance().poll_frequency / 60))
313 else:
314 self._presenter.set_poll_frequency(self._refresh_spin.get_value_as_int() * 60)
316 self._refresh_spin.set_sensitive(not isactive)
317 self._restore_button.set_sensitive(True)
319 def _on_properties_keep_articles_default_toggled(self, widget, *args):
320 if self._initializing_window:
321 return
322 isactive = widget.get_active()
323 if isactive:
324 self._presenter.set_items_stored(feeds.Feed.DEFAULT)
325 self._articles_spin.set_value(float(Config.get_instance().number_of_items_stored))
326 else:
327 self._presenter.set_items_stored(self._articles_spin.get_value_as_int())
328 self._articles_spin.set_sensitive(not isactive)
329 self._restore_button.set_sensitive(True)
332 class FeedPropertyPresenter(MVP.BasicPresenter):
334 TIME_INTERVAL = 60
336 def _initialize(self):
337 self._feed = None
338 self._deleter = None
340 def set_deleter(self, deleter):
341 self._deleter = deleter
343 def activate_deleter(self):
344 if self._deleter:
345 self._deleter()
347 def set_feed(self, feed):
348 self._feed = feed
349 self._view.set_feed(self._feed)
351 def set_username(self, username):
352 loc, uname, pw = self._feed.access_info
353 self._feed.access_info = (loc, username, pw)
355 def set_password(self, password):
356 loc, uname, pw = self._feed.access_info
357 self._feed.access_info = (loc, uname, password)
359 def set_poll_frequency(self, pf):
360 if pf != self._feed.poll_frequency:
361 self._feed.poll_frequency = pf * FeedPropertyPresenter.TIME_INTERVAL
363 def set_items_stored(self, nitems):
364 if nitems != self._feed.number_of_items_stored:
365 self._feed.number_of_items_stored = nitems
367 dialogs = {}
368 def feed_properties_show(feed):
369 global dialogs
370 class _dialogdeleter:
371 def __init__(self, feed, hash):
372 self.feed = feed
373 self.hash = hash
375 def __call__(self):
376 del self.hash[feed]
378 dialog = dialogs.get(feed, None)
380 if not dialog:
381 gladefile = XML(os.path.join(straw.STRAW_DATA_DIR, "feed-properties.glade"))
382 #idget_tree = gladefile.get_widget_tree('feed_properties')
383 dialog = FeedPropertyPresenter(view=FeedPropertyView(gladefile))
384 dialog.set_feed(feed)
385 dialog.set_deleter(_dialogdeleter(feed, dialogs))
386 dialogs[feed] = dialog
388 dialog.view.show()
390 def read_text(fragment, chars):
391 """Read chars cdata characters from html fragment fragment"""
392 parser = SummaryParser.TitleImgParser()
393 parser.feed(fragment)
394 text = parser.get_text(chars)
395 parser.close()
396 return text