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