""" FeedList.py Provides a container for handling the feeds """ __copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc." __license__ = """GNU General Public License This program 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. This program 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 Event import Feed import Config import locale import utils class FeedList(list, Event.SignalEmitter): def __init__(self, init_seq = []): Event.SignalEmitter.__init__(self) self.initialize_slots(Event.FeedsChangedSignal, Event.FeedDeletedSignal, Event.FeedCreatedSignal, Event.AllItemsReadSignal, Event.ItemReadSignal, Event.ItemsAddedSignal, Event.FeedPolledSignal, Event.FeedStatusChangedSignal, Event.FeedErrorStatusChangedSignal, Event.FeedsImportedSignal, Event.FeedDetailChangedSignal) self._loading = False def load_data(self): def _load(feeds, parent): for df in feeds: if isinstance(df, list): #fc = straw.FeedCategory() #fc.undump(df[0]) #self.append(parent, fc) _load(df[1:], parent) else: f = Feed.Feed.create_empty_feed() f.undump(df) self.append(parent, f) self._loading = True feeds = Config.get_instance().feeds if feeds is not None: _load(feeds, None) self._loading = False self.emit_signal(Event.FeedsChangedSignal(self)) def _forward_signal(self, signal): self.emit_signal(signal) def connect_signals(self, ob): #ob.signal_connect(Event.FeedsChangedSignal, # self.feeds_changed, True) ob.signal_connect(Event.FeedDetailChangedSignal, self.feed_detail_changed, True) # these signals are forwarded so that listeners who just want to # listen for a specific event regardless of what feed it came from can # just connect to this feedlist instead of connecting to the # individual feeds. ob.signal_connect(Event.AllItemsReadSignal, self._forward_signal) ob.signal_connect(Event.ItemReadSignal, self._forward_signal) ob.signal_connect(Event.ItemsAddedSignal, self._forward_signal) ob.signal_connect(Event.FeedPolledSignal, self._forward_signal) ob.signal_connect(Event.FeedStatusChangedSignal, self._forward_signal) ob.signal_connect(Event.FeedErrorStatusChangedSignal, self._forward_signal) def __setitem__(self, key, value): list.__setitem__(self, key, value) self.connect_signals(value) self.save_feeds_and_notify(True) def extend(self, parent, values, from_sub=False): list.extend(self, values) for f in values: f.parent = parent self.connect_signals(f) self.save_feeds_and_notify( True, signal=Event.FeedsImportedSignal(self, values, parent, from_sub)) def append(self, parent, value): list.append(self, value) value.parent = parent self.connect_signals(value) self.save_feeds_and_notify( True, signal=Event.FeedCreatedSignal(self, value, parent)) def insert(self, index, parent, value): list.insert(self, index, value) value.parent = parent self.connect_signals(value) self.save_feeds_and_notify( True, signal=Event.FeedCreatedSignal(self, value, parent, index)) def index(self, feed): return list.index(self, feed) def reorder(self, move, delta): k = self[:] move = list(move) move.sort() if delta > 0: move.reverse() if move[0] == 0 and delta < 0 or move[-1] == (len(self) - 1) and delta > 0: return for m in move: k[m + delta], k[m] = k[m], k[m + delta] for i in range(len(k)): list.__setitem__(self, i, k[i]) self.save_feeds_and_notify(True) def __delitem__(self, value): feed = self[value] list.__delitem__(self, value) feed.delete_all_items() self.save_feeds_and_notify( True, signal=Event.FeedDeletedSignal(self, feed)) def save_feeds_and_notify(self, notify, signal=None): if not self._loading: config = Config.get_instance() config.feeds = [f.dump() for f in self] if notify: if not signal: signal = Event.FeedsChangedSignal(self) self.emit_signal(signal) return def feeds_changed(self, signal, notify): self.save_feeds_and_notify(notify, signal) def feed_detail_changed(self, signal, notify): self.save_feeds_and_notify(notify, signal) def _sort_dsu(self, seq): aux_list = [(x.title, x) for x in seq] aux_list.sort(lambda a,b:locale.strcoll(a[0],b[0])) return [x[1] for x in aux_list] def sort(self, indices = None): if not indices or len(indices) == 1: self[:] = self._sort_dsu(self) else: items = self._sort_dsu(indices) for i,x in enumerate(items): list.__setitem__(self, indices[i], items[i]) self.save_feeds_and_notify(True) def __hash__(self): h = 0 for item in self: h ^= hash(item) return h def get_feed_with_id(self, id): for f in self.flatten_list(): if f.id == id: return f return None def flatten_list(self, ob=None): if ob is None: ob = self l = [] for o in ob: if isinstance(o, list): l = l + self.flatten_list(o) else: l.append(o) return l feedlist_instance = None def get_instance(): global feedlist_instance if feedlist_instance is None: feedlist_instance = FeedList() return feedlist_instance