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.ScrollLabel import ScrollLabel
11 from Components.Sources.List import List
12 from Components.Sources.StaticText import StaticText
14 from RSSList import RSSFeedList
16 class RSSSummary(Screen):
18 <screen position="0,0" size="132,64">
19 <widget source="parent.Title" render="Label" position="6,4" size="120,21" font="Regular;18" />
20 <widget source="entry" render="Label" position="6,25" size="120,21" font="Regular;16" />
21 <widget source="global.CurrentTime" render="Label" position="56,46" size="82,18" font="Regular;16" >
22 <convert type="ClockToText">WithSeconds</convert>
26 def __init__(self, session, parent):
27 Screen.__init__(self, session, parent = parent)
28 self["entry"] = StaticText("")
29 parent.onChangedEntry.append(self.selectionChanged)
30 self.onShow.append(parent.updateInfo)
31 self.onClose.append(self.removeWatcher)
33 def removeWatcher(self):
34 self.parent.onChangedEntry.remove(self.selectionChanged)
36 def selectionChanged(self, text):
37 self["entry"].text = text
39 class RSSBaseView(Screen):
40 """Base Screen for all Screens used in SimpleRSS"""
42 def __init__(self, session, poller, parent = None):
43 Screen.__init__(self, session, parent)
44 self.onChangedEntry = []
45 self.rssPoller = poller
46 self.pollDialog = None
48 def createSummary(self):
51 def errorPolling(self, errmsg = ""):
52 # An error occured while polling
55 _("Error while parsing Feed, this usually means there is something wrong with it."),
56 type = MessageBox.TYPE_ERROR,
60 # Don't show "we're updating"-dialog any longer
62 self.pollDialog.close()
63 self.pollDialog = None
65 def singleUpdate(self, feedid, errback = None):
66 # Don't do anything if we have no poller
67 if self.rssPoller is None:
70 # Default errorback to self.errorPolling
71 # If an empty errorback is wanted the Screen needs to provide it
73 errback = self.errorPolling
76 self.rssPoller.singlePoll(feedid, callback=True, errorback=errback)
78 # Open Dialog and save locally
79 self.pollDialog = self.session.open(
81 _("Update is being done in Background.\nContents will automatically be updated when it's done."),
82 type = MessageBox.TYPE_INFO,
86 def selectEnclosure(self, enclosures):
88 if enclosures is None:
91 from Components.Scanner import openList
93 if not openList(self.session, enclosures):
96 _("Found no Enclosure we can display."),
97 type = MessageBox.TYPE_INFO,
101 class RSSEntryView(RSSBaseView):
102 """Shows a RSS Item"""
105 <screen position="center,center" size="460,420" title="Simple RSS Reader" >
106 <widget source="info" render="Label" position="0,0" size="460, 20" halign="right" font="Regular; 18" />
107 <widget name="content" position="0,20" size="460,400" font="Regular; 22" />
110 def __init__(self, session, data, feedTitle="", cur_idx=None, entries=None, parent=None):
111 RSSBaseView.__init__(self, session, None, parent)
114 self.feedTitle = feedTitle
115 self.cur_idx = cur_idx
116 self.entries = entries
118 if cur_idx is not None and entries is not None:
119 self["info"] = StaticText(_("Entry %s/%s") % (cur_idx+1, entries))
121 self["info"] = StaticText()
124 self["content"] = ScrollLabel(''.join((data[0], '\n\n', data[2], '\n\n', str(len(data[3])), ' ', _("Enclosures"))))
126 self["content"] = ScrollLabel()
128 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "ColorActions", "DirectionActions" ],
130 "cancel": self.close,
131 "ok": self.selectEnclosure,
132 "yellow": self.selectEnclosure,
136 "left": self.previous,
137 "nextBouquet": self.nextFeed,
138 "prevBouquet": self.previousFeed,
141 self.onLayoutFinish.append(self.setConditionalTitle)
143 def setConditionalTitle(self):
144 self.setTitle(_("Simple RSS Reader: %s") % (self.feedTitle))
146 def updateInfo(self):
150 text = _("No such Item.")
152 for x in self.onChangedEntry:
159 self["content"].pageUp()
162 self["content"].pageDown()
165 if self.parent is not None:
166 (self.data, self.cur_idx, self.entries) = self.parent.nextEntry()
170 if self.parent is not None:
171 (self.data, self.cur_idx, self.entries) = self.parent.previousEntry()
176 if self.parent is not None:
177 result = self.parent.next()
178 self.feedTitle = result[0]
179 self.entries = len(result[1])
182 self.data = result[1][0]
186 self.setConditionalTitle()
189 def previousFeed(self):
191 if self.parent is not None:
192 result = self.parent.previous()
193 self.feedTitle = result[0]
194 self.entries = len(result[1])
197 self.data = result[1][0]
201 self.setConditionalTitle()
204 def setContent(self):
205 if self.cur_idx is not None and self.entries is not None:
206 self["info"].text = _("Entry %s/%s") % (self.cur_idx+1, self.entries)
208 self["info"].text = ""
211 self["content"].setText(''.join((data[0], '\n\n', data[2], '\n\n', str(len(data[3])), ' ', _("Enclosures"))))
213 self["content"].setText(_("No such Item."))
216 def selectEnclosure(self):
217 if self.data is not None:
218 RSSBaseView.selectEnclosure(self, self.data[3])
220 class RSSFeedView(RSSBaseView):
221 """Shows a RSS-Feed"""
224 <screen position="center,center" size="460,415" title="Simple RSS Reader" >
225 <widget source="info" render="Label" position="0,0" size="460,20" halign="right" font="Regular; 18" />
226 <widget source="content" render="Listbox" position="0,20" size="460,300" scrollbarMode="showOnDemand">
227 <convert type="TemplatedMultiContent">
229 MultiContentEntryText(pos=(0, 3), size=(460, 294), font=0, flags = RT_HALIGN_LEFT|RT_WRAP, text = 0)
231 "fonts": [gFont("Regular", 22)],
236 <widget source="summary" render="Label" position="0,320" size="460,95" font="Regular;16" />
239 def __init__(self, session, feed=None, newItems=False, parent=None, rssPoller=None,id=None):
240 RSSBaseView.__init__(self, session, rssPoller, parent)
243 self.newItems = newItems
246 self["content"] = List(self.feed.history)
247 self["summary"] = StaticText()
248 self["info"] = StaticText()
251 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "MenuActions", "ColorActions" ],
253 "ok": self.showCurrentEntry,
254 "cancel": self.close,
255 "nextBouquet": self.next,
256 "prevBouquet": self.previous,
258 "yellow": self.selectEnclosure,
260 self.onLayoutFinish.append(self.__show)
261 self.onClose.append(self.__close)
265 self["actions"] = ActionMap([ "OkCancelActions" ],
267 "cancel": self.close,
270 self.timer = eTimer()
271 self.timer.callback.append(self.timerTick)
272 self.onExecBegin.append(self.startTimer)
274 self["content"].onSelectionChanged.append(self.updateInfo)
275 self.onLayoutFinish.extend((
277 self.setConditionalTitle
280 def startTimer(self):
281 self.timer.startLongTimer(5)
284 self.timer.callback.remove(self.timerTick)
289 self.rssPoller.addCallback(self.pollCallback)
292 if self.timer is not None:
293 self.timer.callback.remove(self.timerTick)
295 self.rssPoller.removeCallback(self.pollCallback)
297 def pollCallback(self, id = None):
298 print "[SimpleRSS] SimpleRSSFeed called back"
300 if id is None or id+1 == self.id:
301 self["content"].updateList(self.feed.history)
302 self.setConditionalTitle()
305 def setConditionalTitle(self):
306 self.setTitle(_("Simple RSS Reader: %s") % (self.feed.title))
308 def updateInfo(self):
309 current_entry = self["content"].current
311 self["summary"].text = current_entry[2]
313 cur_idx = self["content"].index
314 self["info"].text = _("Entry %s/%s") % (cur_idx+1, len(self.feed.history))
315 summary_text = current_entry[0]
317 self["summary"].text = _("Feed is empty.")
318 self["info"].text = ""
319 summary_text = _("Feed is empty.")
321 for x in self.onChangedEntry:
329 self.singleUpdate(self.id-1)
332 self["content"].selectNext()
333 return (self["content"].current, self["content"].index, len(self.feed.history))
335 def previousEntry(self):
336 self["content"].selectPrevious()
337 return (self["content"].current, self["content"].index, len(self.feed.history))
341 if self.parent is not None:
342 (self.feed, self.id) = self.parent.nextFeed()
343 self["content"].list = self.feed.history
344 self["content"].index = 0
346 self.setConditionalTitle() # Update title
347 return (self.feed.title, self.feed.history, self.id)
348 return (self.feed.title, self.feed.history, self.id)
352 if self.parent is not None:
353 (self.feed, self.id) = self.parent.previousFeed()
354 self["content"].list = self.feed.history
355 self["content"].index = 0
357 self.setConditionalTitle() # Update title
358 return (self.feed.title, self.feed.history, self.id)
359 return (self.feed.title, self.feed.history, self.id)
361 def checkEmpty(self):
362 if self.id > 0 and not len(self.feed.history):
363 self.singleUpdate(self.id-1)
365 def showCurrentEntry(self):
366 current_entry = self["content"].current
367 if not current_entry: # empty list
370 self.session.openWithCallback(
374 cur_idx = self["content"].index,
375 entries = len(self.feed.history),
376 feedTitle = self.feed.title,
380 def selectEnclosure(self):
381 current_entry = self["content"].current
382 if not current_entry: # empty list
385 RSSBaseView.selectEnclosure(self, current_entry[3])
387 class RSSOverview(RSSBaseView):
388 """Shows an Overview over all RSS-Feeds known to rssPoller"""
391 <screen position="center,center" size="460,415" title="Simple RSS Reader" >
392 <widget source="info" render="Label" position="0,0" size="460,20" halign="right" font="Regular; 18" />
393 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
394 <widget source="summary" render="Label" position="0,320" size="460,95" font="Regular;16" />
397 def __init__(self, session, poller):
398 RSSBaseView.__init__(self, session, poller)
400 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
402 "ok": self.showCurrentEntry,
403 "cancel": self.close,
405 "yellow": self.selectEnclosure,
410 # We always have at least "New Items"-Feed
411 self["content"] = RSSFeedList(self.feeds)
412 self["summary"] = StaticText(' '.join((str(len(self.feeds[0][0].history)), _("Entries"))))
413 self["info"] = StaticText(_("Feed %s/%s") % (1, len(self.feeds)))
415 self["content"].connectSelChanged(self.updateInfo)
416 self.onLayoutFinish.append(self.__show)
417 self.onClose.append(self.__close)
420 self.rssPoller.addCallback(self.pollCallback)
421 self.setTitle(_("Simple RSS Reader"))
424 self.rssPoller.removeCallback(self.pollCallback)
427 # Feedlist contains our virtual Feed and all real ones
428 self.feeds = [(self.rssPoller.newItemFeed,)]
429 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
431 def pollCallback(self, id = None):
432 print "[SimpleRSS] SimpleRSS called back"
434 self["content"].setList(self.feeds)
436 self["content"].invalidate()
438 def updateInfo(self):
439 current_entry = self["content"].getCurrent()
440 self["summary"].text = ' '.join((str(len(current_entry.history)), _("Entries")))
441 self["info"].text = _("Feed %s/%s") % (self["content"].getSelectedIndex()+1, len(self.feeds))
442 summary_text = current_entry.title
444 for x in self.onChangedEntry:
451 from Screens.ChoiceBox import ChoiceBox
453 cur_idx = self["content"].getSelectedIndex()
456 (_("Update Feed"), "update"),
457 (_("Setup"), "setup"),
458 (_("Close"), "close")
462 (_("Setup"), "setup"),
463 (_("Close"), "close")
466 self.session.openWithCallback(
473 def menuChoice(self, result):
475 if result[1] == "update":
476 cur_idx = self["content"].getSelectedIndex()
478 self.singleUpdate(cur_idx-1)
479 elif result[1] == "setup":
480 from RSSSetup import RSSSetup
482 self.session.openWithCallback(
485 rssPoller=self.rssPoller
487 elif result[1] == "close":
491 current_entry = self["content"].getCurrent()
494 self["content"].setList(self.feeds)
496 self["content"].moveToEntry(current_entry)
501 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
503 def previousFeed(self):
504 self["content"].down()
505 return (self["content"].getCurrent(), self["content"].getSelectedIndex())
507 def showCurrentEntry(self):
508 current_entry = self["content"].getCurrent()
509 self.session.openWithCallback(
514 rssPoller=self.rssPoller,
515 id=self["content"].getSelectedIndex()
518 def selectEnclosure(self):
519 # Build a list of all enclosures in this feed
521 for entry in self["content"].getCurrent().history:
522 enclosures.extend(entry[3])
523 RSSBaseView.selectEnclosure(self, enclosures)