1 from enigma import eTimer
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
5 from Screens.ChoiceBox import ChoiceBox
7 from Components.Scanner import openList
9 from Components.ActionMap import ActionMap
10 from Components.Label import Label
11 from Components.ScrollLabel import ScrollLabel
12 from Components.Pixmap import Pixmap
14 from RSSList import RSSList
15 from RSSSetup import RSSSetup
17 class RSSBaseView(Screen):
18 """Base Screen for all Screens used in SimpleRSS"""
20 def __init__(self, session, poller):
21 Screen.__init__(self, session)
22 self.rssPoller = poller
23 self.pollDialog = None
25 def errorPolling(self, errmsg = ""):
26 # An error occured while polling
29 "Error while parsing Feed, this usually means there is something wrong with it.",
30 type = MessageBox.TYPE_ERROR,
34 # Don't show "we're updating"-dialog any longer
36 self.pollDialog.close()
37 self.pollDialog = None
39 def singleUpdate(self, feedid, errback = None):
40 # Don't do anything if we have no poller
41 if self.rssPoller is None:
44 # Default errorback to self.errorPolling
45 # If an empty errorback is wanted the Screen needs to provide it
47 errback = self.errorPolling
50 self.rssPoller.singlePoll(feedid, callback=True, errorback=errback)
52 # Open Dialog and save locally
53 self.pollDialog = self.session.open(
55 "Update is being done in Background.\nContents will automatically be updated when it's done.",
56 type = MessageBox.TYPE_INFO,
60 def selectEnclosure(self, enclosures):
62 if enclosures is None:
65 if not openList(self.session, enclosures):
68 "Found no Enclosure we can display.",
69 type = MessageBox.TYPE_INFO,
73 class RSSEntryView(RSSBaseView):
74 """Shows a RSS Item"""
76 <screen position="100,100" size="460,420" title="Simple RSS Reader" >
77 <widget name="info" position="0,0" size="460, 20" halign="right" font="Regular; 18" />
78 <widget name="content" position="0,20" size="460,420" font="Regular; 22" />
81 def __init__(self, session, data, feedTitle="", cur_idx=None, entries=None, nextEntryCB=None, previousEntryCB=None, nextFeedCB=None, previousFeedCB=None):
82 RSSBaseView.__init__(self, session, None)
85 self.feedTitle = feedTitle
86 self.nextEntryCB = nextEntryCB
87 self.previousEntryCB = previousEntryCB
88 self.nextFeedCB = nextFeedCB
89 self.previousFeedCB = previousFeedCB
90 self.cur_idx = cur_idx
91 self.entries = entries
93 if cur_idx is not None and entries is not None:
94 self["info"] = Label("Entry %s/%s" % (cur_idx+1, entries))
96 self["info"] = Label()
99 self["content"] = ScrollLabel("\n\n".join([data[0], data[2], " ".join([str(len(data[3])), "Enclosures"])]))
101 self["content"] = ScrollLabel()
103 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "ColorActions", "DirectionActions" ],
105 "cancel": self.close,
106 "ok": self.selectEnclosure,
107 "yellow": self.selectEnclosure,
111 "left": self.previous,
112 "nextBouquet": self.nextFeed,
113 "prevBouquet": self.previousFeed,
116 self.onLayoutFinish.append(self.setConditionalTitle)
118 def setConditionalTitle(self):
119 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
122 self["content"].pageUp()
125 self["content"].pageDown()
128 if self.nextEntryCB is not None:
129 (self.data, self.cur_idx, self.entries) = self.nextEntryCB()
133 if self.previousEntryCB is not None:
134 (self.data, self.cur_idx, self.entries) = self.previousEntryCB()
139 if self.nextFeedCB is not None:
140 result = self.nextFeedCB()
141 self.feedTitle = result[0]
142 self.entries = len(result[1])
145 self.data = result[1][0]
149 self.setConditionalTitle()
152 def previousFeed(self):
154 if self.previousFeedCB is not None:
155 result = self.previousFeedCB()
156 self.feedTitle = result[0]
157 self.entries = len(result[1])
160 self.data = result[1][0]
164 self.setConditionalTitle()
167 def setContent(self):
168 if self.cur_idx is not None and self.entries is not None:
169 self["info"].setText("Entry %s/%s" % (self.cur_idx+1, self.entries))
171 self["info"].setText("")
172 if self.data is not None:
173 self["content"].setText("\n\n".join([self.data[0], self.data[2], " ".join([str(len(self.data[3])), "Enclosures"])]))
175 self["content"].setText("No such Item.")
177 def selectEnclosure(self):
178 if self.data is not None:
179 RSSBaseView.selectEnclosure(self, self.data[3])
181 class RSSFeedView(RSSBaseView):
182 """Shows a RSS-Feed"""
184 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
185 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
186 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
187 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
190 def __init__(self, session, data, feedTitle = "", newItems=False, nextFeedCB=None, previousFeedCB=None, rssPoller=None, id = None):
191 RSSBaseView.__init__(self, session, rssPoller)
194 self.feedTitle = feedTitle
195 self.newItems = newItems
197 self.nextFeedCB=nextFeedCB
198 self.previousFeedCB=previousFeedCB
200 self["content"] = RSSList(data)
201 self["summary"] = Label()
202 self["info"] = Label()
205 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
207 "ok": self.showCurrentEntry,
208 "cancel": self.close,
209 "nextBouquet": self.next,
210 "prevBouquet": self.previous,
212 "yellow": self.selectEnclosure,
214 self.onShown.append(self.__show)
215 self.onClose.append(self.__close)
219 self["actions"] = ActionMap([ "OkCancelActions" ],
221 "cancel": self.close,
224 self.timer = eTimer()
225 self.timer.timeout.get().append(self.timerTick)
226 self.onExecBegin.append(self.startTimer)
228 self["content"].connectSelChanged(self.updateInfo)
229 self.onLayoutFinish.extend([self.updateInfo, self.setConditionalTitle])
231 def startTimer(self):
232 self.timer.startLongTimer(5)
238 self.rssPoller.addCallback(self.pollCallback)
241 if self.timer is not None:
242 self.timer.timeout.get().remove(self.timerTick)
244 self.rssPoller.removeCallback(self.pollCallback)
246 def pollCallback(self, id = None):
247 print "[SimpleRSS] SimpleRSSFeed called back"
248 current_entry = self["content"].getCurrentEntry()
250 if id is not None and self.id == id+1:
251 print "[SimpleRSS] pollCallback recieved local feed", self.id
252 self.feedTitle = self.rssPoller.feeds[id].title
253 self.data = self.rssPoller.feeds[id].history
255 print "[SimpleRSS] pollCallback recieved all or non-local feed, updating active view (new_items)"
256 self.data = self.rssPoller.new_items
258 print "[SimpleRSS] pollCallback recieved all or non-local feed, updating", self.id
259 self.feedTitle = self.rssPoller.feeds[self.id-1].title
260 self.data = self.rssPoller.feeds[self-id-1].history
262 self["content"].l.setList(self.data)
263 self["content"].moveToEntry(current_entry)
265 self.setConditionalTitle()
268 def setConditionalTitle(self):
269 if not self.newItems:
270 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
272 self.setTitle("Simple RSS Reader: New Items")
274 def updateInfo(self):
275 current_entry = self["content"].getCurrentEntry()
277 self["summary"].setText(current_entry[2])
279 cur_idx = self["content"].getCurrentIndex()
280 self["info"].setText("Entry %s/%s" % (cur_idx+1, len(self.data)))
282 self["summary"].setText("Feed is empty.")
283 self["info"].setText("")
287 self.singleUpdate(self.id-1)
289 def nextEntryCB(self):
290 self["content"].moveDown()
291 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.data))
293 def previousEntryCB(self):
294 self["content"].moveUp()
295 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.data))
297 # TODO: Fix moving back to previously marked entry (same goes for self.previous)
300 if self.nextFeedCB is not None:
301 result = self.nextFeedCB()
302 (self.feedTitle, self.data, self.id) = result
303 #current_entry = self["content"].getCurrentEntry()
304 self["content"].l.setList(self.data) # Update list
305 self["content"].moveToIndex(0)
306 #self["content"].moveToEntry(current_entry)
307 self.updateInfo() # In case entry is no longer in history
308 self.setConditionalTitle() # Update title
310 return (self.feedTitle, self.data, self.id)
314 if self.previousFeedCB is not None:
315 result = self.previousFeedCB()
316 (self.feedTitle, self.data, self.id) = result
317 #current_entry = self["content"].getCurrentEntry()
318 self["content"].l.setList(self.data) # Update list
319 self["content"].moveToIndex(0)
320 #self["content"].moveToEntry(current_entry)
321 self.updateInfo() # In case entry is no longer in history
322 self.setConditionalTitle() # Update title
324 return (self.feedTitle, self.data, self.id)
326 def checkEmpty(self):
327 if self.id > 0 and not len(self.data):
328 self.singleUpdate(self.id-1)
330 def showCurrentEntry(self):
331 current_entry = self["content"].getCurrentEntry()
332 if current_entry is None: # empty list
335 self.session.openWithCallback(
339 cur_idx=self["content"].getCurrentIndex(),
340 entries=len(self.data),
341 feedTitle=self.feedTitle,
342 nextEntryCB=self.nextEntryCB,
343 previousEntryCB=self.previousEntryCB,
344 nextFeedCB=self.next,
345 previousFeedCB=self.previous
348 def selectEnclosure(self):
349 current_entry = self["content"].getCurrentEntry()
350 if current_entry is None: # empty list
353 RSSBaseView.selectEnclosure(self, current_entry[3])
355 class RSSOverview(RSSBaseView):
356 """Shows an Overview over all RSS-Feeds known to rssPoller"""
358 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
359 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
360 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
361 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
364 def __init__(self, session, poller):
365 RSSBaseView.__init__(self, session, poller)
367 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
369 "ok": self.showCurrentEntry,
370 "cancel": self.close,
372 "yellow": self.selectEnclosure,
377 # We always have at least "New Items"-Feed
378 self["content"] = RSSList(self.feeds)
379 self["summary"] = Label(self.feeds[0][2])
380 self["info"] = Label("Feed 1/%s" % len(self.feeds))
382 self["content"].connectSelChanged(self.updateInfo)
383 self.onShown.append(self.__show)
384 self.onClose.append(self.__close)
387 self.rssPoller.addCallback(self.pollCallback)
390 self.rssPoller.removeCallback(self.pollCallback)
395 "New Items since last Auto-Update",
396 ' '.join([str(len(self.rssPoller.new_items)), "Entries"]),
397 self.rssPoller.new_items
403 ' '.join([str(len(feed.history)), "Entries"]),
406 for feed in self.rssPoller.feeds
409 def pollCallback(self, id = None):
410 print "[SimpleRSS] SimpleRSS called back"
411 current_entry = self["content"].getCurrentEntry()
414 print "[SimpleRSS] pollCallback updating feed", id
416 self.rssPoller.feeds[id].title,
417 self.rssPoller.feeds[id].description,
418 ' '.join([str(len(self.rssPoller.feeds[id].history)), "Entries"]),
419 self.rssPoller.feeds[id].history
422 print "[SimpleRSS] pollCallback updating all feeds"
425 self["content"].l.setList(self.feeds)
426 self["content"].moveToEntry(current_entry)
430 def updateInfo(self):
431 current_entry = self["content"].getCurrentEntry()
433 self["summary"].setText(current_entry[2])
434 self["info"].setText("Feed %s/%s" % (self["content"].getCurrentIndex()+1, len(self.feeds)))
435 # Should never happen
437 self["summary"].setText("")
438 self["info"].setText("")
441 cur_idx = self["content"].getCurrentIndex()
444 (_("Update Feed"), "update"),
445 (_("Setup"), "setup"),
446 (_("Close"), "close")
450 (_("Setup"), "setup"),
451 (_("Close"), "close")
453 self.session.openWithCallback(
460 def menuChoice(self, result):
462 if result[1] == "update":
463 cur_idx = self["content"].getCurrentIndex()
465 self.singleUpdate(cur_idx-1)
466 elif result[1] == "setup":
467 self.session.openWithCallback(self.refresh, RSSSetup, rssPoller=self.rssPoller)
468 elif result[1] == "close":
472 current_entry = self["content"].getCurrentEntry()
475 self["content"].l.setList(self.feeds)
477 self["content"].moveToEntry(current_entry)
480 def nextFeedCB(self):
481 self["content"].moveUp()
482 current_entry = self["content"].getCurrentEntry()
483 return (current_entry[0], current_entry[3], self["content"].getCurrentIndex())
485 def previousFeedCB(self):
486 self["content"].moveDown()
487 current_entry = self["content"].getCurrentEntry()
488 return (current_entry[0], current_entry[3], self["content"].getCurrentIndex())
490 def showCurrentEntry(self):
491 current_entry = self["content"].getCurrentEntry()
492 if current_entry is None: # empty list
495 self.session.openWithCallback(
499 feedTitle=current_entry[0],
500 nextFeedCB=self.nextFeedCB,
501 previousFeedCB=self.previousFeedCB,
502 rssPoller=self.rssPoller,
503 id=self["content"].getCurrentIndex()
506 def selectEnclosure(self):
507 current_entry = self["content"].getCurrentEntry()
508 if current_entry is None: # empty list
511 # Build a list of all enclosures in this feed
513 for entry in current_entry[3]:
514 enclosures.extend(entry[3])
515 RSSBaseView.selectEnclosure(self, enclosures)