""" FeedPropertiesDialog.py Provides a module for handling the properties of a feed """ __copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc." __license__ = """ Straw 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. Straw 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ from error import log, logparam, logtb from xml.sax import saxutils import pygtk pygtk.require('2.0') import gtk import gtk.glade import gobject import gnome import time import utils import Feed import Config import FeedCategoryList import SummaryParser import gettext class FeedPropertiesDialog(object): COLUMN_NAME = 0 COLUMN_MEMBER = 1 COLUMN_OBJECT = 2 def __init__(self, parent, feed, deleter): gladef = utils.find_glade_file() xml = gtk.glade.XML(gladef, 'feed_properties_dialog', gettext.textdomain()) self._window = xml.get_widget('feed_properties_dialog') self._window.set_transient_for(parent) self._title = xml.get_widget('properties_title_entry') self._location = xml.get_widget('properties_location_entry') self._username = xml.get_widget('properties_username_entry') self._password = xml.get_widget('properties_password_entry') self._username_title = xml.get_widget('properties_username_label') self._password_title = xml.get_widget('properties_password_label') self._restore_button = xml.get_widget('properties_reset_button') self._refresh_spin = xml.get_widget('properties_refresh_spin') self._articles_spin = xml.get_widget('properties_articles_spin') self._refresh_default_check = xml.get_widget( 'properties_keep_refresh_default') self._articles_default_check = xml.get_widget( 'properties_keep_articles_default') self._next_refresh_label = xml.get_widget( 'properties_next_refresh_label') self._previous_refresh_label = xml.get_widget( 'properties_previous_refresh_label') self._categories_treeview = xml.get_widget('feed_categories_treeview') self._feed_info_href_container = xml.get_widget( 'feed_info_href_container') self._feed_info_description = xml.get_widget('feed_info_description') self._feed_info_copyright = xml.get_widget('feed_info_copyright') self._feed_info_href = gnome.ui.HRef(url='', text='') self._feed_info_href_container.pack_start( self._feed_info_href, expand=False, fill=False) self._title_default = '' self._url_default = '' self._un_default = '' self._pw_default = '' self._size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) self._size_group.add_widget(xml.get_widget('properties_title_label')) self._size_group.add_widget(xml.get_widget('properties_location_label')) self._size_group.add_widget(xml.get_widget('properties_username_label')) self._size_group.add_widget(xml.get_widget('properties_password_label')) model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_PYOBJECT) self._categories_treeview.set_model(model) self._categories_treeview.set_rules_hint(True) r = gtk.CellRendererToggle() r.connect('toggled', self.member_toggled) column = gtk.TreeViewColumn(_('Member'), r, active=self.COLUMN_MEMBER) self._categories_treeview.append_column(column) r = gtk.CellRendererText() column = gtk.TreeViewColumn(_('Name'), r, text=self.COLUMN_NAME) self._categories_treeview.append_column(column) nameFuncMap = {} for key in dir(self.__class__): if key[:3] == 'on_': nameFuncMap[key] = getattr(self, key) xml.signal_autoconnect(nameFuncMap) self._initializing_window = False self._feed = feed self.deleter = deleter def get_state(self): return self._window.window.get_state() def show(self): self._initializing_window = True self.display_properties() self._window.present() self._initializing_window = False def hide(self, *args): self.deleter() self._window.hide() self._window.destroy() def on_feed_properties_dialog_delete_event(self, *args): self.hide() return True def on_feed_properties_close_button_clicked(self, *args): self.hide() return def member_toggled(self, cell, path): model = self._categories_treeview.get_model() category = model[path][self.COLUMN_OBJECT] if self._feed in category.feeds: category.remove_feed(self._feed) model[path][self.COLUMN_MEMBER] = False else: category.append_feed(self._feed, False) model[path][self.COLUMN_MEMBER] = True def display_properties(self): self._title_default = self._feed.title loc, un, pw = self._feed.access_info self._url_default = loc self._un_default = un self._pw_default = pw self._refresh_default = self._feed.poll_frequency self._articles_default = self._feed.number_of_items_stored self._window.set_title(_("%s Properties") % self._feed.title) self._title.set_text(self._feed.title) self._location.set_text(self._feed.access_info[0]) config = Config.get_instance() if self._feed.poll_frequency == Feed.Feed.DEFAULT: freq = config.poll_frequency fdefault = True self._refresh_keep = True else: freq = self._feed.poll_frequency fdefault = False self._refresh_keep = False self._refresh_spin.set_value(float(freq / 60)) self._refresh_spin.set_sensitive(not fdefault) self._refresh_default_check.set_active(fdefault) if self._feed.number_of_items_stored == Feed.Feed.DEFAULT: nitems = config.number_of_items_stored nidefault = True self._articles_keep = True else: nitems = self._feed.number_of_items_stored nidefault = False self._articles_keep = False self._articles_spin.set_value(float(nitems)) self._articles_spin.set_sensitive(not nidefault) self._articles_default_check.set_active(nidefault) if un: self._username.set_text(un) self._password.set_text(pw) model = self._categories_treeview.get_model() model.clear() fclist = FeedCategoryList.get_instance() for c in fclist.user_categories: iter = model.append() model.set(iter, self.COLUMN_NAME, c.title, self.COLUMN_MEMBER, self._feed in c.feeds, self.COLUMN_OBJECT, c) self._previous_refresh_label.set_text( utils.format_date(time.gmtime(self._feed.last_poll))) next = self._feed.next_refresh if next is not None: self._next_refresh_label.set_text( utils.format_date(time.gmtime(next))) self._next_refresh_label.show() else: self._next_refresh_label.hide() self._display_feed_information(self._feed) self._restore_button.set_sensitive(False) def _display_feed_information(self, feed): title = utils.convert_entities(feed.channel_title) if len(title) == 0: title = feed.title if len(title) == 0: title = feed.channel_link title = title.strip() link = feed.channel_link.strip() if len(link) < 1: link = feed.location if len(title) > 0: self._feed_info_href.set_text(saxutils.escape(title)) self._feed_info_href.set_url(link) self._feed_info_href.set_sensitive(len(link) > 0) self._feed_info_href.show() else: self._feed_info_href.hide() description = utils.convert_entities(feed.channel_description.strip()) size = len(description) if size and description != title: description = read_text(description, size) self._feed_info_description.set_text(utils.convert_entities(description)) self._feed_info_description.show() else: self._feed_info_description.hide() copyright = utils.convert_entities(feed.channel_copyright) self._feed_info_copyright.set_text(copyright) if len(copyright): self._feed_info_copyright.show() else: self._feed_info_copyright.hide() def restore_defaults(self): # FIXME: add frequency and number of items and the default flags self._feed.title = self._title_default self._feed.access_info = ( self._url_default, self._un_default, self._pw_default) self._title.set_text(self._title_default) self._location.set_text(self._url_default) if self._un_default is not None: self._username.set_text(self._un_default) else: self._username.set_text("") if self._pw_default is not None: self._password.set_text(self._pw_default) else: self._password.set_text("") self._refresh_default_check.set_active(self._refresh_keep) if not self._refresh_keep: self._refresh_spin.set_value(float(self._refresh_default)) self._articles_default_check.set_active(self._articles_keep) if not self._articles_keep: self._articles_spin.set_value(float(self._articles_default)) self._restore_button.set_sensitive(False) def on_properties_title_entry_insert_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_title_entry_delete_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_title_entry_focus_out_event(self, widget, *args): self._feed.title = widget.get_text().strip() def on_properties_location_entry_insert_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_location_entry_delete_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_location_entry_focus_out_event(self, widget, *args): loc, username, pw = self._feed.access_info self._feed.access_info = (widget.get_text().strip(), username, pw) def on_properties_username_entry_insert_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_username_entry_delete_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(False) def on_properties_username_entry_focus_out_event(self, widget, *args): loc, username, pw = self._feed.access_info text = widget.get_text().strip() if text == "": text = None self._feed.access_info = (loc, text, pw) def on_properties_password_entry_insert_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_password_entry_delete_text(self, *args): if self._initializing_window: return self._restore_button.set_sensitive(False) def on_properties_password_entry_focus_out_event(self, widget, *args): loc, username, pw = self._feed.access_info text = widget.get_text().strip() if text == "": text = None self._feed.access_info = (loc, username, text) def on_properties_reset_button_clicked(self, *args): self.restore_defaults() def on_properties_refresh_spin_focus_out_event(self, widget, *args): widget.update() value = widget.get_value_as_int() if value != self._feed.poll_frequency: self._feed.poll_frequency = value * 60 def on_properties_articles_spin_focus_out_event(self, widget, *args): widget.update() value = widget.get_value_as_int() if value != self._feed.number_of_items_stored: self._feed.number_of_items_stored = value def on_properties_articles_spin_value_changed(self, widget, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_refresh_spin_value_changed(self, widget, *args): if self._initializing_window: return self._restore_button.set_sensitive(True) def on_properties_keep_refresh_default_toggled(self, widget, *args): if self._initializing_window: return if widget.get_active(): self._feed.poll_frequency = Feed.Feed.DEFAULT self._refresh_spin.set_sensitive(False) self._refresh_spin.set_value(float(Config.get_instance().poll_frequency / 60)) else: self._feed.poll_frequency = self._refresh_spin.get_value_as_int() * 60 self._refresh_spin.set_sensitive(True) self._restore_button.set_sensitive(True) def on_properties_keep_articles_default_toggled(self, widget, *args): if self._initializing_window: return if widget.get_active(): self._feed.number_of_items_stored = Feed.Feed.DEFAULT self._articles_spin.set_value(float(Config.get_instance().number_of_items_stored)) self._articles_spin.set_sensitive(False) else: self._feed.number_of_items_stored = self._articles_spin.get_value_as_int() self._articles_spin.set_sensitive(True) self._restore_button.set_sensitive(True) dialogs = {} def show_feed_properties(cls, parent, feed): class _dialogdeleter: def __init__(self, feed, hash): self.feed = feed self.hash = hash def __call__(self): del self.hash[feed] dialog = cls.dialogs.get(feed, None) if not dialog: dialog = cls(parent,feed,_dialogdeleter(feed, cls.dialogs)) cls.dialogs[feed] = dialog dialog.show() return show_feed_properties = classmethod(show_feed_properties) def read_text(fragment, chars): """Read chars cdata characters from html fragment fragment""" parser = SummaryParser.TitleImgParser() parser.feed(fragment) text = parser.get_text(chars) parser.close() return text