Updated Arabic Translation by Djihed Afifi.
[straw.git] / src / lib / FeedPropertiesDialog.py
blob9dc7ad2dfdbb496832063260421d5f0311bbf3ec
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 from error import log, logparam, logtb
22 from xml.sax import saxutils
23 import pygtk
24 pygtk.require('2.0')
25 import gtk
26 import gtk.glade
27 import gobject
28 import gnome
29 import time
30 import utils
31 import Feed
32 import Config
33 import FeedCategoryList
34 import SummaryParser
35 import gettext
37 class FeedPropertiesDialog(object):
38 COLUMN_NAME = 0
39 COLUMN_MEMBER = 1
40 COLUMN_OBJECT = 2
42 def __init__(self, parent, feed, deleter):
43 gladef = utils.find_glade_file()
44 xml = gtk.glade.XML(gladef, 'feed_properties_dialog', gettext.textdomain())
45 self._window = xml.get_widget('feed_properties_dialog')
46 self._window.set_transient_for(parent)
47 self._title = xml.get_widget('properties_title_entry')
48 self._location = xml.get_widget('properties_location_entry')
49 self._username = xml.get_widget('properties_username_entry')
50 self._password = xml.get_widget('properties_password_entry')
51 self._username_title = xml.get_widget('properties_username_label')
52 self._password_title = xml.get_widget('properties_password_label')
53 self._restore_button = xml.get_widget('properties_reset_button')
54 self._refresh_spin = xml.get_widget('properties_refresh_spin')
55 self._articles_spin = xml.get_widget('properties_articles_spin')
56 self._refresh_default_check = xml.get_widget(
57 'properties_keep_refresh_default')
58 self._articles_default_check = xml.get_widget(
59 'properties_keep_articles_default')
60 self._next_refresh_label = xml.get_widget(
61 'properties_next_refresh_label')
62 self._previous_refresh_label = xml.get_widget(
63 'properties_previous_refresh_label')
64 self._categories_treeview = xml.get_widget('feed_categories_treeview')
65 self._feed_info_href_container = xml.get_widget(
66 'feed_info_href_container')
67 self._feed_info_description = xml.get_widget('feed_info_description')
68 self._feed_info_copyright = xml.get_widget('feed_info_copyright')
70 self._feed_info_href = gnome.ui.HRef(url='', text='')
71 self._feed_info_href_container.pack_start(
72 self._feed_info_href, expand=False, fill=False)
74 self._title_default = ''
75 self._url_default = ''
76 self._un_default = ''
77 self._pw_default = ''
79 self._size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
80 self._size_group.add_widget(xml.get_widget('properties_title_label'))
81 self._size_group.add_widget(xml.get_widget('properties_location_label'))
82 self._size_group.add_widget(xml.get_widget('properties_username_label'))
83 self._size_group.add_widget(xml.get_widget('properties_password_label'))
85 model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN,
86 gobject.TYPE_PYOBJECT)
87 self._categories_treeview.set_model(model)
88 self._categories_treeview.set_rules_hint(True)
90 r = gtk.CellRendererToggle()
91 r.connect('toggled', self.member_toggled)
92 column = gtk.TreeViewColumn(_('Member'), r, active=self.COLUMN_MEMBER)
93 self._categories_treeview.append_column(column)
95 r = gtk.CellRendererText()
96 column = gtk.TreeViewColumn(_('Name'), r, text=self.COLUMN_NAME)
97 self._categories_treeview.append_column(column)
99 nameFuncMap = {}
100 for key in dir(self.__class__):
101 if key[:3] == 'on_':
102 nameFuncMap[key] = getattr(self, key)
103 xml.signal_autoconnect(nameFuncMap)
105 self._initializing_window = False
106 self._feed = feed
107 self.deleter = deleter
109 def get_state(self):
110 return self._window.window.get_state()
112 def show(self):
113 self._initializing_window = True
114 self.display_properties()
115 self._window.present()
116 self._initializing_window = False
118 def hide(self, *args):
119 self.deleter()
120 self._window.hide()
121 self._window.destroy()
123 def on_feed_properties_dialog_delete_event(self, *args):
124 self.hide()
125 return True
127 def on_feed_properties_close_button_clicked(self, *args):
128 self.hide()
129 return
131 def member_toggled(self, cell, path):
132 model = self._categories_treeview.get_model()
133 category = model[path][self.COLUMN_OBJECT]
134 if self._feed in category.feeds:
135 category.remove_feed(self._feed)
136 model[path][self.COLUMN_MEMBER] = False
137 else:
138 category.append_feed(self._feed, False)
139 model[path][self.COLUMN_MEMBER] = True
141 def display_properties(self):
142 self._title_default = self._feed.title
143 loc, un, pw = self._feed.access_info
144 self._url_default = loc
145 self._un_default = un
146 self._pw_default = pw
147 self._refresh_default = self._feed.poll_frequency
148 self._articles_default = self._feed.number_of_items_stored
149 self._window.set_title(_("%s Properties") % self._feed.title)
150 self._title.set_text(self._feed.title)
151 self._location.set_text(self._feed.access_info[0])
152 config = Config.get_instance()
153 if self._feed.poll_frequency == Feed.Feed.DEFAULT:
154 freq = config.poll_frequency
155 fdefault = True
156 self._refresh_keep = True
157 else:
158 freq = self._feed.poll_frequency
159 fdefault = False
160 self._refresh_keep = False
161 self._refresh_spin.set_value(float(freq / 60))
162 self._refresh_spin.set_sensitive(not fdefault)
163 self._refresh_default_check.set_active(fdefault)
164 if self._feed.number_of_items_stored == Feed.Feed.DEFAULT:
165 nitems = config.number_of_items_stored
166 nidefault = True
167 self._articles_keep = True
168 else:
169 nitems = self._feed.number_of_items_stored
170 nidefault = False
171 self._articles_keep = False
172 self._articles_spin.set_value(float(nitems))
173 self._articles_spin.set_sensitive(not nidefault)
174 self._articles_default_check.set_active(nidefault)
176 if un:
177 self._username.set_text(un)
178 self._password.set_text(pw)
180 model = self._categories_treeview.get_model()
181 model.clear()
182 fclist = FeedCategoryList.get_instance()
183 for c in fclist.user_categories:
184 iter = model.append()
185 model.set(iter,
186 self.COLUMN_NAME, c.title,
187 self.COLUMN_MEMBER, self._feed in c.feeds,
188 self.COLUMN_OBJECT, c)
190 self._previous_refresh_label.set_text(
191 utils.format_date(time.gmtime(self._feed.last_poll)))
192 next = self._feed.next_refresh
193 if next is not None:
194 self._next_refresh_label.set_text(
195 utils.format_date(time.gmtime(next)))
196 self._next_refresh_label.show()
197 else:
198 self._next_refresh_label.hide()
200 self._display_feed_information(self._feed)
201 self._restore_button.set_sensitive(False)
203 def _display_feed_information(self, feed):
204 title = utils.convert_entities(feed.channel_title)
205 if len(title) == 0:
206 title = feed.title
207 if len(title) == 0:
208 title = feed.channel_link
209 title = title.strip()
211 link = feed.channel_link.strip()
212 if len(link) < 1: link = feed.location
214 if len(title) > 0:
215 self._feed_info_href.set_text(saxutils.escape(title))
216 self._feed_info_href.set_url(link)
217 self._feed_info_href.set_sensitive(len(link) > 0)
218 self._feed_info_href.show()
219 else:
220 self._feed_info_href.hide()
222 description = utils.convert_entities(feed.channel_description.strip())
223 size = len(description)
224 if size and description != title:
225 description = read_text(description, size)
226 self._feed_info_description.set_text(utils.convert_entities(description))
227 self._feed_info_description.show()
228 else:
229 self._feed_info_description.hide()
231 copyright = utils.convert_entities(feed.channel_copyright)
232 self._feed_info_copyright.set_text(copyright)
233 if len(copyright):
234 self._feed_info_copyright.show()
235 else:
236 self._feed_info_copyright.hide()
238 def restore_defaults(self):
239 # FIXME: add frequency and number of items and the default flags
240 self._feed.title = self._title_default
241 self._feed.access_info = (
242 self._url_default, self._un_default, self._pw_default)
243 self._title.set_text(self._title_default)
244 self._location.set_text(self._url_default)
245 if self._un_default is not None:
246 self._username.set_text(self._un_default)
247 else:
248 self._username.set_text("")
249 if self._pw_default is not None:
250 self._password.set_text(self._pw_default)
251 else:
252 self._password.set_text("")
253 self._refresh_default_check.set_active(self._refresh_keep)
254 if not self._refresh_keep:
255 self._refresh_spin.set_value(float(self._refresh_default))
256 self._articles_default_check.set_active(self._articles_keep)
257 if not self._articles_keep:
258 self._articles_spin.set_value(float(self._articles_default))
259 self._restore_button.set_sensitive(False)
261 def on_properties_title_entry_insert_text(self, *args):
262 if self._initializing_window:
263 return
264 self._restore_button.set_sensitive(True)
266 def on_properties_title_entry_delete_text(self, *args):
267 if self._initializing_window:
268 return
269 self._restore_button.set_sensitive(True)
271 def on_properties_title_entry_focus_out_event(self, widget, *args):
272 self._feed.title = widget.get_text().strip()
274 def on_properties_location_entry_insert_text(self, *args):
275 if self._initializing_window:
276 return
277 self._restore_button.set_sensitive(True)
279 def on_properties_location_entry_delete_text(self, *args):
280 if self._initializing_window:
281 return
282 self._restore_button.set_sensitive(True)
284 def on_properties_location_entry_focus_out_event(self, widget, *args):
285 loc, username, pw = self._feed.access_info
286 self._feed.access_info = (widget.get_text().strip(), username, pw)
288 def on_properties_username_entry_insert_text(self, *args):
289 if self._initializing_window:
290 return
291 self._restore_button.set_sensitive(True)
293 def on_properties_username_entry_delete_text(self, *args):
294 if self._initializing_window:
295 return
296 self._restore_button.set_sensitive(False)
298 def on_properties_username_entry_focus_out_event(self, widget, *args):
299 loc, username, pw = self._feed.access_info
300 text = widget.get_text().strip()
301 if text == "":
302 text = None
303 self._feed.access_info = (loc, text, pw)
305 def on_properties_password_entry_insert_text(self, *args):
306 if self._initializing_window:
307 return
308 self._restore_button.set_sensitive(True)
310 def on_properties_password_entry_delete_text(self, *args):
311 if self._initializing_window:
312 return
313 self._restore_button.set_sensitive(False)
315 def on_properties_password_entry_focus_out_event(self, widget, *args):
316 loc, username, pw = self._feed.access_info
317 text = widget.get_text().strip()
318 if text == "":
319 text = None
320 self._feed.access_info = (loc, username, text)
322 def on_properties_reset_button_clicked(self, *args):
323 self.restore_defaults()
325 def on_properties_refresh_spin_focus_out_event(self, widget, *args):
326 widget.update()
327 value = widget.get_value_as_int()
328 if value != self._feed.poll_frequency:
329 self._feed.poll_frequency = value * 60
331 def on_properties_articles_spin_focus_out_event(self, widget, *args):
332 widget.update()
333 value = widget.get_value_as_int()
334 if value != self._feed.number_of_items_stored:
335 self._feed.number_of_items_stored = value
337 def on_properties_articles_spin_value_changed(self, widget, *args):
338 if self._initializing_window:
339 return
340 self._restore_button.set_sensitive(True)
342 def on_properties_refresh_spin_value_changed(self, widget, *args):
343 if self._initializing_window:
344 return
345 self._restore_button.set_sensitive(True)
347 def on_properties_keep_refresh_default_toggled(self, widget, *args):
348 if self._initializing_window:
349 return
350 if widget.get_active():
351 self._feed.poll_frequency = Feed.Feed.DEFAULT
352 self._refresh_spin.set_sensitive(False)
353 self._refresh_spin.set_value(float(Config.get_instance().poll_frequency / 60))
354 else:
355 self._feed.poll_frequency = self._refresh_spin.get_value_as_int() * 60
356 self._refresh_spin.set_sensitive(True)
357 self._restore_button.set_sensitive(True)
359 def on_properties_keep_articles_default_toggled(self, widget, *args):
360 if self._initializing_window:
361 return
362 if widget.get_active():
363 self._feed.number_of_items_stored = Feed.Feed.DEFAULT
364 self._articles_spin.set_value(float(Config.get_instance().number_of_items_stored))
365 self._articles_spin.set_sensitive(False)
366 else:
367 self._feed.number_of_items_stored = self._articles_spin.get_value_as_int()
368 self._articles_spin.set_sensitive(True)
369 self._restore_button.set_sensitive(True)
371 dialogs = {}
372 def show_feed_properties(cls, parent, feed):
373 class _dialogdeleter:
374 def __init__(self, feed, hash):
375 self.feed = feed
376 self.hash = hash
378 def __call__(self):
379 del self.hash[feed]
381 dialog = cls.dialogs.get(feed, None)
382 if not dialog:
383 dialog = cls(parent,feed,_dialogdeleter(feed, cls.dialogs))
384 cls.dialogs[feed] = dialog
385 dialog.show()
386 return
387 show_feed_properties = classmethod(show_feed_properties)
389 def read_text(fragment, chars):
390 """Read chars cdata characters from html fragment fragment"""
391 parser = SummaryParser.TitleImgParser()
392 parser.feed(fragment)
393 text = parser.get_text(chars)
394 parser.close()
395 return text