1 from enigma import eTimer
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
6 from Components.ActionMap import ActionMap
7 from Components.Label import Label
8 from Components.ScrollLabel import ScrollLabel
10 from RSSList import RSSFeedList, RSSEntryList
12 class RSSBaseView(Screen):
13 """Base Screen for all Screens used in SimpleRSS"""
15 def __init__(self, session, poller, parent = None):
16 Screen.__init__(self, session, parent)
17 self.rssPoller = poller
18 self.pollDialog = None
20 def errorPolling(self, errmsg = ""):
21 # An error occured while polling
24 _("Error while parsing Feed, this usually means there is something wrong with it."),
25 type = MessageBox.TYPE_ERROR,
29 # Don't show "we're updating"-dialog any longer
31 self.pollDialog.close()
32 self.pollDialog = None
34 def singleUpdate(self, feedid, errback = None):
35 # Don't do anything if we have no poller
36 if self.rssPoller is None:
39 # Default errorback to self.errorPolling
40 # If an empty errorback is wanted the Screen needs to provide it
42 errback = self.errorPolling
45 self.rssPoller.singlePoll(feedid, callback=True, errorback=errback)
47 # Open Dialog and save locally
48 self.pollDialog = self.session.open(
50 _("Update is being done in Background.\nContents will automatically be updated when it's done."),
51 type = MessageBox.TYPE_INFO,
55 def selectEnclosure(self, enclosures):
57 if enclosures is None:
60 from Components.Scanner import openList
62 if not openList(self.session, enclosures):
65 _("Found no Enclosure we can display."),
66 type = MessageBox.TYPE_INFO,
70 class RSSEntryView(RSSBaseView):
71 """Shows a RSS Item"""
74 <screen position="100,100" size="460,420" title="Simple RSS Reader" >
75 <widget name="info" position="0,0" size="460, 20" halign="right" font="Regular; 18" />
76 <widget name="content" position="0,20" size="460,400" font="Regular; 22" />
79 def __init__(self, session, data, feedTitle="", cur_idx=None, entries=None, parent=None):
80 RSSBaseView.__init__(self, session, None, parent)
83 self.feedTitle = feedTitle
84 self.cur_idx = cur_idx
85 self.entries = entries
87 if cur_idx is not None and entries is not None:
88 self["info"] = Label(_("Entry %s/%s") % (cur_idx+1, entries))
90 self["info"] = Label()
93 self["content"] = ScrollLabel("\n\n".join([data[0], data[2], " ".join([str(len(data[3])), "Enclosures"])]))
95 self["content"] = ScrollLabel()
97 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "ColorActions", "DirectionActions" ],
100 "ok": self.selectEnclosure,
101 "yellow": self.selectEnclosure,
105 "left": self.previous,
106 "nextBouquet": self.nextFeed,
107 "prevBouquet": self.previousFeed,
110 self.onLayoutFinish.append(self.setConditionalTitle)
112 def setConditionalTitle(self):
113 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
116 self["content"].pageUp()
119 self["content"].pageDown()
122 if self.parent is not None:
123 (self.data, self.cur_idx, self.entries) = self.parent.nextEntry()
127 if self.parent is not None:
128 (self.data, self.cur_idx, self.entries) = self.parent.previousEntry()
133 if self.parent is not None:
134 result = self.parent.next()
135 self.feedTitle = result[0]
136 self.entries = len(result[1])
139 self.data = result[1][0]
143 self.setConditionalTitle()
146 def previousFeed(self):
148 if self.parent is not None:
149 result = self.parent.previous()
150 self.feedTitle = result[0]
151 self.entries = len(result[1])
154 self.data = result[1][0]
158 self.setConditionalTitle()
161 def setContent(self):
162 if self.cur_idx is not None and self.entries is not None:
163 self["info"].setText(_("Entry %s/%s") % (self.cur_idx+1, self.entries))
165 self["info"].setText("")
166 if self.data is not None:
167 self["content"].setText("\n\n".join([self.data[0], self.data[2], " ".join([str(len(self.data[3])), _("Enclosures")])]))
169 self["content"].setText(_("No such Item."))
171 def selectEnclosure(self):
172 if self.data is not None:
173 RSSBaseView.selectEnclosure(self, self.data[3])
175 class RSSFeedView(RSSBaseView):
176 """Shows a RSS-Feed"""
179 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
180 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
181 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
182 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
185 def __init__(self, session, feed=None, newItems=False, parent=None, rssPoller=None,id=None):
186 RSSBaseView.__init__(self, session, rssPoller, parent)
189 self.newItems = newItems
192 self["content"] = RSSEntryList(self.feed.history)
193 self["summary"] = Label()
194 self["info"] = Label()
197 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
199 "ok": self.showCurrentEntry,
200 "cancel": self.close,
201 "nextBouquet": self.next,
202 "prevBouquet": self.previous,
204 "yellow": self.selectEnclosure,
206 self.onLayoutFinish.append(self.__show)
207 self.onClose.append(self.__close)
211 self["actions"] = ActionMap([ "OkCancelActions" ],
213 "cancel": self.close,
216 self.timer = eTimer()
217 self.timer.callback.append(self.timerTick)
218 self.onExecBegin.append(self.startTimer)
220 self["content"].connectSelChanged(self.updateInfo)
221 self.onLayoutFinish.extend([self.updateInfo, self.setConditionalTitle])
223 def startTimer(self):
224 self.timer.startLongTimer(5)
227 self.timer.callback.remove(self.timerTick)
232 self.rssPoller.addCallback(self.pollCallback)
235 if self.timer is not None:
236 self.timer.callback.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"].getCurrent()
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"].getCurrent()
258 self["summary"].setText(current_entry[2])
260 cur_idx = self["content"].getSelectedIndex()
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"].down()
272 return (self["content"].getCurrent(), self["content"].getSelectedIndex(), len(self.feed.history))
274 def previousEntry(self):
276 return (self["content"].getCurrent(), self["content"].getSelectedIndex(), 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"].getCurrent()
284 self["content"].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"].getCurrent()
297 self["content"].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"].getCurrent()
311 if current_entry is None: # empty list
314 self.session.openWithCallback(
318 cur_idx=self["content"].getSelectedIndex(),
319 entries=len(self.feed.history),
320 feedTitle=self.feed.title,
324 def selectEnclosure(self):
325 current_entry = self["content"].getCurrent()
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"""
335 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
336 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
337 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
338 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
341 def __init__(self, session, poller):
342 RSSBaseView.__init__(self, session, poller)
344 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
346 "ok": self.showCurrentEntry,
347 "cancel": self.close,
349 "yellow": self.selectEnclosure,
354 # We always have at least "New Items"-Feed
355 self["content"] = RSSFeedList(self.feeds)
356 self["summary"] = Label(' '.join([str(len(self.feeds[0][0].history)), _("Entries")]))
357 self["info"] = Label(_("Feed %s/%s") % (1, len(self.feeds)))
359 self["content"].connectSelChanged(self.updateInfo)
360 self.onLayoutFinish.append(self.__show)
361 self.onClose.append(self.__close)
364 self.rssPoller.addCallback(self.pollCallback)
367 self.rssPoller.removeCallback(self.pollCallback)
370 # Feedlist contains our virtual Feed and all real ones
371 self.feeds = [(self.rssPoller.newItemFeed,)]
372 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
374 def pollCallback(self, id = None):
375 print "[SimpleRSS] SimpleRSS called back"
377 self["content"].invalidate()
379 def updateInfo(self):
380 current_entry = self["content"].getCurrent()
381 self["summary"].setText(' '.join([str(len(current_entry.history)), _("Entries")]))
382 self["info"].setText(_("Feed %s/%s") % (self["content"].getSelectedIndex()+1, len(self.feeds)))
385 from Screens.ChoiceBox import ChoiceBox
387 cur_idx = self["content"].getSelectedIndex()
390 (_("Update Feed"), "update"),
391 (_("Setup"), "setup"),
392 (_("Close"), "close")
396 (_("Setup"), "setup"),
397 (_("Close"), "close")
400 self.session.openWithCallback(
407 def menuChoice(self, result):
409 if result[1] == "update":
410 cur_idx = self["content"].getSelectedIndex()
412 self.singleUpdate(cur_idx-1)
413 elif result[1] == "setup":
414 from RSSSetup import RSSSetup
416 self.session.openWithCallback(
419 rssPoller=self.rssPoller
421 elif result[1] == "close":
425 current_entry = self["content"].getCurrent()
428 self["content"].setList(self.feeds)
430 self["content"].moveToEntry(current_entry)
435 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
437 def previousFeed(self):
438 self["content"].down()
439 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
441 def showCurrentEntry(self):
442 current_entry = self["content"].getCurrent()
443 self.session.openWithCallback(
448 rssPoller=self.rssPoller,
449 id=self["content"].getSelectedIndex()
452 def selectEnclosure(self):
453 # Build a list of all enclosures in this feed
455 for entry in self["content"].getCurrent().history:
456 enclosures.extend(entry[3])
457 RSSBaseView.selectEnclosure(self, enclosures)