pre gobject: 3-pane view, callgraph, feed navigation
[straw.git] / src / lib / FeedList.py
blobe80551eabe0cc1922e1d81c2a99afcead335f6b8
1 """ FeedList.py
3 Provides a container for handling the feeds
4 """
5 __copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc."
6 __license__ = """GNU General Public License
8 This program is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place - Suite 330, Boston, MA 02111-1307, USA. """
22 import Event
23 import Feed
24 import Config
25 import locale
26 import utils
28 class FeedList(list, Event.SignalEmitter):
29 def __init__(self, init_seq = []):
30 Event.SignalEmitter.__init__(self)
31 self.initialize_slots(Event.FeedsChangedSignal,
32 Event.FeedDeletedSignal,
33 Event.FeedCreatedSignal,
34 Event.AllItemsReadSignal,
35 Event.ItemReadSignal,
36 Event.ItemsAddedSignal,
37 Event.FeedPolledSignal,
38 Event.FeedStatusChangedSignal,
39 Event.FeedErrorStatusChangedSignal,
40 Event.FeedsImportedSignal,
41 Event.FeedDetailChangedSignal)
42 self._loading = False
44 def load_data(self):
45 def _load(feeds, parent):
46 for df in feeds:
47 if isinstance(df, list):
48 #fc = straw.FeedCategory()
49 #fc.undump(df[0])
50 #self.append(parent, fc)
51 _load(df[1:], parent)
52 else:
53 f = Feed.Feed.create_empty_feed()
54 f.undump(df)
55 self.append(parent, f)
56 self._loading = True
57 feeds = Config.get_instance().feeds
58 if feeds is not None:
59 _load(feeds, None)
60 self._loading = False
61 self.emit_signal(Event.FeedsChangedSignal(self))
63 def _forward_signal(self, signal):
64 self.emit_signal(signal)
66 def connect_signals(self, ob):
67 #ob.signal_connect(Event.FeedsChangedSignal,
68 # self.feeds_changed, True)
69 ob.signal_connect(Event.FeedDetailChangedSignal,
70 self.feed_detail_changed, True)
72 # these signals are forwarded so that listeners who just want to
73 # listen for a specific event regardless of what feed it came from can
74 # just connect to this feedlist instead of connecting to the
75 # individual feeds.
76 ob.signal_connect(Event.AllItemsReadSignal, self._forward_signal)
77 ob.signal_connect(Event.ItemReadSignal, self._forward_signal)
78 ob.signal_connect(Event.ItemsAddedSignal, self._forward_signal)
79 ob.signal_connect(Event.FeedPolledSignal, self._forward_signal)
80 ob.signal_connect(Event.FeedStatusChangedSignal, self._forward_signal)
81 ob.signal_connect(Event.FeedErrorStatusChangedSignal, self._forward_signal)
83 def __setitem__(self, key, value):
84 list.__setitem__(self, key, value)
85 self.connect_signals(value)
86 self.save_feeds_and_notify(True)
88 def extend(self, parent, values, from_sub=False):
89 list.extend(self, values)
90 for f in values:
91 f.parent = parent
92 self.connect_signals(f)
93 self.save_feeds_and_notify(
94 True, signal=Event.FeedsImportedSignal(self, values, parent, from_sub))
96 def append(self, parent, value):
97 list.append(self, value)
98 value.parent = parent
99 self.connect_signals(value)
100 self.save_feeds_and_notify(
101 True, signal=Event.FeedCreatedSignal(self, value, parent))
103 def insert(self, index, parent, value):
104 list.insert(self, index, value)
105 value.parent = parent
106 self.connect_signals(value)
107 self.save_feeds_and_notify(
108 True, signal=Event.FeedCreatedSignal(self, value, parent, index))
110 def index(self, feed):
111 return list.index(self, feed)
113 def reorder(self, move, delta):
114 k = self[:]
115 move = list(move)
116 move.sort()
117 if delta > 0:
118 move.reverse()
119 if move[0] == 0 and delta < 0 or move[-1] == (len(self) - 1) and delta > 0:
120 return
121 for m in move:
122 k[m + delta], k[m] = k[m], k[m + delta]
123 for i in range(len(k)):
124 list.__setitem__(self, i, k[i])
125 self.save_feeds_and_notify(True)
127 def __delitem__(self, value):
128 feed = self[value]
129 list.__delitem__(self, value)
130 feed.delete_all_items()
131 self.save_feeds_and_notify(
132 True, signal=Event.FeedDeletedSignal(self, feed))
134 def save_feeds_and_notify(self, notify, signal=None):
135 if not self._loading:
136 config = Config.get_instance()
137 config.feeds = [f.dump() for f in self]
138 if notify:
139 if not signal:
140 signal = Event.FeedsChangedSignal(self)
141 self.emit_signal(signal)
142 return
144 def feeds_changed(self, signal, notify):
145 self.save_feeds_and_notify(notify, signal)
147 def feed_detail_changed(self, signal, notify):
148 self.save_feeds_and_notify(notify, signal)
150 def _sort_dsu(self, seq):
151 aux_list = [(x.title, x) for x in seq]
152 aux_list.sort(lambda a,b:locale.strcoll(a[0],b[0]))
153 return [x[1] for x in aux_list]
155 def sort(self, indices = None):
156 if not indices or len(indices) == 1:
157 self[:] = self._sort_dsu(self)
158 else:
159 items = self._sort_dsu(indices)
160 for i,x in enumerate(items):
161 list.__setitem__(self, indices[i], items[i])
162 self.save_feeds_and_notify(True)
164 def __hash__(self):
165 h = 0
166 for item in self:
167 h ^= hash(item)
168 return h
170 def get_feed_with_id(self, id):
171 for f in self.flatten_list():
172 if f.id == id:
173 return f
174 return None
176 def flatten_list(self, ob=None):
177 if ob is None:
178 ob = self
179 l = []
180 for o in ob:
181 if isinstance(o, list):
182 l = l + self.flatten_list(o)
183 else:
184 l.append(o)
185 return l
187 feedlist_instance = None
189 def get_instance():
190 global feedlist_instance
191 if feedlist_instance is None:
192 feedlist_instance = FeedList()
193 return feedlist_instance