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 RSSFeed import BaseFeed
15 from RSSList import RSSFeedList, RSSEntryList
16 from RSSSetup import RSSSetup
18 class RSSBaseView(Screen):
19 """Base Screen for all Screens used in SimpleRSS"""
21 def __init__(self, session, poller, parent=None):
22 Screen.__init__(self, session)
23 self.rssPoller = poller
24 self.pollDialog = None
27 def errorPolling(self, errmsg = ""):
28 # An error occured while polling
31 "Error while parsing Feed, this usually means there is something wrong with it.",
32 type = MessageBox.TYPE_ERROR,
36 # Don't show "we're updating"-dialog any longer
38 self.pollDialog.close()
39 self.pollDialog = None
41 def singleUpdate(self, feedid, errback = None):
42 # Don't do anything if we have no poller
43 if self.rssPoller is None:
46 # Default errorback to self.errorPolling
47 # If an empty errorback is wanted the Screen needs to provide it
49 errback = self.errorPolling
52 self.rssPoller.singlePoll(feedid, callback=True, errorback=errback)
54 # Open Dialog and save locally
55 self.pollDialog = self.session.open(
57 "Update is being done in Background.\nContents will automatically be updated when it's done.",
58 type = MessageBox.TYPE_INFO,
62 def selectEnclosure(self, enclosures):
64 if enclosures is None:
67 if not openList(self.session, enclosures):
70 "Found no Enclosure we can display.",
71 type = MessageBox.TYPE_INFO,
75 class RSSEntryView(RSSBaseView):
76 """Shows a RSS Item"""
78 <screen position="100,100" size="460,420" title="Simple RSS Reader" >
79 <widget name="info" position="0,0" size="460, 20" halign="right" font="Regular; 18" />
80 <widget name="content" position="0,20" size="460,400" font="Regular; 22" />
83 def __init__(self, session, data, feedTitle="", cur_idx=None, entries=None, parent=None):
84 RSSBaseView.__init__(self, session, None, parent)
87 self.feedTitle = feedTitle
88 self.cur_idx = cur_idx
89 self.entries = entries
91 if cur_idx is not None and entries is not None:
92 self["info"] = Label("Entry %s/%s" % (cur_idx+1, entries))
94 self["info"] = Label()
97 self["content"] = ScrollLabel("\n\n".join([data[0], data[2], " ".join([str(len(data[3])), "Enclosures"])]))
99 self["content"] = ScrollLabel()
101 self["actions"] = ActionMap([ "OkCancelActions", "ChannelSelectBaseActions", "ColorActions", "DirectionActions" ],
103 "cancel": self.close,
104 "ok": self.selectEnclosure,
105 "yellow": self.selectEnclosure,
109 "left": self.previous,
110 "nextBouquet": self.nextFeed,
111 "prevBouquet": self.previousFeed,
114 self.onLayoutFinish.append(self.setConditionalTitle)
116 def setConditionalTitle(self):
117 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
120 self["content"].pageUp()
123 self["content"].pageDown()
126 if self.parent is not None:
127 (self.data, self.cur_idx, self.entries) = self.parent.nextEntry()
131 if self.parent is not None:
132 (self.data, self.cur_idx, self.entries) = self.parent.previousEntry()
137 if self.parent is not None:
138 result = self.parent.next()
139 self.feedTitle = result[0]
140 self.entries = len(result[1])
143 self.data = result[1][0]
147 self.setConditionalTitle()
150 def previousFeed(self):
152 if self.parent is not None:
153 result = self.parent.previous()
154 self.feedTitle = result[0]
155 self.entries = len(result[1])
158 self.data = result[1][0]
162 self.setConditionalTitle()
165 def setContent(self):
166 if self.cur_idx is not None and self.entries is not None:
167 self["info"].setText("Entry %s/%s" % (self.cur_idx+1, self.entries))
169 self["info"].setText("")
170 if self.data is not None:
171 self["content"].setText("\n\n".join([self.data[0], self.data[2], " ".join([str(len(self.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"""
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, data, feedTitle = "", newItems=False, parent=None, rssPoller=None, id = None):
189 RSSBaseView.__init__(self, session, rssPoller, parent)
192 self.feedTitle = feedTitle
193 self.newItems = newItems
196 self["content"] = RSSEntryList(self.data)
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.timeout.get().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)
234 self.rssPoller.addCallback(self.pollCallback)
237 if self.timer is not None:
238 self.timer.timeout.get().remove(self.timerTick)
240 self.rssPoller.removeCallback(self.pollCallback)
242 def pollCallback(self, id = None):
243 print "[SimpleRSS] SimpleRSSFeed called back"
245 # TODO: do we really need this?
246 current_entry = self["content"].getCurrentEntry()
247 self["content"].moveToEntry(current_entry)
249 self["content"].invalidate()
250 self.setConditionalTitle()
253 def setConditionalTitle(self):
254 if not self.newItems:
255 self.setTitle(': '.join(["Simple RSS Reader", self.feedTitle]))
257 self.setTitle("Simple RSS Reader: New Items")
259 def updateInfo(self):
260 current_entry = self["content"].getCurrentEntry()
262 self["summary"].setText(current_entry[2])
264 cur_idx = self["content"].getCurrentIndex()
265 self["info"].setText("Entry %s/%s" % (cur_idx+1, len(self.data)))
267 self["summary"].setText("Feed is empty.")
268 self["info"].setText("")
272 self.singleUpdate(self.id-1)
275 self["content"].moveDown()
276 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.data))
278 def previousEntry(self):
279 self["content"].moveUp()
280 return (self["content"].getCurrentEntry(), self["content"].getCurrentIndex(), len(self.data))
282 # TODO: Fix moving back to previously marked entry (same goes for self.previous)
285 if self.parent is not None:
286 result = self.parent.nextFeed()
287 (self.feedTitle, self.data, self.id) = result
288 #current_entry = self["content"].getCurrentEntry()
289 self["content"].l.setList(self.data) # Update list
290 self["content"].moveToIndex(0)
291 #self["content"].moveToEntry(current_entry)
292 self.updateInfo() # In case entry is no longer in history
293 self.setConditionalTitle() # Update title
295 return (self.feedTitle, self.data, self.id)
299 if self.parent is not None:
300 result = self.parent.previousFeed()
301 (self.feedTitle, self.data, self.id) = result
302 #current_entry = self["content"].getCurrentEntry()
303 self["content"].l.setList(self.data) # Update list
304 self["content"].moveToIndex(0)
305 #self["content"].moveToEntry(current_entry)
306 self.updateInfo() # In case entry is no longer in history
307 self.setConditionalTitle() # Update title
309 return (self.feedTitle, self.data, self.id)
311 def checkEmpty(self):
312 if self.id > 0 and not len(self.data):
313 self.singleUpdate(self.id-1)
315 def showCurrentEntry(self):
316 current_entry = self["content"].getCurrentEntry()
317 if current_entry is None: # empty list
320 self.session.openWithCallback(
324 cur_idx=self["content"].getCurrentIndex(),
325 entries=len(self.data),
326 feedTitle=self.feedTitle,
330 def selectEnclosure(self):
331 current_entry = self["content"].getCurrentEntry()
332 if current_entry is None: # empty list
335 RSSBaseView.selectEnclosure(self, current_entry[3])
337 class RSSOverview(RSSBaseView):
338 """Shows an Overview over all RSS-Feeds known to rssPoller"""
340 <screen position="100,100" size="460,415" title="Simple RSS Reader" >
341 <widget name="info" position="0,0" size="460,20" halign="right" font="Regular; 18" />
342 <widget name="content" position="0,20" size="460,300" scrollbarMode="showOnDemand" />
343 <widget name="summary" position="0,320" size="460,95" font="Regular;16" />
346 def __init__(self, session, poller):
347 RSSBaseView.__init__(self, session, poller)
349 self["actions"] = ActionMap([ "OkCancelActions", "MenuActions", "ColorActions" ],
351 "ok": self.showCurrentEntry,
352 "cancel": self.close,
354 "yellow": self.selectEnclosure,
359 # We always have at least "New Items"-Feed
360 self["content"] = RSSFeedList(self.feeds)
361 self["summary"] = Label(' '.join([str(len(self.feeds[0][0].history)), "Entries"]))
362 self["info"] = Label("Feed 1/%s" % len(self.feeds))
364 self["content"].connectSelChanged(self.updateInfo)
365 self.onLayoutFinish.append(self.__show)
366 self.onClose.append(self.__close)
369 self.rssPoller.addCallback(self.pollCallback)
372 self.rssPoller.removeCallback(self.pollCallback)
375 # Build virtual "new item"-Feed
376 newItemFeed = BaseFeed("", False)
377 newItemFeed.title = "New Items"
378 newItemFeed.description = "New Items since last Auto-Update"
379 newItemFeed.history = self.rssPoller.new_items
381 # Feedlist contains our virtual Feed and all real ones
382 self.feeds = [(newItemFeed,)]
383 self.feeds.extend([(feed,) for feed in self.rssPoller.feeds])
385 def pollCallback(self, id = None):
386 print "[SimpleRSS] SimpleRSS called back"
388 self["content"].invalidate()
390 def updateInfo(self):
391 current_entry = self["content"].getCurrentEntry()
392 self["summary"].setText(' '.join([str(len(current_entry.history)), "Entries"]))
393 self["info"].setText("Feed %s/%s" % (self["content"].getCurrentIndex()+1, len(self.feeds)))
396 cur_idx = self["content"].getCurrentIndex()
399 (_("Update Feed"), "update"),
400 (_("Setup"), "setup"),
401 (_("Close"), "close")
405 (_("Setup"), "setup"),
406 (_("Close"), "close")
408 self.session.openWithCallback(
415 def menuChoice(self, result):
417 if result[1] == "update":
418 cur_idx = self["content"].getCurrentIndex()
420 self.singleUpdate(cur_idx-1)
421 elif result[1] == "setup":
422 self.session.openWithCallback(
425 rssPoller=self.rssPoller
427 elif result[1] == "close":
431 current_entry = self["content"].getCurrentEntry()
434 self["content"].l.setList(self.feeds)
436 self["content"].moveToEntry(current_entry)
440 self["content"].moveUp()
441 current_entry = self["content"].getCurrentEntry()
442 return (current_entry.title, current_entry.history, self["content"].getCurrentIndex())
444 def previousFeed(self):
445 self["content"].moveDown()
446 current_entry = self["content"].getCurrentEntry()
447 return (current_entry.title, current_entry.history, self["content"].getCurrentIndex())
449 def showCurrentEntry(self):
450 current_entry = self["content"].getCurrentEntry()
451 self.session.openWithCallback(
454 current_entry.history,
456 feedTitle=current_entry.title,
457 rssPoller=self.rssPoller,
458 id=self["content"].getCurrentIndex()
461 def selectEnclosure(self):
462 # Build a list of all enclosures in this feed
464 for entry in self["content"].getCurrentEntry().history:
465 enclosures.extend(entry[3])
466 RSSBaseView.selectEnclosure(self, enclosures)