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 RSSFeedList, RSSEntryList
15 from RSSSetup import RSSSetup
17 class RSSBaseView(Screen):
18 """Base Screen for all Screens used in SimpleRSS"""
20 def __init__(self, session, poller, parent=None):
21 Screen.__init__(self, session)
22 self.rssPoller = poller
23 self.pollDialog = None
26 def errorPolling(self, errmsg = ""):
27 # An error occured while polling
30 _("Error while parsing Feed, this usually means there is something wrong with it."),
31 type = MessageBox.TYPE_ERROR,
35 # Don't show "we're updating"-dialog any longer
37 self.pollDialog.close()
38 self.pollDialog = None
40 def singleUpdate(self, feedid, errback = None):
41 # Don't do anything if we have no poller
42 if self.rssPoller is None:
45 # Default errorback to self.errorPolling
46 # If an empty errorback is wanted the Screen needs to provide it
48 errback = self.errorPolling
51 self.rssPoller.singlePoll(feedid, callback=True, errorback=errback)
53 # Open Dialog and save locally
54 self.pollDialog = self.session.open(
56 _("Update is being done in Background.\nContents will automatically be updated when it's done."),
57 type = MessageBox.TYPE_INFO,
61 def selectEnclosure(self, enclosures):
63 if enclosures is None:
66 if not openList(self.session, enclosures):
69 _("Found no Enclosure we can display."),
70 type = MessageBox.TYPE_INFO,
74 class RSSEntryView(RSSBaseView):
75 """Shows a RSS Item"""
77 <screen position="100,100" size="460,420" title="Simple RSS Reader" >
78 <widget name="info" position="0,0" size="460, 20" halign="right" font="Regular; 18" />
79 <widget name="content" position="0,20" size="460,400" font="Regular; 22" />
82 def __init__(self, session, data, feedTitle="", cur_idx=None, entries=None, parent=None):
83 RSSBaseView.__init__(self, session, None, parent)
86 self.feedTitle = feedTitle
87 self.cur_idx = cur_idx
88 self.entries = entries
90 if cur_idx is not None and entries is not None:
91 self["info"] = Label(_("Entry %s/%s") % (cur_idx+1, entries))
93 self["info"] = Label()
96 self["content"] = ScrollLabel("\n\n".join([data[0], data[2], " ".join([str(len(data[3])), "Enclosures"])]))
98 self["content"] = ScrollLabel()
100 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "ColorActions", "DirectionActions" ],
102 "cancel": self.close,
103 "ok": self.selectEnclosure,
104 "yellow": self.selectEnclosure,
108 "left": self.previous,
109 "nextBouquet": self.nextFeed,
110 "prevBouquet": self.previousFeed,
113 self.onLayoutFinish.append(self.setConditionalTitle)
115 def setConditionalTitle(self):
116 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
119 self["content"].pageUp()
122 self["content"].pageDown()
125 if self.parent is not None:
126 (self.data, self.cur_idx, self.entries) = self.parent.nextEntry()
130 if self.parent is not None:
131 (self.data, self.cur_idx, self.entries) = self.parent.previousEntry()
136 if self.parent is not None:
137 result = self.parent.next()
138 self.feedTitle = result[0]
139 self.entries = len(result[1])
142 self.data = result[1][0]
146 self.setConditionalTitle()
149 def previousFeed(self):
151 if self.parent is not None:
152 result = self.parent.previous()
153 self.feedTitle = result[0]
154 self.entries = len(result[1])
157 self.data = result[1][0]
161 self.setConditionalTitle()
164 def setContent(self):
165 if self.cur_idx is not None and self.entries is not None:
166 self["info"].setText(_("Entry %s/%s") % (self.cur_idx+1, self.entries))
168 self["info"].setText("")
169 if self.data is not None:
170 self["content"].setText("\n\n".join([self.data[0], self.data[2], " ".join([str(len(self.data[3])), _("Enclosures")])]))
172 self["content"].setText(_("No such Item."))
174 def selectEnclosure(self):
175 if self.data is not None:
176 RSSBaseView.selectEnclosure(self, self.data[3])
178 class RSSFeedView(RSSBaseView):
179 """Shows a RSS-Feed"""
181 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
182 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
183 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
184 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
187 def __init__(self, session, feed=None, newItems=False, parent=None, rssPoller=None,id=None):
188 RSSBaseView.__init__(self, session, rssPoller, parent)
191 self.newItems = newItems
194 self["content"] = RSSEntryList(self.feed.history)
195 self["summary"] = Label()
196 self["info"] = Label()
199 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
201 "ok": self.showCurrentEntry,
202 "cancel": self.close,
203 "nextBouquet": self.next,
204 "prevBouquet": self.previous,
206 "yellow": self.selectEnclosure,
208 self.onLayoutFinish.append(self.__show)
209 self.onClose.append(self.__close)
213 self["actions"] = ActionMap([ "OkCancelActions" ],
215 "cancel": self.close,
218 self.timer = eTimer()
219 self.timer.timeout.get().append(self.timerTick)
220 self.onExecBegin.append(self.startTimer)
222 self["content"].connectSelChanged(self.updateInfo)
223 self.onLayoutFinish.extend([self.updateInfo, self.setConditionalTitle])
225 def startTimer(self):
226 self.timer.startLongTimer(5)
232 self.rssPoller.addCallback(self.pollCallback)
235 if self.timer is not None:
236 self.timer.timeout.get().remove(self.timerTick)
238 self.rssPoller.removeCallback(self.pollCallback)
240 def pollCallback(self, id = None):
241 print "[SimpleRSS] SimpleRSSFeed called back"
243 if id is None or id+1 == self.id:
244 # TODO: do we really need this?
245 current_entry = self["content"].getCurrentEntry()
246 self["content"].moveToEntry(current_entry)
248 self["content"].invalidate()
249 self.setConditionalTitle()
252 def setConditionalTitle(self):
253 self.setTitle(': '.join(["Simple RSS Reader", self.feed.title]))
255 def updateInfo(self):
256 current_entry = self["content"].getCurrentEntry()
258 self["summary"].setText(current_entry[2])
260 cur_idx = self["content"].getCurrentIndex()
261 self["info"].setText(_("Entry %s/%s") % (cur_idx+1, len(self.feed.history)))
263 self["summary"].setText(_("Feed is empty."))
264 self["info"].setText("")
268 self.singleUpdate(self.id-1)
271 self["content"].moveDown()
272 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.feed.history))
274 def previousEntry(self):
275 self["content"].moveUp()
276 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.feed.history))
278 # TODO: Fix moving back to previously marked entry (same goes for self.previous)
281 if self.parent is not None:
282 (self.feed, self.id) = self.parent.nextFeed()
283 #current_entry = self["content"].getCurrentEntry()
284 self["content"].l.setList(self.feed.history) # Update list
285 self["content"].moveToIndex(0)
286 #self["content"].moveToEntry(current_entry)
287 self.updateInfo() # In case entry is no longer in history
288 self.setConditionalTitle() # Update title
289 return (self.feed.title, self.feed.history, self.id)
290 return (self.feed.title, self.feed.history, self.id)
294 if self.parent is not None:
295 (self.feed, self.id) = self.parent.previousFeed()
296 #current_entry = self["content"].getCurrentEntry()
297 self["content"].l.setList(self.feed.history) # Update list
298 self["content"].moveToIndex(0)
299 #self["content"].moveToEntry(current_entry)
300 self.updateInfo() # In case entry is no longer in history
301 self.setConditionalTitle() # Update title
302 return (self.feed.title, self.feed.history, self.id)
303 return (self.feed.title, self.feed.history, self.id)
305 def checkEmpty(self):
306 if self.id > 0 and not len(self.feed.history):
307 self.singleUpdate(self.id-1)
309 def showCurrentEntry(self):
310 current_entry = self["content"].getCurrentEntry()
311 if current_entry is None: # empty list
314 self.session.openWithCallback(
318 cur_idx=self["content"].getCurrentIndex(),
319 entries=len(self.feed.history),
320 feedTitle=self.feed.title,
324 def selectEnclosure(self):
325 current_entry = self["content"].getCurrentEntry()
326 if current_entry is None: # empty list
329 RSSBaseView.selectEnclosure(self, current_entry[3])
331 class RSSOverview(RSSBaseView):
332 """Shows an Overview over all RSS-Feeds known to rssPoller"""
334 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
335 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
336 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
337 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
340 def __init__(self, session, poller):
341 RSSBaseView.__init__(self, session, poller)
343 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
345 "ok": self.showCurrentEntry,
346 "cancel": self.close,
348 "yellow": self.selectEnclosure,
353 # We always have at least "New Items"-Feed
354 self["content"] = RSSFeedList(self.feeds)
355 self["summary"] = Label(' '.join([str(len(self.feeds[0][0].history)), _("Entries")]))
356 self["info"] = Label(_("Feed %s/%s") % (1, len(self.feeds)))
358 self["content"].connectSelChanged(self.updateInfo)
359 self.onLayoutFinish.append(self.__show)
360 self.onClose.append(self.__close)
363 self.rssPoller.addCallback(self.pollCallback)
366 self.rssPoller.removeCallback(self.pollCallback)
369 # Feedlist contains our virtual Feed and all real ones
370 self.feeds = [(self.rssPoller.newItemFeed,)]
371 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
373 def pollCallback(self, id = None):
374 print "[SimpleRSS] SimpleRSS called back"
376 self["content"].invalidate()
378 def updateInfo(self):
379 current_entry = self["content"].getCurrentEntry()
380 self["summary"].setText(' '.join([str(len(current_entry.history)), _("Entries")]))
381 self["info"].setText(_("Feed %s/%s") % (self["content"].getCurrentIndex()+1, len(self.feeds)))
384 cur_idx = self["content"].getCurrentIndex()
387 (_("Update Feed"), "update"),
388 (_("Setup"), "setup"),
389 (_("Close"), "close")
393 (_("Setup"), "setup"),
394 (_("Close"), "close")
396 self.session.openWithCallback(
403 def menuChoice(self, result):
405 if result[1] == "update":
406 cur_idx = self["content"].getCurrentIndex()
408 self.singleUpdate(cur_idx-1)
409 elif result[1] == "setup":
410 self.session.openWithCallback(
413 rssPoller=self.rssPoller
415 elif result[1] == "close":
419 current_entry = self["content"].getCurrentEntry()
422 self["content"].l.setList(self.feeds)
424 self["content"].moveToEntry(current_entry)
428 self["content"].moveUp()
429 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex())
431 def previousFeed(self):
432 self["content"].moveDown()
433 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex())
435 def showCurrentEntry(self):
436 current_entry = self["content"].getCurrentEntry()
437 self.session.openWithCallback(
442 rssPoller=self.rssPoller,
443 id=self["content"].getCurrentIndex()
446 def selectEnclosure(self):
447 # Build a list of all enclosures in this feed
449 for entry in self["content"].getCurrentEntry().history:
450 enclosures.extend(entry[3])
451 RSSBaseView.selectEnclosure(self, enclosures)