""" CategorySelector.py

Module for selecting categories
"""
__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. """

import locale
import pygtk
pygtk.require('2.0')
import gobject
import gtk
import FeedCategoryList
import MVP
import Event

class Column:
    TITLE=0
    CATEGORY=1

class CategoryView(MVP.WidgetView):
    """
    Widget: gtk.ComboBox
    Model: ListStore
    """
    def _initialize(self):
        self._popup = None
        self._widget.set_wrap_width(1)
        title = gtk.CellRendererText()
        self._widget.pack_start(title,False)
        self._widget.add_attribute(title,'text',Column.TITLE)
        self._widget.connect('changed', self._selection_changed)
        return

    def _model_set(self):
        self._widget.set_model(self._model)
        return

    def _selection_changed(self, combo, data=None):
        self._presenter.selection_changed(combo, data)

    def set_active(self, index): self._widget.set_active(index)
    def get_active(self): return self._widget.get_active()

    def get_active_iter(self): return self._widget.get_active_iter()
    def set_active_iter(self, it): self._widget.set_active_iter(it)

class CategoryPresenter(MVP.BasicPresenter):
    def _initialize(self):
        self.initialize_slots(Event.CategorySelectionChangedSignal)
        self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
        self.model.set_sort_func(Column.TITLE, self._sort_func)
        self.model.set_sort_column_id(Column.TITLE, gtk.SORT_ASCENDING)
        self._init_signals()
        return

    def _sort_func(self, model, a, b):
        """
        From the gtk.TreeSortable.set_sort_func doc:

        The comparison callback should return -1 if the iter1 row should come before
        the iter2 row, 0 if the rows are equal, or 1 if the iter1 row should come
        after the iter2 row.
        """
        fclist = FeedCategoryList.get_instance()
        retval = 0
        cat_a = model.get_value(a, Column.CATEGORY)
        cat_b = model.get_value(b, Column.CATEGORY)

        if cat_a in fclist.pseudo_categories:
            retval = -1
        elif cat_b in fclist.pseudo_categories:
            retval = 1
        elif cat_a is not None and cat_b is not None:
            retval = locale.strcoll(cat_a.title, cat_b.title)
        elif cat_a is not None: retval = -1
        elif cat_b is not None: retval = 1
        return retval

    def _init_signals(self):
        fclist = FeedCategoryList.get_instance()
        fclist.signal_connect(Event.FeedCategoryListLoadedSignal,
                              self._display_categories)
        fclist.signal_connect(Event.FeedCategoryAddedSignal,
                              self._category_added_cb)
        fclist.signal_connect(Event.FeedCategoryRemovedSignal,
                              self._category_removed_cb)
        fclist.signal_connect(Event.FeedCategoryChangedSignal,
                              self._category_changed_cb)
        return

    def _get_selected_category(self):
        category = None
        if len(self._model):
            active = self._view.get_active()
            category = self._model[active][Column.CATEGORY]
        return category

    def _category_added_cb(self, signal):
        newcat = signal.category
        treeiter = self._model.append()
        self._model.set(treeiter,
                        Column.TITLE, newcat.title,
                        Column.CATEGORY, newcat)
        return

    def _category_removed_cb(self, signal):
        self._model.foreach(self._foreach_remove_cat,
                            signal.category)
        self._update_selection()
        return

    def _foreach_remove_cat(self, model, path, iter, category):
        cat = model[path][Column.CATEGORY]
        if cat is category:
            model.remove(iter)
            return True
        return False

    def _category_changed_cb(self, signal):
        self._model.foreach(self._foreach_category_changed,
                            signal.sender)
        self._update_selection()
        return

    def _foreach_category_changed(self, model, path, iter, category):
        cat = model[path][Column.CATEGORY]
        if cat is category:
            model.set(iter,
                      Column.TITLE, category.title,
                      Column.CATEGORY, category)
            return True
        return False

    def _display_categories(self, signal):
        fclist = signal.sender
        self._model.clear()
        for category in fclist.pseudo_categories:
            it = self._model.append()
            self._model.set(it,
                            Column.TITLE, category.title,
                            Column.CATEGORY, category)
        for category in fclist.user_categories:
            it = self._model.append()
            self._model.set(it,
                            Column.TITLE, category.title,
                            Column.CATEGORY, category)
        self._update_selection()
        return

    def _update_selection(self):
        active = self._view.get_active()
        if active < 0:
            self._view.set_active_iter(self._model.get_iter_first())
        return

    def selection_changed(self, combo, data=None):
        model = combo.get_model()
        newitem = model[combo.get_active()][1]
        self.emit_signal(Event.CategorySelectionChangedSignal(self,newitem))
        return

    def category_selected(self, category):
        self._model.foreach(self._foreach_category_selected,
                            category)
        self._update_selection()

    def _foreach_category_selected(self, model, path, iter, category):
        cat = model[path][Column.CATEGORY]
        if cat is category:
            self._view.set_active_iter(iter)
            return True
        return False
