1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2011 Christian Weiske <cweiske@cweiske.de>
4 # License: GPLv3 or later
8 from Screens.Screen import Screen
9 from Screens.HelpMenu import HelpableScreen
10 from Components.Label import Label
11 from Components.ScrollLabel import ScrollLabel
12 from Components.ActionMap import ActionMap
13 from Components.Sources.StaticText import StaticText
14 from Tools import Directories
15 from twisted.web import client
16 from twisted.web.client import _makeGetterFactory, HTTPClientFactory
17 from enigma import gFont
20 from config import createPage, loadDefaultPageOptions, feedPagesToConfig, savePageConfig
21 from Components.config import config
25 class CurlyTx(Screen, HelpableScreen):
27 <screen name="CurlyTx" position="center,center" size="560,430" title="CurlyTx" >
28 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
29 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
30 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
31 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
32 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" />
33 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" />
34 <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" />
35 <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" />
36 <widget name="text" position="5,45" size="550,380" font="Console;20" />
42 httpGetterFactory = None
43 showingHeaders = False
44 staticPageFeedFile = 'curlytx-pagefeed.xml'
46 def __init__(self, session, args = None):
47 #self.skin = CurlyTx.skin
48 Screen.__init__(self, session)
49 HelpableScreen.__init__(self)
50 #self.skinName = [ "CurlyTx", "Setup" ]
52 self["text"] = ScrollLabel("foo")
54 self["key_red"] = StaticText(_("Settings"))
55 self["key_green"] = StaticText(_("Reload"))
56 self["key_yellow"] = StaticText(_("Prev"))
57 self["key_blue"] = StaticText(_("Next"))
60 self["actions"] = ActionMap(
61 ["WizardActions", "ColorActions", "InputActions", "InfobarEPGActions"], {
65 "down": self.pageDown,
67 "red": self.showSettings,
69 "yellow": self.prevPage,
70 "blue": self.nextPage,
72 "showEventInfo": self.showHeader
77 self.onFirstExecBegin.append(self.afterLayout)
79 def afterLayout(self):
81 self.loadStaticConfig()
82 self.loadUrl(config.plugins.CurlyTx.defaultPage.value)
85 self.helpList.append((
86 self["actions"], "WizardActions",
87 [("up", _("Scroll page contents up"))]))
88 self.helpList.append((
89 self["actions"], "WizardActions",
90 [("down", _("Scroll page contents down"))]))
91 self.helpList.append((
92 self["actions"], "InfobarEPGActions",
93 [("showEventInfo", _("Show HTTP response headers"))]))
94 self.helpList.append((
95 self["actions"], "ColorActions",
96 [("red", _("Show program settings"))]))
97 self.helpList.append((
98 self["actions"], "ColorActions",
99 [("green", _("Reload current page URL"))]))
100 self.helpList.append((
101 self["actions"], "ColorActions",
102 [("yellow", _("Switch to next configured page URL"))]))
103 self.helpList.append((
104 self["actions"], "ColorActions",
105 [("blue", _("Switch to previous configured page URL"))]))
106 self.helpList.append((
107 self["actions"], "WizardActions",
108 [("ok", _("Close window"))]))
109 self.helpList.append((
110 self["actions"], "WizardActions",
111 [("back", _("Close window"))]))
113 def loadButtons(self):
114 pageCount = len(config.plugins.CurlyTx.pages)
116 self["key_green"].setText("")
117 self["key_yellow"].setText("")
118 self["key_blue"].setText("")
120 self["key_green"].setText(_("Reload"))
121 self["key_yellow"].setText("")
122 self["key_blue"].setText("")
124 self["key_green"].setText(_("Reload"))
125 self["key_yellow"].setText(_("Prev"))
126 self["key_blue"].setText(_("Next"))
129 self["text"].pageUp()
132 self["text"].pageDown()
135 if self.currentPage == None:
138 pageId = self.currentPage - 1
140 pageId = len(config.plugins.CurlyTx.pages) - 1
144 if self.currentPage == None:
147 pageId = self.currentPage + 1
148 if pageId > len(config.plugins.CurlyTx.pages) - 1:
153 if self.currentPage == None:
156 self.loadUrl(self.currentPage)
158 def loadUrl(self, pageId):
159 self.httpGetterFactory = None
164 cfg = config.plugins.CurlyTx
165 pageCount = len(cfg.pages)
167 if pageId > (pageCount - 1):
168 if len(cfg.pages) == 0:
171 self["text"].setText(_("Invalid page") + " " + pageId);
174 url = cfg.pages[pageId].uri.value
175 title = cfg.pages[pageId].title.value
178 title = "{0} [{1}/{2}]".format(title, pageId + 1, pageCount)
180 self.currentPage = pageId
181 self.currentUrl = url
182 self.currentFontSize = cfg.pages[pageId].fontSize.value
186 self["text"].setText(_("Loading ...") + "\n" + url);
188 if (url.startswith('file://')):
189 self.loadLocalFile(url)
191 self.getPageWebClient(url).addCallback(self.urlLoaded).addErrback(self.urlFailed, url)
193 def loadLocalFile(self, url):
195 if not os.path.exists(file):
196 self.showFail('File does not exist', file)
199 with open(file, 'r') as f:
200 self.urlLoaded(f.read())
202 def setTextFont(self):
203 if self["text"].long_text is not None:
204 self["text"].long_text.setFont(gFont("Console", self.currentFontSize))
206 def urlLoaded(self, html):
207 self["text"].setText(html)
209 def urlFailed(self, error, url):
210 self.showFail(error.getErrorMessage(), url)
212 def showFail(self, message, url):
213 self["text"].setText(
214 _("Error fetching URL:") + "\n " + message
218 def loadNoPage(self):
219 self["text"].setText(_("Go and add a page in the settings"));
221 def showHeader(self):
222 if not self.httpGetterFactory:
225 if self.showingHeaders:
226 self["text"].setText(self.pageContent)
227 self.pageContent = None
228 self.showingHeaders = False
229 elif self.httpGetterFactory.response_headers:
230 headers = _("HTTP response headers for") + "\n" + self.currentUrl + "\n\n"
231 for (k, v) in self.httpGetterFactory.response_headers.items():
232 headers += k + ": " + ("\n" + k + ": ").join(v) + "\n"
233 self.pageContent = self["text"].getText()
234 self["text"].setText(headers)
235 self.showingHeaders = True
237 def showSettings(self):
238 from CurlyTxSettings import CurlyTxSettings
239 self.session.openWithCallback(self.onSettingsChanged, CurlyTxSettings)
241 def onSettingsChanged(self):
243 if len(config.plugins.CurlyTx.pages) == 0:
244 self.currentPage = None
245 self.loadUrl(self.currentPage)
246 elif self.currentPage == None:
248 self.loadUrl(self.currentPage)
251 def getPageWebClient(self, url, contextFactory=None, *args, **kwargs):
253 Download a web page as a string.
255 COPY OF twisted.web.client.getPage to store the factory
257 Download a page. Return a deferred, which will callback with a
258 page (as a string) or errback with a description of the error.
260 See L{HTTPClientFactory} to see what extra arguments can be passed.
262 self.httpGetterFactory = _makeGetterFactory(
265 contextFactory=contextFactory,
267 return self.httpGetterFactory.deferred
269 def loadStaticConfig(self):
271 Always try to load the static config file from
272 /etc/enigma2/curlytx-pagefeed.xml
274 staticFeedPath = Directories.resolveFilename(Directories.SCOPE_CONFIG, self.staticPageFeedFile)
275 if not os.path.exists(staticFeedPath):
278 from AtomFeed import AtomFeed
280 'file://' + staticFeedPath,
281 self.saveStaticConfig, self.loadStaticConfigFail
284 def loadStaticConfigFail(self, errorMessage):
285 """ Loading the page url feed failed somehow """
286 from Screens.MessageBox import MessageBox
289 _("Error loading page feed:") + "\n\n" + str(errorMessage),
290 type = MessageBox.TYPE_ERROR
293 def saveStaticConfig(self, pages):
294 feedPagesToConfig(pages)