8e18c0f6eb946092fe17cfa580e1fa71c78c55be
[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 Screens.MessageBox import MessageBox
11 from Components.Label import Label
12 from Components.ScrollLabel import ScrollLabel
13 from Components.ActionMap import ActionMap
14 from Components.Sources.StaticText import StaticText
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 Components.config import config
21
22 import os
23
24 class CurlyTx(Screen,HelpableScreen):
25     skin = """
26         <screen name="CurlyTx" position="center,center" size="560,430" title="CurlyTx" >
27           <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
28           <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
29           <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
30           <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
31           <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" />
32           <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" />
33           <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" />
34           <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" />
35           <widget name="text" position="5,45" size="550,380" font="Console;20" />
36         </screen>"""
37
38     currentUrl = None
39     currentPage = None
40     currentFontSize = 20
41     httpGetterFactory = None
42     showingHeaders = False
43
44     def __init__(self, session, args = None):
45         #self.skin = CurlyTx.skin
46         Screen.__init__(self, session)
47         HelpableScreen.__init__(self)
48         #self.skinName = [ "CurlyTx", "Setup" ]
49
50         self["text"] = ScrollLabel("foo")
51
52         self["key_red"]    = StaticText(_("Settings"))
53         self["key_green"]  = StaticText(_("Reload"))
54         self["key_yellow"] = StaticText(_("Prev"))
55         self["key_blue"]   = StaticText(_("Next"))
56
57
58         self["actions"] = ActionMap(
59             ["WizardActions", "ColorActions", "InputActions", "InfobarEPGActions"], {
60                 "ok":   self.close,
61                 "back": self.close,
62                 "up":   self.pageUp,
63                 "down": self.pageDown,
64
65                 "red":    self.showSettings,
66                 "green":  self.reload,
67                 "yellow": self.prevPage,
68                 "blue":   self.nextPage,
69
70                 "showEventInfo": self.showHeader
71             }, -1)
72
73         self.loadHelp()
74         self.loadButtons()
75         self.onLayoutFinish.append(self.afterLayout)
76
77     def afterLayout(self):
78         self.setTextFont
79         self.loadUrl(config.plugins.CurlyTx.defaultPage.value)
80
81     def loadHelp(self):
82         self.helpList.append((
83                 self["actions"], "WizardActions",
84                 [("up", _("Scroll page contents up"))]))
85         self.helpList.append((
86                 self["actions"], "WizardActions",
87                 [("down", _("Scroll page contents down"))]))
88         self.helpList.append((
89                 self["actions"], "InfobarEPGActions",
90                 [("showEventInfo", _("Show HTTP response headers"))]))
91         self.helpList.append((
92                 self["actions"], "ColorActions",
93                 [("red", _("Show program settings"))]))
94         self.helpList.append((
95                 self["actions"], "ColorActions",
96                 [("green", _("Reload current page URL"))]))
97         self.helpList.append((
98                 self["actions"], "ColorActions",
99                 [("yellow", _("Switch to next configured page URL"))]))
100         self.helpList.append((
101                 self["actions"], "ColorActions",
102                 [("blue", _("Switch to previous configured page URL"))]))
103         self.helpList.append((
104                 self["actions"], "WizardActions",
105                 [("ok", _("Close window"))]))
106         self.helpList.append((
107                 self["actions"], "WizardActions",
108                 [("back", _("Close window"))]))
109
110     def loadButtons(self):
111         pageCount = len(config.plugins.CurlyTx.pages)
112         if pageCount == 0:
113             self["key_green"].setText("")
114             self["key_yellow"].setText("")
115             self["key_blue"].setText("")
116         elif pageCount == 1:
117             self["key_green"].setText(_("Reload"))
118             self["key_yellow"].setText("")
119             self["key_blue"].setText("")
120         else:
121             self["key_green"].setText(_("Reload"))
122             self["key_yellow"].setText(_("Prev"))
123             self["key_blue"].setText(_("Next"))
124
125     def pageUp(self):
126         self["text"].pageUp()
127
128     def pageDown(self):
129         self["text"].pageDown()
130
131     def prevPage(self):
132         if self.currentPage == None:
133             return
134
135         pageId = self.currentPage - 1
136         if pageId < 0:
137             pageId = len(config.plugins.CurlyTx.pages) - 1
138         self.loadUrl(pageId)
139
140     def nextPage(self):
141         if self.currentPage == None:
142             return
143
144         pageId = self.currentPage + 1
145         if pageId > len(config.plugins.CurlyTx.pages) - 1:
146             pageId = 0
147         self.loadUrl(pageId)
148
149     def reload(self):
150         if self.currentPage == None:
151             return
152
153         self.loadUrl(self.currentPage)
154
155     def loadUrl(self, pageId):
156         self.httpGetterFactory = None
157         if pageId == None:
158             self.loadNoPage()
159             return
160
161         cfg = config.plugins.CurlyTx
162         pageCount = len(cfg.pages)
163         pageId = int(pageId)
164         if pageId > (pageCount - 1):
165             if len(cfg.pages) == 0:
166                 self.loadNoPage()
167             else:
168                 self["text"].setText(_("Invalid page") + " " + pageId);
169             return
170
171         url   = cfg.pages[pageId].uri.value
172         title = cfg.pages[pageId].title.value
173
174         if pageCount > 1:
175             title = "{0} [{1}/{2}]".format(title, pageId + 1, pageCount)
176
177         self.currentPage = pageId
178         self.currentUrl = url
179         self.currentFontSize = cfg.pages[pageId].fontSize.value
180
181         self.setTitle(title)
182         self.setTextFont()
183         self["text"].setText(_("Loading ...") + "\n" + url);
184
185         if (url.startswith('file://')):
186             self.loadLocalFile(url)
187         else:
188             self.getPageWebClient(url).addCallback(self.urlLoaded).addErrback(self.urlFailed, url)
189
190     def loadLocalFile(self, url):
191         file = url[7:]
192         if not os.path.exists(file):
193             self.showFail('File does not exist', file)
194             return
195
196         with open(file, 'r') as f:
197             self.urlLoaded(f.read())
198
199     def setTextFont(self):
200         if self["text"].long_text is not None:
201             self["text"].long_text.setFont(gFont("Console", self.currentFontSize))
202
203     def urlLoaded(self, html):
204         self["text"].setText(html)
205
206     def urlFailed(self, error, url):
207         self.showFail(error.getErrorMessage(), url)
208
209     def showFail(self, message, url):
210         self["text"].setText(
211             _("Error fetching URL:") + "\n " + message
212             + "\n\nURL: " + url
213             )
214
215     def loadNoPage(self):
216         self["text"].setText(_("Go and add a page in the settings"));
217
218     def showHeader(self):
219         if not self.httpGetterFactory:
220             return
221
222         if self.showingHeaders:
223             self["text"].setText(self.pageContent)
224             self.pageContent    = None
225             self.showingHeaders = False
226         elif self.httpGetterFactory.response_headers:
227             headers = _("HTTP response headers for") + "\n" + self.currentUrl + "\n\n"
228             for (k, v) in self.httpGetterFactory.response_headers.items():
229                 headers += k + ": " + ("\n" + k + ": ").join(v) + "\n"
230             self.pageContent = self["text"].getText()
231             self["text"].setText(headers)
232             self.showingHeaders = True
233
234     def showSettings(self):
235         from CurlyTxSettings import CurlyTxSettings
236         self.session.openWithCallback(self.onSettingsChanged, CurlyTxSettings)
237
238     def onSettingsChanged(self):
239         self.loadButtons()
240         if len(config.plugins.CurlyTx.pages) == 0:
241             self.currentPage = None
242             self.loadUrl(self.currentPage)
243         elif self.currentPage == None:
244             self.currentPage = 0
245             self.loadUrl(self.currentPage)
246
247
248     def getPageWebClient(self, url, contextFactory=None, *args, **kwargs):
249         """
250         Download a web page as a string.
251
252         COPY OF twisted.web.client.getPage to store the factory
253
254         Download a page. Return a deferred, which will callback with a
255         page (as a string) or errback with a description of the error.
256
257         See L{HTTPClientFactory} to see what extra arguments can be passed.
258         """
259         self.httpGetterFactory = _makeGetterFactory(
260             url,
261             HTTPClientFactory,
262             contextFactory=contextFactory,
263             *args, **kwargs)
264         return self.httpGetterFactory.deferred