1 from JobManager
import Job
2 from gobject
import GObject
, SIGNAL_RUN_FIRST
3 from model
import Feed
, Item
, Category
4 from storage
import DAO
, Storage
14 def import_opml(path
):
20 fm
.init_storage(_storage_path
)
22 def setup(storage_path
= None):
24 _storage_path
= storage_path
26 def lookup_feed(id, ctg_id
):
28 return fm
.lookup_feed(id, ctg_id
)
30 def lookup_category(ctg_id
):
32 return fm
.lookup_category(ctg_id
)
34 def get_feed_items(id):
36 return fm
.get_feed_items(id)
38 def get_category_items(id):
40 return fm
.get_category_items(id)
46 def update_all_feeds(observers
):
48 return fm
.update_all_feeds(observers
)
50 def save_category(title
, pid
= None):
52 return fm
.save_category(title
, parent_id
= pid
)
56 result
= fm
.save_feed(feed
)
61 return fm
.categories
, fm
.model
63 class FeedManager(GObject
):
65 "item-added" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, (gobject
.TYPE_PYOBJECT
,)),
66 "feed-added" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, (gobject
.TYPE_PYOBJECT
,)),
67 "category-added" : (gobject
.SIGNAL_RUN_LAST
, gobject
.TYPE_NONE
, (gobject
.TYPE_PYOBJECT
,)),
71 GObject
.__init
__(self
)
75 def init_storage(self
, path
):
76 self
.storage
= Storage(path
)
77 self
.dao
= DAO(self
.storage
)
79 #self.categories = self.get_categories()
80 self
.nodes
, self
.model
= self
.dao
.get_nodes()
83 #self.feeds = dict([(node.id, node) for node in self.nodes.values() if node.type == "F"])
88 def import_opml(self
, path
):
89 job
= Job("opml-parse")
91 job
.observers
= [ { "job-done": [ self
.import_opml_save
] } ]
92 JobManager
.start_job(job
)
94 def import_opml_save(self
, handler
, opml_data
):
95 categories
= opml_data
97 self
._save
_tree
(opml_data
)
98 #for item in opml_data:
99 # if isinstance(item, Feed):
100 # self.save_feed(item)
102 # self.save_category(item)
104 def _save_tree(self
, level
, parent_id
= 1):
106 if isinstance(item
, Feed
):
109 parent_id
= item
.parent
.id
110 item
.parent_id
= parent_id
115 parent_id
= item
.parent
.id
116 item
.parent_id
= parent_id
117 self
.save_category(item
)
119 def lookup_feed(self
, id):
120 return self
.nodes
[id]
122 def lookup_category(self
, id):
123 return self
.categories
[id]
125 def save_feed(self
, feed
):
126 if not feed
.parent_id
:
129 category
= self
.lookup_category(feed
.parent_id
)
134 result
= self
.dao
.save(feed
)
136 if not self
.feeds
.has_key(feed
.parent_id
):
137 self
.feeds
[feed
.parent_id
] = []
139 feed
.connect("unread-count-changed", category
.on_unread_count_changed
)
141 self
.feeds
[feed
.parent_id
].append(feed
)
142 self
.emit("feed-added", feed
)
146 def update_all_feeds(self
, observers
):
147 feeds
= [node
for key
in self
.model
.keys() for node
in self
.model
[key
] if node
.type == "F"]
149 FeedUpdater
.update_feeds(feeds
, [{
150 "job-done": [ self
.update_all_feeds_done
],
151 "task-start": [ self
._on
_update
_feed
_start
],
152 "task-done": [ self
._on
_update
_feed
_done
]
155 def update_all_feeds_done(self
, handler
, data
):
158 def _on_update_feed_start(self
, handler
, feed
):
159 feed
.props
.status
= straw
.FS_UPDATING
161 def _on_update_feed_done(self
, handler
, data
):
162 feed
= data
.task_info
.data
["feed"]
163 feed
.props
.status
= straw
.FS_IDLE
168 for item
in data
.result
.items
:
169 item
.feed_id
= feed
.id
171 if not self
.feed_item_exists(item
):
173 feed
.props
.unread_count
+= 1
174 self
.emit("item-added", item
)
178 def save_category(self
, category
):
179 self
.dao
.save(category
)
180 category
.connect("unread-count-changed",
181 self
.lookup_category(category
.parent_id
).on_unread_count_changed
)
182 self
.categories
[category
.id] = category
183 self
.emit("category-added", category
)
187 def get_feed_items(self
, id):
188 feed
= self
.lookup_feed(id)
189 feed
.items
= self
.dao
.get(Item
, " WHERE feed_id = %d" % feed
.id)
190 for item
in feed
.items
:
192 item
.connect("is-read-changed", feed
.on_is_read_changed
)
193 item
.connect("is-read-changed", self
.on_item_is_read_changed
)
196 def get_category_items(self
, id):
197 category
= self
.lookup_category(id)
202 def _get_children_feeds(category_id
):
205 if self
.feeds
.has_key(category_id
):
206 feed_ids
= [str(feed
.id) for feed
in self
.feeds
[category_id
]]
208 children_categories
= [ctg_id
for ctg_id
in self
.categories
.keys() if self
.categories
[ctg_id
].parent_id
== category_id
]
210 for ctg_id
in children_categories
:
211 feed_ids
.extend(_get_children_feeds(ctg_id
))
215 in_str
= ", ".join(_get_children_feeds(id))
217 items
= self
.dao
.get(Item
, " WHERE feed_id IN(%s) ORDER BY id" % in_str
)
220 feed
= self
.lookup_feed(item
.feed_id
)
222 item
.connect("is-read-changed", feed
.on_is_read_changed
)
223 item
.connect("is-read-changed", self
.on_item_is_read_changed
)
227 def feed_item_exists(self
, item
):
228 result
= self
.dao
.get(Item
, " WHERE feed_id = ? AND title = ?", (item
.feed_id
, item
.title
,))
229 return len(result
) > 0
231 def on_item_is_read_changed(self
, obj
, is_read
):
234 def _process_model(self
):
235 self
.categories
= dict([(node
.id, node
) for node
in self
.nodes
.values() if node
.type == "C"])
238 for category_id
in self
.categories
.keys():
239 category
= self
.categories
[category_id
]
241 if category
.parent_id
!= None:
242 category
.connect("unread-count-changed",
243 self
.categories
[category
.parent_id
].on_unread_count_changed
)
245 for node
in self
.nodes
.values():
246 if node
.parent_id
!= None:
247 node
.parent
= self
.nodes
[node
.parent_id
]
250 if not self
.feeds
.has_key(node
.parent_id
):
251 self
.feeds
[node
.parent_id
] = []
253 self
.feeds
[node
.parent_id
].append(node
)
254 self
.categories
[node
.parent_id
].props
.unread_count
+= node
.unread_count
256 node
.connect("unread-count-changed", node
.parent
.on_unread_count_changed
)
263 _instance
= FeedManager()