1 # for localized messages
4 from enigma import eTimer
6 from Screens.Screen import Screen
7 from Screens.MessageBox import MessageBox
9 from Components.ActionMap import ActionMap
10 from Components.Label import Label
11 from Components.ScrollLabel import ScrollLabel
13 from RSSList import RSSFeedList, RSSEntryList
15 class RSSBaseView(Screen):
16 """Base Screen for all Screens used in SimpleRSS"""
18 def __init__(self, session, poller, parent = None):
19 Screen.__init__(self, session, parent)
20 self.rssPoller = poller
21 self.pollDialog = None
23 def errorPolling(self, errmsg = ""):
24 # An error occured while polling
27 _("Error while parsing Feed, this usually means there is something wrong with it."),
28 type = MessageBox.TYPE_ERROR,
32 # Don't show "we're updating"-dialog any longer
34 self.pollDialog.close()
35 self.pollDialog = None
37 def singleUpdate(self, feedid, errback = None):
38 # Don't do anything if we have no poller
39 if self.rssPoller is None:
42 # Default errorback to self.errorPolling
43 # If an empty errorback is wanted the Screen needs to provide it
45 errback = self.errorPolling
48 self.rssPoller.singlePoll(feedid, callback=True, errorback=errback)
50 # Open Dialog and save locally
51 self.pollDialog = self.session.open(
53 _("Update is being done in Background.\nContents will automatically be updated when it's done."),
54 type = MessageBox.TYPE_INFO,
58 def selectEnclosure(self, enclosures):
60 if enclosures is None:
63 from Components.Scanner import openList
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"""
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(_("Simple RSS Reader: %s") % (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"""
182 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
183 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
184 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
185 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
188 def __init__(self, session, feed=None, newItems=False, parent=None, rssPoller=None,id=None):
189 RSSBaseView.__init__(self, session, rssPoller, parent)
192 self.newItems = newItems
195 self["content"] = RSSEntryList(self.feed.history)
196 self["summary"] = Label()
197 self["info"] = Label()
200 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
202 "ok": self.showCurrentEntry,
203 "cancel": self.close,
204 "nextBouquet": self.next,
205 "prevBouquet": self.previous,
207 "yellow": self.selectEnclosure,
209 self.onLayoutFinish.append(self.__show)
210 self.onClose.append(self.__close)
214 self["actions"] = ActionMap([ "OkCancelActions" ],
216 "cancel": self.close,
219 self.timer = eTimer()
220 self.timer.callback.append(self.timerTick)
221 self.onExecBegin.append(self.startTimer)
223 self["content"].connectSelChanged(self.updateInfo)
224 self.onLayoutFinish.extend([self.updateInfo, self.setConditionalTitle])
226 def startTimer(self):
227 self.timer.startLongTimer(5)
230 self.timer.callback.remove(self.timerTick)
235 self.rssPoller.addCallback(self.pollCallback)
238 if self.timer is not None:
239 self.timer.callback.remove(self.timerTick)
241 self.rssPoller.removeCallback(self.pollCallback)
243 def pollCallback(self, id = None):
244 print "[SimpleRSS] SimpleRSSFeed called back"
246 if id is None or id+1 == self.id:
247 # TODO: do we really need this?
248 current_entry = self["content"].getCurrent()
249 self["content"].moveToEntry(current_entry)
251 self["content"].invalidate()
252 self.setConditionalTitle()
255 def setConditionalTitle(self):
256 self.setTitle(_("Simple RSS Reader: %s") % (self.feed.title))
258 def updateInfo(self):
259 current_entry = self["content"].getCurrent()
261 self["summary"].setText(current_entry[2])
263 cur_idx = self["content"].getSelectedIndex()
264 self["info"].setText(_("Entry %s/%s") % (cur_idx+1, len(self.feed.history)))
266 self["summary"].setText(_("Feed is empty."))
267 self["info"].setText("")
271 self.singleUpdate(self.id-1)
274 self["content"].down()
275 return (self["content"].getCurrent(), self["content"].getSelectedIndex(), len(self.feed.history))
277 def previousEntry(self):
279 return (self["content"].getCurrent(), self["content"].getSelectedIndex(), len(self.feed.history))
281 # TODO: Fix moving back to previously marked entry (same goes for self.previous)
284 if self.parent is not None:
285 (self.feed, self.id) = self.parent.nextFeed()
286 #current_entry = self["content"].getCurrent()
287 self["content"].setList(self.feed.history) # Update list
288 self["content"].moveToIndex(0)
289 #self["content"].moveToEntry(current_entry)
290 self.updateInfo() # In case entry is no longer in history
291 self.setConditionalTitle() # Update title
292 return (self.feed.title, self.feed.history, self.id)
293 return (self.feed.title, self.feed.history, self.id)
297 if self.parent is not None:
298 (self.feed, self.id) = self.parent.previousFeed()
299 #current_entry = self["content"].getCurrent()
300 self["content"].setList(self.feed.history) # Update list
301 self["content"].moveToIndex(0)
302 #self["content"].moveToEntry(current_entry)
303 self.updateInfo() # In case entry is no longer in history
304 self.setConditionalTitle() # Update title
305 return (self.feed.title, self.feed.history, self.id)
306 return (self.feed.title, self.feed.history, self.id)
308 def checkEmpty(self):
309 if self.id > 0 and not len(self.feed.history):
310 self.singleUpdate(self.id-1)
312 def showCurrentEntry(self):
313 current_entry = self["content"].getCurrent()
314 if current_entry is None: # empty list
317 self.session.openWithCallback(
321 cur_idx=self["content"].getSelectedIndex(),
322 entries=len(self.feed.history),
323 feedTitle=self.feed.title,
327 def selectEnclosure(self):
328 current_entry = self["content"].getCurrent()
329 if current_entry is None: # empty list
332 RSSBaseView.selectEnclosure(self, current_entry[3])
334 class RSSOverview(RSSBaseView):
335 """Shows an Overview over all RSS-Feeds known to rssPoller"""
338 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
339 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
340 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
341 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
344 def __init__(self, session, poller):
345 RSSBaseView.__init__(self, session, poller)
347 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
349 "ok": self.showCurrentEntry,
350 "cancel": self.close,
352 "yellow": self.selectEnclosure,
357 # We always have at least "New Items"-Feed
358 self["content"] = RSSFeedList(self.feeds)
359 self["summary"] = Label(' '.join((str(len(self.feeds[0][0].history)), _("Entries"))))
360 self["info"] = Label(_("Feed %s/%s") % (1, len(self.feeds)))
362 self["content"].connectSelChanged(self.updateInfo)
363 self.onLayoutFinish.append(self.__show)
364 self.onClose.append(self.__close)
367 self.rssPoller.addCallback(self.pollCallback)
368 self.setTitle(_("Simple RSS Reader"))
371 self.rssPoller.removeCallback(self.pollCallback)
374 # Feedlist contains our virtual Feed and all real ones
375 self.feeds = [(self.rssPoller.newItemFeed,)]
376 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
378 def pollCallback(self, id = None):
379 print "[SimpleRSS] SimpleRSS called back"
381 self["content"].invalidate()
383 def updateInfo(self):
384 current_entry = self["content"].getCurrent()
385 self["summary"].setText(' '.join((str(len(current_entry.history)), _("Entries"))))
386 self["info"].setText(_("Feed %s/%s") % (self["content"].getSelectedIndex()+1, len(self.feeds)))
389 from Screens.ChoiceBox import ChoiceBox
391 cur_idx = self["content"].getSelectedIndex()
394 (_("Update Feed"), "update"),
395 (_("Setup"), "setup"),
396 (_("Close"), "close")
400 (_("Setup"), "setup"),
401 (_("Close"), "close")
404 self.session.openWithCallback(
411 def menuChoice(self, result):
413 if result[1] == "update":
414 cur_idx = self["content"].getSelectedIndex()
416 self.singleUpdate(cur_idx-1)
417 elif result[1] == "setup":
418 from RSSSetup import RSSSetup
420 self.session.openWithCallback(
423 rssPoller=self.rssPoller
425 elif result[1] == "close":
429 current_entry = self["content"].getCurrent()
432 self["content"].setList(self.feeds)
434 self["content"].moveToEntry(current_entry)
439 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
441 def previousFeed(self):
442 self["content"].down()
443 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
445 def showCurrentEntry(self):
446 current_entry = self["content"].getCurrent()
447 self.session.openWithCallback(
452 rssPoller=self.rssPoller,
453 id=self["content"].getSelectedIndex()
456 def selectEnclosure(self):
457 # Build a list of all enclosures in this feed
459 for entry in self["content"].getCurrent().history:
460 enclosures.extend(entry[3])
461 RSSBaseView.selectEnclosure(self, enclosures)