eric6/WebBrowser/Network/EricSchemeHandler.py

changeset 6942
2602857055c5
parent 6691
973b0d0ecc87
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2016 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a scheme handler for the eric: scheme.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import pyqtSignal, QByteArray, QBuffer, QIODevice, \
13 QUrlQuery, QMutex, QMutexLocker
14 from PyQt5.QtWidgets import qApp
15 from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler
16
17 from ..Tools.WebBrowserTools import readAllFileContents
18
19
20 class EricSchemeHandler(QWebEngineUrlSchemeHandler):
21 """
22 Class implementing a scheme handler for the eric: scheme.
23 """
24 SupportedPages = [
25 "adblock", # error page for URLs blocked by AdBlock
26 "home", "start", "startpage", # eric home page
27 "speeddial", # eric speeddial
28 ]
29
30 def __init__(self, parent=None):
31 """
32 Constructor
33
34 @param parent reference to the parent object
35 @type QObject
36 """
37 super(EricSchemeHandler, self).__init__(parent)
38
39 self.__replies = []
40
41 def requestStarted(self, job):
42 """
43 Public method handling the URL request.
44
45 @param job URL request job
46 @type QWebEngineUrlRequestJob
47 """
48 if job.requestUrl().path() in self.SupportedPages:
49 reply = EricSchemeReply(job)
50 reply.closed.connect(lambda: self.__replyClosed(reply))
51 self.__replies.append(reply)
52 job.reply(b"text/html", reply)
53 else:
54 job.reply(QByteArray(), QBuffer())
55 # job.fail(QWebEngineUrlRequestJob.UrlNotFound)
56
57 def __replyClosed(self, reply):
58 """
59 Private slot handling the closed signal of a reply.
60
61 @param reply reference to the network reply
62 @type EricSchemeReply
63 """
64 if reply in self.__replies:
65 self.__replies.remove(reply)
66
67
68 class EricSchemeReply(QIODevice):
69 """
70 Class implementing a reply for a requested eric: page.
71
72 @signal closed emitted to signal that the web engine has read
73 the data
74 """
75 closed = pyqtSignal()
76
77 _speedDialPage = ""
78
79 def __init__(self, job, parent=None):
80 """
81 Constructor
82
83 @param job reference to the URL request
84 @type QWebEngineUrlRequestJob
85 @param parent reference to the parent object
86 @type QObject
87 """
88 super(EricSchemeReply, self).__init__(parent)
89
90 self.__loaded = False
91 self.__job = job
92 self.__mutex = QMutex()
93
94 self.__pageName = self.__job.requestUrl().path()
95 self.__buffer = QBuffer()
96
97 self.__loadPage()
98
99 def __loadPage(self):
100 """
101 Private method to load the requested page.
102 """
103 if self.__loaded:
104 return
105
106 lock = QMutexLocker(self.__mutex)
107
108 if self.__pageName == "adblock":
109 contents = self.__adBlockPage()
110 elif self.__pageName in ["home", "start", "startpage"]:
111 contents = self.__startPage()
112 elif self.__pageName == "speeddial":
113 contents = self.__speedDialPage()
114 else:
115 contents = ""
116
117 self.__buffer.setData(contents.encode("utf-8"))
118 self.__buffer.open(QIODevice.ReadOnly)
119 self.open(QIODevice.ReadOnly)
120 lock.unlock()
121
122 self.readyRead.emit()
123
124 self.__loaded = True
125
126 def bytesAvailable(self):
127 """
128 Public method to get the number of available bytes.
129
130 @return number of available bytes
131 @rtype int
132 """
133 lock = QMutexLocker(self.__mutex) # __IGNORE_WARNING__
134 return self.__buffer.bytesAvailable()
135
136 def readData(self, maxlen):
137 """
138 Public method to retrieve data from the reply object.
139
140 @param maxlen maximum number of bytes to read (integer)
141 @return string containing the data (bytes)
142 """
143 lock = QMutexLocker(self.__mutex) # __IGNORE_WARNING__
144 return self.__buffer.read(maxlen)
145
146 def close(self):
147 """
148 Public method used to cloase the reply.
149 """
150 super(EricSchemeReply, self).close()
151 self.closed.emit()
152
153 def __adBlockPage(self):
154 """
155 Private method to build the AdBlock page.
156
157 @return built AdBlock page
158 @rtype str
159 """
160 query = QUrlQuery(self.__job.requestUrl())
161 rule = query.queryItemValue("rule")
162 subscription = query.queryItemValue("subscription")
163 title = self.tr("Content blocked by AdBlock Plus")
164 message = self.tr(
165 "Blocked by rule: <i>{0} ({1})</i>").format(rule, subscription)
166
167 page = readAllFileContents(":/html/adblockPage.html")
168 page = page.replace(
169 "@FAVICON@", "qrc:icons/adBlockPlus16.png")
170 page = page.replace(
171 "@IMAGE@", "qrc:icons/adBlockPlus64.png")
172 page = page.replace("@TITLE@", title)
173 page = page.replace("@MESSAGE@", message)
174
175 return page
176
177 def __startPage(self):
178 """
179 Private method to build the Start page.
180
181 @return built Start page
182 @rtype str
183 """
184 page = readAllFileContents(":/html/startPage.html")
185 page = page.replace("@FAVICON@", "qrc:icons/ericWeb16.png")
186 page = page.replace("@IMAGE@", "qrc:icons/ericWeb32.png")
187 page = page.replace("@TITLE@",
188 self.tr("Welcome to eric6 Web Browser!"))
189 page = page.replace("@ERIC_LINK@", self.tr("About eric6"))
190 page = page.replace("@HEADER_TITLE@", self.tr("eric6 Web Browser"))
191 page = page.replace("@SUBMIT@", self.tr("Search!"))
192 if qApp.isLeftToRight():
193 ltr = "LTR"
194 else:
195 ltr = "RTL"
196 page = page.replace("@QT_LAYOUT_DIRECTION@", ltr)
197
198 return page
199
200 def __speedDialPage(self):
201 """
202 Private method to create the Speeddial page.
203
204 @return prepared speeddial page (QByteArray)
205 """
206 if not self._speedDialPage:
207 page = readAllFileContents(":/html/speeddialPage.html")
208 page = page.replace("@FAVICON@", "qrc:icons/ericWeb16.png")
209 page = page.replace("@IMG_PLUS@", "qrc:icons/plus.png")
210 page = page.replace("@IMG_CLOSE@", "qrc:icons/close.png")
211 page = page.replace("@IMG_EDIT@", "qrc:icons/edit.png")
212 page = page.replace("@IMG_RELOAD@", "qrc:icons/reload.png")
213 page = page.replace("@IMG_SETTINGS@", "qrc:icons/setting.png")
214 page = page.replace("@LOADING-IMG@", "qrc:icons/loading.gif")
215 page = page.replace("@BOX-BORDER@",
216 "qrc:icons/box-border-small.png")
217
218 page = page.replace("@JQUERY@", "qrc:javascript/jquery.js")
219 page = page.replace("@JQUERY-UI@", "qrc:javascript/jquery-ui.js")
220
221 page = page.replace("@SITE-TITLE@", self.tr("Speed Dial"))
222 page = page.replace("@URL@", self.tr("URL"))
223 page = page.replace("@TITLE@", self.tr("Title"))
224 page = page.replace("@APPLY@", self.tr("Apply"))
225 page = page.replace("@CLOSE@", self.tr("Close"))
226 page = page.replace("@NEW-PAGE@", self.tr("New Page"))
227 page = page.replace("@TITLE-EDIT@", self.tr("Edit"))
228 page = page.replace("@TITLE-REMOVE@", self.tr("Remove"))
229 page = page.replace("@TITLE-RELOAD@", self.tr("Reload"))
230 page = page.replace("@TITLE-WARN@",
231 self.tr("Are you sure to remove this"
232 " speed dial?"))
233 page = page.replace("@TITLE-WARN-REL@",
234 self.tr("Are you sure you want to reload"
235 " all speed dials?"))
236 page = page.replace("@TITLE-FETCHTITLE@",
237 self.tr("Load title from page"))
238 page = page.replace("@SETTINGS-TITLE@",
239 self.tr("Speed Dial Settings"))
240 page = page.replace("@ADD-TITLE@", self.tr("Add New Page"))
241 page = page.replace("@TXT_NRROWS@",
242 self.tr("Maximum pages in a row:"))
243 page = page.replace("@TXT_SDSIZE@",
244 self.tr("Change size of pages:"))
245 page = page.replace("@JAVASCRIPT_DISABLED@",
246 self.tr("SpeedDial requires enabled"
247 " JavaScript."))
248
249 self._speedDialPage = page
250
251 from WebBrowser.WebBrowserWindow import WebBrowserWindow
252 dial = WebBrowserWindow.speedDial()
253 page = (
254 self._speedDialPage
255 .replace("@INITIAL-SCRIPT@", dial.initialScript())
256 .replace("@ROW-PAGES@", str(dial.pagesInRow()))
257 .replace("@SD-SIZE@", str(dial.sdSize()))
258 )
259
260 return page

eric ide

mercurial