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(''.join((data[0], '\n\n', data[2], '\n\n', 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("")
171 self["content"].setText(''.join((data[0], '\n\n', data[2], '\n\n', str(len(data[3])), ' ', _("Enclosures"))))
173 self["content"].setText(_("No such Item."))
175 def selectEnclosure(self):
176 if self.data is not None:
177 RSSBaseView.selectEnclosure(self, self.data[3])
179 class RSSFeedView(RSSBaseView):
180 """Shows a RSS-Feed"""
183 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
184 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
185 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
186 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
189 def __init__(self, session, feed=None, newItems=False, parent=None, rssPoller=None,id=None):
190 RSSBaseView.__init__(self, session, rssPoller, parent)
193 self.newItems = newItems
196 self["content"] = RSSEntryList(self.feed.history)
197 self["summary"] = Label()
198 self["info"] = Label()
201 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
203 "ok": self.showCurrentEntry,
204 "cancel": self.close,
205 "nextBouquet": self.next,
206 "prevBouquet": self.previous,
208 "yellow": self.selectEnclosure,
210 self.onLayoutFinish.append(self.__show)
211 self.onClose.append(self.__close)
215 self["actions"] = ActionMap([ "OkCancelActions" ],
217 "cancel": self.close,
220 self.timer = eTimer()
221 self.timer.callback.append(self.timerTick)
222 self.onExecBegin.append(self.startTimer)
224 self["content"].connectSelChanged(self.updateInfo)
225 self.onLayoutFinish.extend([self.updateInfo, self.setConditionalTitle])
227 def startTimer(self):
228 self.timer.startLongTimer(5)
231 self.timer.callback.remove(self.timerTick)
236 self.rssPoller.addCallback(self.pollCallback)
239 if self.timer is not None:
240 self.timer.callback.remove(self.timerTick)
242 self.rssPoller.removeCallback(self.pollCallback)
244 def pollCallback(self, id = None):
245 print "[SimpleRSS] SimpleRSSFeed called back"
247 if id is None or id+1 == self.id:
248 # TODO: do we really need this?
249 current_entry = self["content"].getCurrent()
250 self["content"].moveToEntry(current_entry)
252 self["content"].invalidate()
253 self.setConditionalTitle()
256 def setConditionalTitle(self):
257 self.setTitle(_("Simple RSS Reader: %s") % (self.feed.title))
259 def updateInfo(self):
260 current_entry = self["content"].getCurrent()
262 self["summary"].setText(current_entry[2])
264 cur_idx = self["content"].getSelectedIndex()
265 self["info"].setText(_("Entry %s/%s") % (cur_idx+1, len(self.feed.history)))
267 self["summary"].setText(_("Feed is empty."))
268 self["info"].setText("")
272 self.singleUpdate(self.id-1)
275 self["content"].down()
276 return (self["content"].getCurrent(), self["content"].getSelectedIndex(), len(self.feed.history))
278 def previousEntry(self):
280 return (self["content"].getCurrent(), self["content"].getSelectedIndex(), len(self.feed.history))
282 # TODO: Fix moving back to previously marked entry (same goes for self.previous)
285 if self.parent is not None:
286 (self.feed, self.id) = self.parent.nextFeed()
287 #current_entry = self["content"].getCurrent()
288 self["content"].setList(self.feed.history) # Update list
289 self["content"].moveToIndex(0)
290 #self["content"].moveToEntry(current_entry)
291 self.updateInfo() # In case entry is no longer in history
292 self.setConditionalTitle() # Update title
293 return (self.feed.title, self.feed.history, self.id)
294 return (self.feed.title, self.feed.history, self.id)
298 if self.parent is not None:
299 (self.feed, self.id) = self.parent.previousFeed()
300 #current_entry = self["content"].getCurrent()
301 self["content"].setList(self.feed.history) # Update list
302 self["content"].moveToIndex(0)
303 #self["content"].moveToEntry(current_entry)
304 self.updateInfo() # In case entry is no longer in history
305 self.setConditionalTitle() # Update title
306 return (self.feed.title, self.feed.history, self.id)
307 return (self.feed.title, self.feed.history, self.id)
309 def checkEmpty(self):
310 if self.id > 0 and not len(self.feed.history):
311 self.singleUpdate(self.id-1)
313 def showCurrentEntry(self):
314 current_entry = self["content"].getCurrent()
315 if current_entry is None: # empty list
318 self.session.openWithCallback(
322 cur_idx=self["content"].getSelectedIndex(),
323 entries=len(self.feed.history),
324 feedTitle=self.feed.title,
328 def selectEnclosure(self):
329 current_entry = self["content"].getCurrent()
330 if current_entry is None: # empty list
333 RSSBaseView.selectEnclosure(self, current_entry[3])
335 class RSSOverview(RSSBaseView):
336 """Shows an Overview over all RSS-Feeds known to rssPoller"""
339 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
340 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
341 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
342 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
345 def __init__(self, session, poller):
346 RSSBaseView.__init__(self, session, poller)
348 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
350 "ok": self.showCurrentEntry,
351 "cancel": self.close,
353 "yellow": self.selectEnclosure,
358 # We always have at least "New Items"-Feed
359 self["content"] = RSSFeedList(self.feeds)
360 self["summary"] = Label(' '.join((str(len(self.feeds[0][0].history)), _("Entries"))))
361 self["info"] = Label(_("Feed %s/%s") % (1, len(self.feeds)))
363 self["content"].connectSelChanged(self.updateInfo)
364 self.onLayoutFinish.append(self.__show)
365 self.onClose.append(self.__close)
368 self.rssPoller.addCallback(self.pollCallback)
369 self.setTitle(_("Simple RSS Reader"))
372 self.rssPoller.removeCallback(self.pollCallback)
375 # Feedlist contains our virtual Feed and all real ones
376 self.feeds = [(self.rssPoller.newItemFeed,)]
377 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
379 def pollCallback(self, id = None):
380 print "[SimpleRSS] SimpleRSS called back"
382 self["content"].invalidate()
384 def updateInfo(self):
385 current_entry = self["content"].getCurrent()
386 self["summary"].setText(' '.join((str(len(current_entry.history)), _("Entries"))))
387 self["info"].setText(_("Feed %s/%s") % (self["content"].getSelectedIndex()+1, len(self.feeds)))
390 from Screens.ChoiceBox import ChoiceBox
392 cur_idx = self["content"].getSelectedIndex()
395 (_("Update Feed"), "update"),
396 (_("Setup"), "setup"),
397 (_("Close"), "close")
401 (_("Setup"), "setup"),
402 (_("Close"), "close")
405 self.session.openWithCallback(
412 def menuChoice(self, result):
414 if result[1] == "update":
415 cur_idx = self["content"].getSelectedIndex()
417 self.singleUpdate(cur_idx-1)
418 elif result[1] == "setup":
419 from RSSSetup import RSSSetup
421 self.session.openWithCallback(
424 rssPoller=self.rssPoller
426 elif result[1] == "close":
430 current_entry = self["content"].getCurrent()
433 self["content"].setList(self.feeds)
435 self["content"].moveToEntry(current_entry)
440 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
442 def previousFeed(self):
443 self["content"].down()
444 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
446 def showCurrentEntry(self):
447 current_entry = self["content"].getCurrent()
448 self.session.openWithCallback(
453 rssPoller=self.rssPoller,
454 id=self["content"].getSelectedIndex()
457 def selectEnclosure(self):
458 # Build a list of all enclosures in this feed
460 for entry in self["content"].getCurrent().history:
461 enclosures.extend(entry[3])
462 RSSBaseView.selectEnclosure(self, enclosures)