1 from JobManager
import Job
2 from error
import debug
3 from gobject
import GObject
, SIGNAL_RUN_FIRST
4 from model
import Feed
, Item
, Category
5 from storage
import DAO
, Storage
17 fm
.init_storage(_storage_path
)
19 def setup(storage_path
= None):
21 _storage_path
= storage_path
23 def import_opml(path
, category
):
25 fm
.import_opml(path
, category
)
27 def export_opml(root_id
, filename
):
29 fm
.export_opml(root_id
, filename
)
33 return fm
.lookup_feed(id)
35 def lookup_category(ctg_id
):
37 return fm
.lookup_category(ctg_id
)
43 def update_all_feeds(observers
):
45 return fm
.update_all_feeds(observers
)
47 def is_update_all_running():
49 return fm
.update_all_id
!= None
51 def stop_update_all():
53 return fm
.stop_update_all()
55 def update_nodes(nodes
, observers
= {}):
57 return fm
.update_nodes(nodes
, observers
)
59 def save_category(category
):
61 return fm
.save_category(category
)
65 result
= fm
.save_feed(feed
)
68 def save_all(save_list
):
70 fm
.save_all(save_list
)
76 def get_children_feeds(node_id
):
77 node
= lookup_category(node_id
)
82 return [_node
for _node
in node
.all_children() if _node
.type == "F"]
84 def categories(root_id
= 1):
87 if not nodes
.has_key(root_id
):
92 for node
in nodes
[root_id
].children
:
94 for child
in categories(node
.id):
97 def move_node(node
, target_path
):
99 fm
.move_node(node
, target_path
)
101 def delete_nodes(node_ids
):
103 fm
.delete_nodes(node_ids
)
105 class FeedManager(GObject
):
107 "item-added" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, (gobject
.TYPE_PYOBJECT
,)),
108 "feed-added" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, (gobject
.TYPE_PYOBJECT
,)),
109 "category-added" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, (gobject
.TYPE_PYOBJECT
,)),
110 "update-all-done" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, ())
114 GObject
.__init
__(self
)
117 self
.update_all_id
= None
119 def emit(self
, *args
):
120 gobject
.idle_add(gobject
.GObject
.emit
, self
, *args
)
122 def init_storage(self
, path
):
123 self
.storage
= Storage(path
)
124 self
.dao
= DAO(self
.storage
)
125 self
.nodes
= self
.dao
.get_nodes()
127 self
._prepare
_model
()
129 def _prepare_model(self
):
130 for node
in self
.nodes
.values():
131 self
._setup
_node
_signals
(node
)
133 if node
.parent_id
!= None:
134 node
.parent
= self
.nodes
[node
.parent_id
]
135 node
.parent
.append_child(node
)
139 if isinstance(node
, Feed
):
140 node
.status
= straw
.FS_IDLE
142 def _setup_node_signals(self
, node
):
143 node
.connect("parent-changed", self
.on_parent_changed
)
144 node
.connect("norder-changed", self
.on_norder_changed
)
146 def import_opml(self
, path
, category
):
147 job
= Job("opml-parse")
148 job
.data
= ("file://" + path
, category
)
149 job
.observers
= [ { "task-done": [ self
._on
_opml
_imported
] } ]
151 JobManager
.start(job
)
153 def _on_opml_imported(self
, handler
, task_result
):
154 save_list
= task_result
.result
158 self
.save_all(save_list
)
161 def export_opml(self
, root_id
, filename
):
162 if not self
.nodes
.has_key(root_id
):
165 opml
.export(self
.nodes
[root_id
], filename
)
167 def _model_add_node(self
, node
):
168 self
.nodes
[node
.parent_id
].add_child(node
)
170 def move_node(self
, node
, target_path
):
171 debug("fm:move_node %d to %s" % (node
.id, str(target_path
)))
172 new_parent
= self
.nodes
[1].get_by_path(target_path
[:-1])
175 new_parent
= self
.nodes
[1]
178 node
.move(new_parent
, target_path
[-1:][0])
181 def delete_nodes(self
, node_ids
):
189 def delete_node(self
, id):
190 if not self
.nodes
.has_key(id):
193 node
= self
.nodes
[id]
195 children
= list(node
.children
)
198 for child_node
in children
:
199 self
.delete_node(child_node
.id)
201 node
.parent
.remove_child(node
)
205 debug("deleting F %s" % id)
206 self
.dao
.delete_feed(id)
207 elif node
.type == "C":
208 debug("deleting C %s" % id)
209 self
.dao
.delete_category(id)
211 def save_all(self
, save_list
):
212 for item
in save_list
:
213 if isinstance(item
, Feed
):
214 item
.status
= straw
.FS_IDLE
218 item
.parent_id
= item
.parent
.id
221 item
.parent
= self
.nodes
[1]
226 item
.parent_id
= item
.parent
.id
229 item
.parent
= self
.nodes
[1]
231 self
.save_category(item
)
233 def lookup_feed(self
, id):
234 return self
.nodes
[id]
236 def lookup_category(self
, id):
237 return self
.nodes
[id]
239 def save_feed(self
, feed
):
240 if not feed
.parent_id
:
243 category
= self
.lookup_category(feed
.parent_id
)
249 result
= self
.dao
.save(feed
)
251 result
= self
.dao
.save(feed
)
252 self
._model
_add
_node
(feed
)
255 self
.nodes
[feed
.id] = feed
257 self
._setup
_node
_signals
(feed
)
258 self
.emit("feed-added", feed
)
262 def update_all_feeds(self
, observers
):
263 feeds
= [node
for node
in self
.nodes
.values() if node
.type == "F"]
265 self
.update_all_id
= FeedUpdater
.update(feeds
, [{
266 "job-done": [ self
._on
_update
_all
_done
],
267 "update-started": [ self
._on
_update
_feed
_start
],
268 "update-done": [ self
._on
_update
_feed
_done
]
271 def update_nodes(self
, nodes
, observers
):
278 feeds
.extend([child_node
for child_node
in node
.all_children() if child_node
.type == "F"])
280 FeedUpdater
.update(feeds
, [{
281 "update-started": [ self
._on
_update
_feed
_start
],
282 "update-done": [ self
._on
_update
_feed
_done
]
285 def stop_update_all(self
):
286 FeedUpdater
.stop(self
.update_all_id
)
288 def _on_update_all_done(self
, handler
, data
):
289 self
.update_all_id
= None
290 self
.emit("update-all-done")
292 def _on_update_feed_start(self
, handler
, feed
):
293 feed
.props
.status
= straw
.FS_UPDATING
295 def _on_update_feed_done(self
, handler
, update_result
):
296 feed
= update_result
.feed
298 if update_result
.error
:
299 feed
.props
.status
= straw
.FS_ERROR
302 feed
.props
.status
= straw
.FS_IDLE
306 # Some metadata could change between the updates.
309 for item
in feed
.items
:
310 item
.feed_id
= feed
.id
312 if not ItemManager
.feed_item_exists(item
):
314 feed
.props
.unread_count
+= 1
315 self
.emit("item-added", item
)
319 def save_category(self
, category
):
320 debug("saving category %s with parent %s" % (category
.name
, str(category
.parent_id
)))
322 if category
.parent
and not category
.parent_id
:
323 category
.parent_id
= category
.parent
.id
327 self
.dao
.save(category
)
328 self
._model
_add
_node
(category
)
329 self
.dao
.save(category
)
333 self
.nodes
[category
.id] = category
335 self
._setup
_node
_signals
(category
)
336 self
.emit("category-added", category
)
338 def on_parent_changed(self
, obj
, old_parent
):
339 debug("parent changed, saving %d" % (obj
.id))
342 def on_norder_changed(self
, obj
, old_norder
):
343 debug("norder changed, saving %d" % (obj
.id))
351 _instance
= FeedManager()