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