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
13 from RSSList import RSSFeedList, RSSEntryList
14 from RSSSetup import RSSSetup
16 class RSSBaseView(Screen):
17 """Base Screen for all Screens used in SimpleRSS"""
19 def __init__(self, session, poller, parent=None):
20 Screen.__init__(self, session)
21 self.rssPoller = poller
22 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,400" font="Regular; 22" />
81 def __init__(self, session, data, feedTitle="", cur_idx=None, entries=None, parent=None):
82 RSSBaseView.__init__(self, session, None, parent)
85 self.feedTitle = feedTitle
86 self.cur_idx = cur_idx
87 self.entries = entries
89 if cur_idx is not None and entries is not None:
90 self["info"] = Label(_("Entry %s/%s") % (cur_idx+1, entries))
92 self["info"] = Label()
95 self["content"] = ScrollLabel("\n\n".join([data[0], data[2], " ".join([str(len(data[3])), "Enclosures"])]))
97 self["content"] = ScrollLabel()
99 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "ColorActions", "DirectionActions" ],
101 "cancel": self.close,
102 "ok": self.selectEnclosure,
103 "yellow": self.selectEnclosure,
107 "left": self.previous,
108 "nextBouquet": self.nextFeed,
109 "prevBouquet": self.previousFeed,
112 self.onLayoutFinish.append(self.setConditionalTitle)
114 def setConditionalTitle(self):
115 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
118 self["content"].pageUp()
121 self["content"].pageDown()
124 if self.parent is not None:
125 (self.data, self.cur_idx, self.entries) = self.parent.nextEntry()
129 if self.parent is not None:
130 (self.data, self.cur_idx, self.entries) = self.parent.previousEntry()
135 if self.parent is not None:
136 result = self.parent.next()
137 self.feedTitle = result[0]
138 self.entries = len(result[1])
141 self.data = result[1][0]
145 self.setConditionalTitle()
148 def previousFeed(self):
150 if self.parent is not None:
151 result = self.parent.previous()
152 self.feedTitle = result[0]
153 self.entries = len(result[1])
156 self.data = result[1][0]
160 self.setConditionalTitle()
163 def setContent(self):
164 if self.cur_idx is not None and self.entries is not None:
165 self["info"].setText(_("Entry %s/%s") % (self.cur_idx+1, self.entries))
167 self["info"].setText("")
168 if self.data is not None:
169 self["content"].setText("\n\n".join([self.data[0], self.data[2], " ".join([str(len(self.data[3])), _("Enclosures")])]))
171 self["content"].setText(_("No such Item."))
173 def selectEnclosure(self):
174 if self.data is not None:
175 RSSBaseView.selectEnclosure(self, self.data[3])
177 class RSSFeedView(RSSBaseView):
178 """Shows a RSS-Feed"""
180 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
181 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
182 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
183 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
186 def __init__(self, session, feed=None, newItems=False, parent=None, rssPoller=None,id=None):
187 RSSBaseView.__init__(self, session, rssPoller, parent)
190 self.newItems = newItems
193 self["content"] = RSSEntryList(self.feed.history)
194 self["summary"] = Label()
195 self["info"] = Label()
198 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
200 "ok": self.showCurrentEntry,
201 "cancel": self.close,
202 "nextBouquet": self.next,
203 "prevBouquet": self.previous,
205 "yellow": self.selectEnclosure,
207 self.onLayoutFinish.append(self.__show)
208 self.onClose.append(self.__close)
212 self["actions"] = ActionMap([ "OkCancelActions" ],
214 "cancel": self.close,
217 self.timer = eTimer()
218 self.timer.callback.append(self.timerTick)
219 self.onExecBegin.append(self.startTimer)
221 self["content"].connectSelChanged(self.updateInfo)
222 self.onLayoutFinish.extend([self.updateInfo, self.setConditionalTitle])
224 def startTimer(self):
225 self.timer.startLongTimer(5)
228 self.timer.callback.remove(self.timerTick)
234 self.rssPoller.addCallback(self.pollCallback)
237 if self.timer is not None:
238 self.timer.callback.remove(self.timerTick)
240 self.rssPoller.removeCallback(self.pollCallback)
242 def pollCallback(self, id = None):
243 print "[SimpleRSS] SimpleRSSFeed called back"
245 if id is None or id+1 == self.id:
246 # TODO: do we really need this?
247 current_entry = self["content"].getCurrentEntry()
248 self["content"].moveToEntry(current_entry)
250 self["content"].invalidate()
251 self.setConditionalTitle()
254 def setConditionalTitle(self):
255 self.setTitle(': '.join(["Simple RSS Reader", self.feed.title]))
257 def updateInfo(self):
258 current_entry = self["content"].getCurrentEntry()
260 self["summary"].setText(current_entry[2])
262 cur_idx = self["content"].getCurrentIndex()
263 self["info"].setText(_("Entry %s/%s") % (cur_idx+1, len(self.feed.history)))
265 self["summary"].setText(_("Feed is empty."))
266 self["info"].setText("")
270 self.singleUpdate(self.id-1)
273 self["content"].moveDown()
274 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.feed.history))
276 def previousEntry(self):
277 self["content"].moveUp()
278 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.feed.history))
280 # TODO: Fix moving back to previously marked entry (same goes for self.previous)
283 if self.parent is not None:
284 (self.feed, self.id) = self.parent.nextFeed()
285 #current_entry = self["content"].getCurrentEntry()
286 self["content"].l.setList(self.feed.history) # Update list
287 self["content"].moveToIndex(0)
288 #self["content"].moveToEntry(current_entry)
289 self.updateInfo() # In case entry is no longer in history
290 self.setConditionalTitle() # Update title
291 return (self.feed.title, self.feed.history, self.id)
292 return (self.feed.title, self.feed.history, self.id)
296 if self.parent is not None:
297 (self.feed, self.id) = self.parent.previousFeed()
298 #current_entry = self["content"].getCurrentEntry()
299 self["content"].l.setList(self.feed.history) # Update list
300 self["content"].moveToIndex(0)
301 #self["content"].moveToEntry(current_entry)
302 self.updateInfo() # In case entry is no longer in history
303 self.setConditionalTitle() # Update title
304 return (self.feed.title, self.feed.history, self.id)
305 return (self.feed.title, self.feed.history, self.id)
307 def checkEmpty(self):
308 if self.id > 0 and not len(self.feed.history):
309 self.singleUpdate(self.id-1)
311 def showCurrentEntry(self):
312 current_entry = self["content"].getCurrentEntry()
313 if current_entry is None: # empty list
316 self.session.openWithCallback(
320 cur_idx=self["content"].getCurrentIndex(),
321 entries=len(self.feed.history),
322 feedTitle=self.feed.title,
326 def selectEnclosure(self):
327 current_entry = self["content"].getCurrentEntry()
328 if current_entry is None: # empty list
331 RSSBaseView.selectEnclosure(self, current_entry[3])
333 class RSSOverview(RSSBaseView):
334 """Shows an Overview over all RSS-Feeds known to rssPoller"""
336 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
337 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
338 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
339 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
342 def __init__(self, session, poller):
343 RSSBaseView.__init__(self, session, poller)
345 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
347 "ok": self.showCurrentEntry,
348 "cancel": self.close,
350 "yellow": self.selectEnclosure,
355 # We always have at least "New Items"-Feed
356 self["content"] = RSSFeedList(self.feeds)
357 self["summary"] = Label(' '.join([str(len(self.feeds[0][0].history)), _("Entries")]))
358 self["info"] = Label(_("Feed %s/%s") % (1, len(self.feeds)))
360 self["content"].connectSelChanged(self.updateInfo)
361 self.onLayoutFinish.append(self.__show)
362 self.onClose.append(self.__close)
365 self.rssPoller.addCallback(self.pollCallback)
368 self.rssPoller.removeCallback(self.pollCallback)
371 # Feedlist contains our virtual Feed and all real ones
372 self.feeds = [(self.rssPoller.newItemFeed,)]
373 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
375 def pollCallback(self, id = None):
376 print "[SimpleRSS] SimpleRSS called back"
378 self["content"].invalidate()
380 def updateInfo(self):
381 current_entry = self["content"].getCurrentEntry()
382 self["summary"].setText(' '.join([str(len(current_entry.history)), _("Entries")]))
383 self["info"].setText(_("Feed %s/%s") % (self["content"].getCurrentIndex()+1, len(self.feeds)))
386 cur_idx = self["content"].getCurrentIndex()
389 (_("Update Feed"), "update"),
390 (_("Setup"), "setup"),
391 (_("Close"), "close")
395 (_("Setup"), "setup"),
396 (_("Close"), "close")
398 self.session.openWithCallback(
405 def menuChoice(self, result):
407 if result[1] == "update":
408 cur_idx = self["content"].getCurrentIndex()
410 self.singleUpdate(cur_idx-1)
411 elif result[1] == "setup":
412 self.session.openWithCallback(
415 rssPoller=self.rssPoller
417 elif result[1] == "close":
421 current_entry = self["content"].getCurrentEntry()
424 self["content"].l.setList(self.feeds)
426 self["content"].moveToEntry(current_entry)
430 self["content"].moveUp()
431 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex())
433 def previousFeed(self):
434 self["content"].moveDown()
435 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex())
437 def showCurrentEntry(self):
438 current_entry = self["content"].getCurrentEntry()
439 self.session.openWithCallback(
444 rssPoller=self.rssPoller,
445 id=self["content"].getCurrentIndex()
448 def selectEnclosure(self):
449 # Build a list of all enclosures in this feed
451 for entry in self["content"].getCurrentEntry().history:
452 enclosures.extend(entry[3])
453 RSSBaseView.selectEnclosure(self, enclosures)