show curlytx in plugin browser
[enigma2-curlytx.git] / src / CurlyTx.py
1 # -*- coding: utf-8 -*-
2 # CurlyTx main window
3 # Copyright (C) 2011 Christian Weiske <cweiske@cweiske.de>
4 # License: GPLv3 or later
5
6 from . import _
7
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
18
19 from . import config
20 from config import createPage, loadDefaultPageOptions, feedPagesToConfig, feedSettingsToConfig, savePageConfig
21 from Components.config import config
22
23 import os
24
25 class CurlyTx(Screen, HelpableScreen):
26     skin = """
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" />
37         </screen>"""
38
39     currentUrl = None
40     currentPage = None
41     currentFontSize = 20
42     httpGetterFactory = None
43     showingHeaders = False
44     staticPageFeedFile = 'curlytx-pagefeed.xml'
45
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" ]
51
52         self["text"] = ScrollLabel("foo")
53
54         self["key_red"]    = StaticText(_("Settings"))
55         self["key_green"]  = StaticText(_("Reload"))
56         self["key_yellow"] = StaticText(_("Prev"))
57         self["key_blue"]   = StaticText(_("Next"))
58
59
60         self["actions"] = ActionMap(
61             ["WizardActions", "ColorActions", "InputActions", "InfobarEPGActions"], {
62                 "ok":   self.close,
63                 "back": self.close,
64                 "up":   self.pageUp,
65                 "down": self.pageDown,
66
67                 "red":    self.showSettings,
68                 "green":  self.reload,
69                 "yellow": self.prevPage,
70                 "blue":   self.nextPage,
71
72                 "showEventInfo": self.showHeader
73             }, -1)
74
75         self.loadHelp()
76         self.loadButtons()
77         self.onFirstExecBegin.append(self.afterLayout)
78
79     def afterLayout(self):
80         self.setTextFont
81         self.loadStaticConfig()
82         self.loadUrl(config.plugins.CurlyTx.defaultPage.value)
83
84     def loadHelp(self):
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"))]))
112
113     def loadButtons(self):
114         pageCount = len(config.plugins.CurlyTx.pages)
115         if pageCount == 0:
116             self["key_green"].setText("")
117             self["key_yellow"].setText("")
118             self["key_blue"].setText("")
119         elif pageCount == 1:
120             self["key_green"].setText(_("Reload"))
121             self["key_yellow"].setText("")
122             self["key_blue"].setText("")
123         else:
124             self["key_green"].setText(_("Reload"))
125             self["key_yellow"].setText(_("Prev"))
126             self["key_blue"].setText(_("Next"))
127
128         if config.plugins.CurlyTx.enableSettings.getValue():
129             self["key_red"].setText(_("Settings"))
130         else:
131             self["key_red"].setText("")
132
133     def pageUp(self):
134         self["text"].pageUp()
135
136     def pageDown(self):
137         self["text"].pageDown()
138
139     def prevPage(self):
140         if self.currentPage == None:
141             return
142
143         pageId = self.currentPage - 1
144         if pageId < 0:
145             pageId = len(config.plugins.CurlyTx.pages) - 1
146         self.loadUrl(pageId)
147
148     def nextPage(self):
149         if self.currentPage == None:
150             return
151
152         pageId = self.currentPage + 1
153         if pageId > len(config.plugins.CurlyTx.pages) - 1:
154             pageId = 0
155         self.loadUrl(pageId)
156
157     def reload(self):
158         if self.currentPage == None:
159             return
160
161         self.loadUrl(self.currentPage)
162
163     def loadUrl(self, pageId):
164         self.httpGetterFactory = None
165         if pageId == None:
166             self.loadNoPage()
167             return
168
169         cfg = config.plugins.CurlyTx
170         pageCount = len(cfg.pages)
171         pageId = int(pageId)
172         if pageId > (pageCount - 1):
173             if len(cfg.pages) == 0:
174                 self.loadNoPage()
175             else:
176                 self["text"].setText(_("Invalid page") + " " + pageId);
177             return
178
179         url   = cfg.pages[pageId].uri.value
180         title = cfg.pages[pageId].title.value
181
182         if pageCount > 1:
183             title = "{0} [{1}/{2}]".format(title, pageId + 1, pageCount)
184
185         self.currentPage = pageId
186         self.currentUrl = url
187         self.currentFontSize = cfg.pages[pageId].fontSize.value
188
189         self.setTitle(title)
190         self.setTextFont()
191         self["text"].setText(_("Loading ...") + "\n" + url);
192
193         if (url.startswith('file://')):
194             self.loadLocalFile(url)
195         else:
196             self.getPageWebClient(url).addCallback(self.urlLoaded).addErrback(self.urlFailed, url)
197
198     def loadLocalFile(self, url):
199         file = url[7:]
200         if not os.path.exists(file):
201             self.showFail('File does not exist', file)
202             return
203
204         with open(file, 'r') as f:
205             self.urlLoaded(f.read())
206
207     def setTextFont(self):
208         if self["text"].long_text is not None:
209             self["text"].long_text.setFont(gFont("Console", self.currentFontSize))
210
211     def urlLoaded(self, html):
212         self["text"].setText(html)
213
214     def urlFailed(self, error, url):
215         self.showFail(error.getErrorMessage(), url)
216
217     def showFail(self, message, url):
218         self["text"].setText(
219             _("Error fetching URL:") + "\n " + message
220             + "\n\nURL: " + url
221             )
222
223     def loadNoPage(self):
224         self["text"].setText(_("Go and add a page in the settings"));
225
226     def showHeader(self):
227         if not self.httpGetterFactory:
228             return
229
230         if self.showingHeaders:
231             self["text"].setText(self.pageContent)
232             self.pageContent    = None
233             self.showingHeaders = False
234         elif self.httpGetterFactory.response_headers:
235             headers = _("HTTP response headers for") + "\n" + self.currentUrl + "\n\n"
236             for (k, v) in self.httpGetterFactory.response_headers.items():
237                 headers += k + ": " + ("\n" + k + ": ").join(v) + "\n"
238             self.pageContent = self["text"].getText()
239             self["text"].setText(headers)
240             self.showingHeaders = True
241
242     def showSettings(self):
243         if not config.plugins.CurlyTx.enableSettings.getValue():
244             return
245
246         from CurlyTxSettings import CurlyTxSettings
247         self.session.openWithCallback(self.onSettingsChanged, CurlyTxSettings)
248
249     def onSettingsChanged(self):
250         self.loadButtons()
251         if len(config.plugins.CurlyTx.pages) == 0:
252             self.currentPage = None
253             self.loadUrl(self.currentPage)
254         elif self.currentPage == None:
255             self.currentPage = 0
256             self.loadUrl(self.currentPage)
257
258
259     def getPageWebClient(self, url, contextFactory=None, *args, **kwargs):
260         """
261         Download a web page as a string.
262
263         COPY OF twisted.web.client.getPage to store the factory
264
265         Download a page. Return a deferred, which will callback with a
266         page (as a string) or errback with a description of the error.
267
268         See L{HTTPClientFactory} to see what extra arguments can be passed.
269         """
270         self.httpGetterFactory = _makeGetterFactory(
271             url,
272             HTTPClientFactory,
273             contextFactory=contextFactory,
274             *args, **kwargs)
275         return self.httpGetterFactory.deferred
276
277     def loadStaticConfig(self):
278         """
279         Always try to load the static config file from
280         /etc/enigma2/curlytx-pagefeed.xml
281         """
282         staticFeedPath = Directories.resolveFilename(Directories.SCOPE_CONFIG, self.staticPageFeedFile)
283         if not os.path.exists(staticFeedPath):
284             return
285
286         from AtomFeed import AtomFeed
287         AtomFeed(
288             'file://' + staticFeedPath,
289             self.saveStaticConfig, self.loadStaticConfigFail
290             )
291
292     def loadStaticConfigFail(self, errorMessage):
293         """ Loading the page url feed failed somehow """
294         from Screens.MessageBox import MessageBox
295         self.session.open(
296             MessageBox,
297             _("Error loading page feed:") + "\n\n" + str(errorMessage),
298             type = MessageBox.TYPE_ERROR
299             )
300
301     def saveStaticConfig(self, pages, settings):
302         feedPagesToConfig(pages)
303         feedSettingsToConfig(settings)
304         savePageConfig()
305         self.loadButtons()