""" 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
