6 |
6 |
7 """ |
7 """ |
8 Module implementing the helpbrowser using QWebView. |
8 Module implementing the helpbrowser using QWebView. |
9 """ |
9 """ |
10 |
10 |
11 from PyQt4.QtCore import pyqtSlot, pyqtSignal, QObject, QT_TRANSLATE_NOOP, QUrl, \ |
11 from PyQt4.QtCore import pyqtSlot, pyqtSignal, QObject, QT_TRANSLATE_NOOP, \ |
12 QBuffer, QIODevice, QFileInfo, Qt, QTimer, QEvent, QRect, QFile, QPoint, \ |
12 QUrl, QBuffer, QIODevice, QFileInfo, Qt, QTimer, QEvent, QRect, QFile, \ |
13 QByteArray, qVersion |
13 QPoint, QByteArray, qVersion |
14 from PyQt4.QtGui import qApp, QDesktopServices, QStyle, QMenu, QApplication, \ |
14 from PyQt4.QtGui import qApp, QDesktopServices, QStyle, QMenu, QApplication, \ |
15 QInputDialog, QLineEdit, QClipboard, QMouseEvent, QLabel, QToolTip, QColor, \ |
15 QInputDialog, QLineEdit, QClipboard, QMouseEvent, QLabel, QToolTip, \ |
16 QPalette, QFrame, QPrinter, QPrintDialog, QDialog |
16 QColor, QPalette, QFrame, QPrinter, QPrintDialog, QDialog |
17 from PyQt4.QtWebKit import QWebView, QWebPage, QWebSettings |
17 from PyQt4.QtWebKit import QWebView, QWebPage, QWebSettings |
18 try: |
18 try: |
19 from PyQt4.QtWebKit import QWebElement |
19 from PyQt4.QtWebKit import QWebElement |
20 except ImportError: |
20 except ImportError: |
21 pass |
21 pass |
72 self.rel = "" |
72 self.rel = "" |
73 self.type_ = "" |
73 self.type_ = "" |
74 self.href = "" |
74 self.href = "" |
75 self.title = "" |
75 self.title = "" |
76 |
76 |
77 ########################################################################################## |
77 ############################################################################### |
78 |
78 |
79 |
79 |
80 class JavaScriptEricObject(QObject): |
80 class JavaScriptEricObject(QObject): |
81 """ |
81 """ |
82 Class implementing an external javascript object to search via the startpage. |
82 Class implementing an external javascript object to search via the |
|
83 startpage. |
83 """ |
84 """ |
84 # these must be in line with the strings used by the javascript part of the start page |
85 # these must be in line with the strings used by the javascript part of |
|
86 # the start page |
85 translations = [ |
87 translations = [ |
86 QT_TRANSLATE_NOOP("JavaScriptEricObject", "Welcome to eric5 Web Browser!"), |
88 QT_TRANSLATE_NOOP("JavaScriptEricObject", |
|
89 "Welcome to eric5 Web Browser!"), |
87 QT_TRANSLATE_NOOP("JavaScriptEricObject", "eric5 Web Browser"), |
90 QT_TRANSLATE_NOOP("JavaScriptEricObject", "eric5 Web Browser"), |
88 QT_TRANSLATE_NOOP("JavaScriptEricObject", "Search!"), |
91 QT_TRANSLATE_NOOP("JavaScriptEricObject", "Search!"), |
89 QT_TRANSLATE_NOOP("JavaScriptEricObject", "About eric5"), |
92 QT_TRANSLATE_NOOP("JavaScriptEricObject", "About eric5"), |
90 ] |
93 ] |
91 |
94 |
160 |
163 |
161 self.__lastRequest = None |
164 self.__lastRequest = None |
162 self.__lastRequestType = QWebPage.NavigationTypeOther |
165 self.__lastRequestType = QWebPage.NavigationTypeOther |
163 |
166 |
164 import Helpviewer.HelpWindow |
167 import Helpviewer.HelpWindow |
165 from .Network.NetworkAccessManagerProxy import NetworkAccessManagerProxy |
168 from .Network.NetworkAccessManagerProxy import \ |
|
169 NetworkAccessManagerProxy |
166 self.__proxy = NetworkAccessManagerProxy(self) |
170 self.__proxy = NetworkAccessManagerProxy(self) |
167 self.__proxy.setWebPage(self) |
171 self.__proxy.setWebPage(self) |
168 self.__proxy.setPrimaryNetworkAccessManager( |
172 self.__proxy.setPrimaryNetworkAccessManager( |
169 Helpviewer.HelpWindow.HelpWindow.networkAccessManager()) |
173 Helpviewer.HelpWindow.HelpWindow.networkAccessManager()) |
170 self.setNetworkAccessManager(self.__proxy) |
174 self.setNetworkAccessManager(self.__proxy) |
195 return False |
199 return False |
196 |
200 |
197 if type_ == QWebPage.NavigationTypeFormResubmitted: |
201 if type_ == QWebPage.NavigationTypeFormResubmitted: |
198 res = E5MessageBox.yesNo(self.view(), |
202 res = E5MessageBox.yesNo(self.view(), |
199 self.trUtf8("Resending POST request"), |
203 self.trUtf8("Resending POST request"), |
200 self.trUtf8("""In order to display the site, the request along with""" |
204 self.trUtf8( |
201 """ all the data must be sent once again, which may lead""" |
205 """In order to display the site, the request along with""" |
202 """ to some unexpected behaviour of the site e.g. the""" |
206 """ all the data must be sent once again, which may lead""" |
203 """ same action might be performed once again. Do you want""" |
207 """ to some unexpected behaviour of the site e.g. the""" |
204 """ to continue anyway?"""), |
208 """ same action might be performed once again. Do you""" |
|
209 """ want to continue anyway?"""), |
205 icon=E5MessageBox.Warning) |
210 icon=E5MessageBox.Warning) |
206 if not res: |
211 if not res: |
207 return False |
212 return False |
208 |
213 |
209 return QWebPage.acceptNavigationRequest(self, frame, request, type_) |
214 return QWebPage.acceptNavigationRequest(self, frame, request, type_) |
210 |
215 |
211 def populateNetworkRequest(self, request): |
216 def populateNetworkRequest(self, request): |
212 """ |
217 """ |
213 Public method to add data to a network request. |
218 Public method to add data to a network request. |
214 |
219 |
215 @param request reference to the network request object (QNetworkRequest) |
220 @param request reference to the network request object |
|
221 (QNetworkRequest) |
216 """ |
222 """ |
217 try: |
223 try: |
218 request.setAttribute(QNetworkRequest.User + 100, self) |
224 request.setAttribute(QNetworkRequest.User + 100, self) |
219 if self.__lastRequest.url() == request.url(): |
225 if self.__lastRequest.url() == request.url(): |
220 request.setAttribute(QNetworkRequest.User + 101, self.__lastRequestType) |
226 request.setAttribute(QNetworkRequest.User + 101, |
221 if self.__lastRequestType == QWebPage.NavigationTypeLinkClicked: |
227 self.__lastRequestType) |
222 request.setRawHeader("X-Eric5-UserLoadAction", QByteArray("1")) |
228 if self.__lastRequestType == \ |
|
229 QWebPage.NavigationTypeLinkClicked: |
|
230 request.setRawHeader("X-Eric5-UserLoadAction", |
|
231 QByteArray("1")) |
223 except TypeError: |
232 except TypeError: |
224 pass |
233 pass |
225 |
234 |
226 def pageAttributeId(self): |
235 def pageAttributeId(self): |
227 """ |
236 """ |
250 def extension(self, extension, option, output): |
259 def extension(self, extension, option, output): |
251 """ |
260 """ |
252 Public method to implement a specific extension. |
261 Public method to implement a specific extension. |
253 |
262 |
254 @param extension extension to be executed (QWebPage.Extension) |
263 @param extension extension to be executed (QWebPage.Extension) |
255 @param option provides input to the extension (QWebPage.ExtensionOption) |
264 @param option provides input to the extension |
|
265 (QWebPage.ExtensionOption) |
256 @param output stores the output results (QWebPage.ExtensionReturn) |
266 @param output stores the output results (QWebPage.ExtensionReturn) |
257 @return flag indicating a successful call of the extension (boolean) |
267 @return flag indicating a successful call of the extension (boolean) |
258 """ |
268 """ |
259 if extension == QWebPage.ChooseMultipleFilesExtension: |
269 if extension == QWebPage.ChooseMultipleFilesExtension: |
260 info = sip.cast(option, QWebPage.ChooseMultipleFilesExtensionOption) |
270 info = sip.cast(option, |
261 files = sip.cast(output, QWebPage.ChooseMultipleFilesExtensionReturn) |
271 QWebPage.ChooseMultipleFilesExtensionOption) |
|
272 files = sip.cast(output, |
|
273 QWebPage.ChooseMultipleFilesExtensionReturn) |
262 if info is None or files is None: |
274 if info is None or files is None: |
263 return super().extension(extension, option, output) |
275 return super().extension(extension, option, output) |
264 |
276 |
265 suggestedFileName = "" |
277 suggestedFileName = "" |
266 if info.suggestedFileNames: |
278 if info.suggestedFileNames: |
273 return True |
285 return True |
274 |
286 |
275 if extension == QWebPage.ErrorPageExtension: |
287 if extension == QWebPage.ErrorPageExtension: |
276 info = sip.cast(option, QWebPage.ErrorPageExtensionOption) |
288 info = sip.cast(option, QWebPage.ErrorPageExtensionOption) |
277 if info.error == 102: |
289 if info.error == 102: |
278 # this is something of a hack; hopefully it will work in the future |
290 # this is something of a hack; hopefully it will work in |
|
291 # the future |
279 return False |
292 return False |
280 |
293 |
281 errorPage = sip.cast(output, QWebPage.ErrorPageExtensionReturn) |
294 errorPage = sip.cast(output, QWebPage.ErrorPageExtensionReturn) |
282 urlString = bytes(info.url.toEncoded()).decode() |
295 urlString = bytes(info.url.toEncoded()).decode() |
283 errorPage.baseUrl = info.url |
296 errorPage.baseUrl = info.url |
284 if info.domain == QWebPage.QtNetwork and \ |
297 if info.domain == QWebPage.QtNetwork and \ |
285 info.error == QNetworkReply.ContentAccessDenied and \ |
298 info.error == QNetworkReply.ContentAccessDenied and \ |
286 info.errorString.startswith("AdBlockRule:"): |
299 info.errorString.startswith("AdBlockRule:"): |
287 if info.frame != info.frame.page().mainFrame(): |
300 if info.frame != info.frame.page().mainFrame(): |
288 # content in <iframe> |
301 # content in <iframe> |
289 docElement = info.frame.page().mainFrame().documentElement() |
302 docElement = info.frame.page().mainFrame()\ |
|
303 .documentElement() |
290 for element in docElement.findAll("iframe"): |
304 for element in docElement.findAll("iframe"): |
291 src = element.attribute("src") |
305 src = element.attribute("src") |
292 if src in info.url.toString(): |
306 if src in info.url.toString(): |
293 element.setAttribute("style", "display:none;") |
307 element.setAttribute("style", "display:none;") |
294 return False |
308 return False |
295 else: |
309 else: |
296 # the whole page is blocked |
310 # the whole page is blocked |
297 rule = info.errorString.replace("AdBlockRule:", "") |
311 rule = info.errorString.replace("AdBlockRule:", "") |
298 title = self.trUtf8("Content blocked by AdBlock Plus") |
312 title = self.trUtf8("Content blocked by AdBlock Plus") |
299 message = self.trUtf8("Blocked by rule: <i>{0}</i>").format(rule) |
313 message = self.trUtf8( |
|
314 "Blocked by rule: <i>{0}</i>").format(rule) |
300 |
315 |
301 htmlFile = QFile(":/html/adblockPage.html") |
316 htmlFile = QFile(":/html/adblockPage.html") |
302 htmlFile.open(QFile.ReadOnly) |
317 htmlFile.open(QFile.ReadOnly) |
303 html = htmlFile.readAll() |
318 html = htmlFile.readAll() |
304 html = html.replace("@FAVICON@", "qrc:icons/adBlockPlus16.png") |
319 html = html.replace( |
305 html = html.replace("@IMAGE@", "qrc:icons/adBlockPlus64.png") |
320 "@FAVICON@", "qrc:icons/adBlockPlus16.png") |
|
321 html = html.replace( |
|
322 "@IMAGE@", "qrc:icons/adBlockPlus64.png") |
306 html = html.replace("@TITLE@", title.encode("utf8")) |
323 html = html.replace("@TITLE@", title.encode("utf8")) |
307 html = html.replace("@MESSAGE@", message.encode("utf8")) |
324 html = html.replace("@MESSAGE@", message.encode("utf8")) |
308 errorPage.content = html |
325 errorPage.content = html |
309 return True |
326 return True |
310 |
327 |
326 pixmap = qApp.style()\ |
343 pixmap = qApp.style()\ |
327 .standardIcon(QStyle.SP_MessageBoxWarning).pixmap(16, 16) |
344 .standardIcon(QStyle.SP_MessageBoxWarning).pixmap(16, 16) |
328 imageBuffer = QBuffer() |
345 imageBuffer = QBuffer() |
329 imageBuffer.open(QIODevice.ReadWrite) |
346 imageBuffer.open(QIODevice.ReadWrite) |
330 if pixmap.save(imageBuffer, "PNG"): |
347 if pixmap.save(imageBuffer, "PNG"): |
331 html = html.replace("@FAVICON@", imageBuffer.buffer().toBase64()) |
348 html = html.replace( |
|
349 "@FAVICON@", imageBuffer.buffer().toBase64()) |
332 html = html.replace("@TITLE@", title.encode("utf8")) |
350 html = html.replace("@TITLE@", title.encode("utf8")) |
333 html = html.replace("@H1@", info.errorString.encode("utf8")) |
351 html = html.replace("@H1@", info.errorString.encode("utf8")) |
334 html = html.replace("@H2@", self.trUtf8("When connecting to: {0}.")\ |
352 html = html.replace( |
|
353 "@H2@", self.trUtf8("When connecting to: {0}.")\ |
335 .format(urlString).encode("utf8")) |
354 .format(urlString).encode("utf8")) |
336 html = html.replace("@LI-1@", |
355 html = html.replace("@LI-1@", |
337 self.trUtf8("Check the address for errors such as " |
356 self.trUtf8("Check the address for errors such as " |
338 "<b>ww</b>.example.org instead of " |
357 "<b>ww</b>.example.org instead of " |
339 "<b>www</b>.example.org").encode("utf8")) |
358 "<b>www</b>.example.org").encode("utf8")) |
340 html = html.replace("@LI-2@", |
359 html = html.replace("@LI-2@", |
341 self.trUtf8("If the address is correct, try checking the network " |
360 self.trUtf8( |
342 "connection.").encode("utf8")) |
361 "If the address is correct, try checking the network " |
|
362 "connection.").encode("utf8")) |
343 html = html.replace("@LI-3@", |
363 html = html.replace("@LI-3@", |
344 self.trUtf8("If your computer or network is protected by a firewall " |
364 self.trUtf8( |
345 "or proxy, make sure that the browser is permitted to " |
365 "If your computer or network is protected by a firewall " |
346 "access the network.").encode("utf8")) |
366 "or proxy, make sure that the browser is permitted to " |
|
367 "access the network.").encode("utf8")) |
347 html = html.replace("@LI-4@", |
368 html = html.replace("@LI-4@", |
348 self.trUtf8("If your cache policy is set to offline browsing," |
369 self.trUtf8("If your cache policy is set to offline browsing," |
349 "only pages in the local cache are available.")\ |
370 "only pages in the local cache are available.")\ |
350 .encode("utf8")) |
371 .encode("utf8")) |
351 html = html.replace("@BUTTON@", self.trUtf8("Try Again").encode("utf8")) |
372 html = html.replace( |
|
373 "@BUTTON@", self.trUtf8("Try Again").encode("utf8")) |
352 errorPage.content = html |
374 errorPage.content = html |
353 return True |
375 return True |
354 |
376 |
355 return QWebPage.extension(self, extension, option, output) |
377 return QWebPage.extension(self, extension, option, output) |
356 |
378 |
504 |
528 |
505 @param pos position to show the info at (QPoint) |
529 @param pos position to show the info at (QPoint) |
506 """ |
530 """ |
507 if SSL_AVAILABLE and self.__sslConfiguration is not None: |
531 if SSL_AVAILABLE and self.__sslConfiguration is not None: |
508 from E5Network.E5SslInfoWidget import E5SslInfoWidget |
532 from E5Network.E5SslInfoWidget import E5SslInfoWidget |
509 widget = E5SslInfoWidget(self.mainFrame().url(), self.__sslConfiguration, |
533 widget = E5SslInfoWidget( |
510 self.view()) |
534 self.mainFrame().url(), self.__sslConfiguration, self.view()) |
511 widget.showAt(pos) |
535 widget.showAt(pos) |
512 else: |
536 else: |
513 E5MessageBox.warning(self.view(), |
537 E5MessageBox.warning(self.view(), |
514 self.trUtf8("SSL Info"), |
538 self.trUtf8("SSL Info"), |
515 self.trUtf8("""This site does not contain SSL information.""")) |
539 self.trUtf8("""This site does not contain SSL information.""")) |
687 """ |
711 """ |
688 Private slot to add javascript bindings for adding search providers. |
712 Private slot to add javascript bindings for adding search providers. |
689 |
713 |
690 @param frame reference to the web frame (QWebFrame) |
714 @param frame reference to the web frame (QWebFrame) |
691 """ |
715 """ |
692 self.page().settings().setAttribute(QWebSettings.JavascriptEnabled, True) |
716 self.page().settings().setAttribute(QWebSettings.JavascriptEnabled, |
|
717 True) |
693 if self.__javaScriptBinding is None: |
718 if self.__javaScriptBinding is None: |
694 self.__javaScriptBinding = JavaScriptExternalObject(self.mw, self) |
719 self.__javaScriptBinding = JavaScriptExternalObject(self.mw, self) |
695 |
720 |
696 if frame is None: |
721 if frame is None: |
697 # called from QWebFrame.javaScriptWindowObjectCleared |
722 # called from QWebFrame.javaScriptWindowObjectCleared |
698 frame = self.sender() |
723 frame = self.sender() |
699 if isinstance(frame, HelpWebPage): |
724 if isinstance(frame, HelpWebPage): |
700 frame = frame.mainFrame() |
725 frame = frame.mainFrame() |
701 if frame.url().scheme() == "eric" and frame.url().path() == "home": |
726 if frame.url().scheme() == "eric" and frame.url().path() == "home": |
702 if self.__javaScriptEricObject is None: |
727 if self.__javaScriptEricObject is None: |
703 self.__javaScriptEricObject = JavaScriptEricObject(self.mw, self) |
728 self.__javaScriptEricObject = JavaScriptEricObject( |
704 frame.addToJavaScriptWindowObject("eric", self.__javaScriptEricObject) |
729 self.mw, self) |
705 elif frame.url().scheme() == "eric" and frame.url().path() == "speeddial": |
730 frame.addToJavaScriptWindowObject( |
706 frame.addToJavaScriptWindowObject("speeddial", self.__speedDial) |
731 "eric", self.__javaScriptEricObject) |
|
732 elif frame.url().scheme() == "eric" and \ |
|
733 frame.url().path() == "speeddial": |
|
734 frame.addToJavaScriptWindowObject( |
|
735 "speeddial", self.__speedDial) |
707 self.__speedDial.addWebFrame(frame) |
736 self.__speedDial.addWebFrame(frame) |
708 else: |
737 else: |
709 # called from QWebPage.frameCreated |
738 # called from QWebPage.frameCreated |
710 frame.javaScriptWindowObjectCleared.connect(self.__addExternalBinding) |
739 frame.javaScriptWindowObjectCleared.connect( |
|
740 self.__addExternalBinding) |
711 frame.addToJavaScriptWindowObject("external", self.__javaScriptBinding) |
741 frame.addToJavaScriptWindowObject("external", self.__javaScriptBinding) |
712 |
742 |
713 def linkedResources(self, relation=""): |
743 def linkedResources(self, relation=""): |
714 """ |
744 """ |
715 Public method to extract linked resources. |
745 Public method to extract linked resources. |
1034 self.trUtf8("Bookmark this Link"), self.__bookmarkLink)\ |
1068 self.trUtf8("Bookmark this Link"), self.__bookmarkLink)\ |
1035 .setData(hit.linkUrl()) |
1069 .setData(hit.linkUrl()) |
1036 menu.addSeparator() |
1070 menu.addSeparator() |
1037 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"), |
1071 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"), |
1038 self.trUtf8("Copy Link to Clipboard"), self.__copyLink) |
1072 self.trUtf8("Copy Link to Clipboard"), self.__copyLink) |
1039 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"), |
1073 menu.addAction( |
1040 self.trUtf8("Send Link"), self.__sendLink).setData(hit.linkUrl()) |
1074 UI.PixmapCache.getIcon("mailSend.png"), |
|
1075 self.trUtf8("Send Link"), |
|
1076 self.__sendLink).setData(hit.linkUrl()) |
1041 if Preferences.getHelp("VirusTotalEnabled") and \ |
1077 if Preferences.getHelp("VirusTotalEnabled") and \ |
1042 Preferences.getHelp("VirusTotalServiceKey") != "": |
1078 Preferences.getHelp("VirusTotalServiceKey") != "": |
1043 menu.addAction(UI.PixmapCache.getIcon("virustotal.png"), |
1079 menu.addAction( |
1044 self.trUtf8("Scan Link with VirusTotal"), self.__virusTotal)\ |
1080 UI.PixmapCache.getIcon("virustotal.png"), |
1045 .setData(hit.linkUrl()) |
1081 self.trUtf8("Scan Link with VirusTotal"), |
|
1082 self.__virusTotal).setData(hit.linkUrl()) |
1046 |
1083 |
1047 if not hit.imageUrl().isEmpty(): |
1084 if not hit.imageUrl().isEmpty(): |
1048 if not menu.isEmpty(): |
1085 if not menu.isEmpty(): |
1049 menu.addSeparator() |
1086 menu.addSeparator() |
1050 menu.addAction(UI.PixmapCache.getIcon("openNewTab.png"), |
1087 menu.addAction(UI.PixmapCache.getIcon("openNewTab.png"), |
1051 self.trUtf8("Open Image in New Tab"), |
1088 self.trUtf8("Open Image in New Tab"), |
1052 self.__openLinkInNewTab).setData(hit.imageUrl()) |
1089 self.__openLinkInNewTab).setData(hit.imageUrl()) |
1053 menu.addSeparator() |
1090 menu.addSeparator() |
1054 menu.addAction(UI.PixmapCache.getIcon("download.png"), |
1091 menu.addAction(UI.PixmapCache.getIcon("download.png"), |
1055 self.trUtf8("Save Image"), self.__downloadImage) |
1092 self.trUtf8("Save Image"), self.__downloadImage) |
1056 menu.addAction(self.trUtf8("Copy Image to Clipboard"), self.__copyImage) |
1093 menu.addAction( |
|
1094 self.trUtf8("Copy Image to Clipboard"), self.__copyImage) |
1057 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"), |
1095 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"), |
1058 self.trUtf8("Copy Image Location to Clipboard"), |
1096 self.trUtf8("Copy Image Location to Clipboard"), |
1059 self.__copyLocation).setData(hit.imageUrl().toString()) |
1097 self.__copyLocation).setData(hit.imageUrl().toString()) |
1060 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"), |
1098 menu.addAction( |
1061 self.trUtf8("Send Image Link"), self.__sendLink).setData(hit.imageUrl()) |
1099 UI.PixmapCache.getIcon("mailSend.png"), |
|
1100 self.trUtf8("Send Image Link"), |
|
1101 self.__sendLink).setData(hit.imageUrl()) |
1062 menu.addSeparator() |
1102 menu.addSeparator() |
1063 menu.addAction(UI.PixmapCache.getIcon("adBlockPlus.png"), |
1103 menu.addAction(UI.PixmapCache.getIcon("adBlockPlus.png"), |
1064 self.trUtf8("Block Image"), self.__blockImage)\ |
1104 self.trUtf8("Block Image"), self.__blockImage)\ |
1065 .setData(hit.imageUrl().toString()) |
1105 .setData(hit.imageUrl().toString()) |
1066 if Preferences.getHelp("VirusTotalEnabled") and \ |
1106 if Preferences.getHelp("VirusTotalEnabled") and \ |
1067 Preferences.getHelp("VirusTotalServiceKey") != "": |
1107 Preferences.getHelp("VirusTotalServiceKey") != "": |
1068 menu.addAction(UI.PixmapCache.getIcon("virustotal.png"), |
1108 menu.addAction( |
1069 self.trUtf8("Scan Image with VirusTotal"), self.__virusTotal)\ |
1109 UI.PixmapCache.getIcon("virustotal.png"), |
1070 .setData(hit.imageUrl()) |
1110 self.trUtf8("Scan Image with VirusTotal"), |
|
1111 self.__virusTotal).setData(hit.imageUrl()) |
1071 |
1112 |
1072 element = hit.element() |
1113 element = hit.element() |
1073 if not element.isNull(): |
1114 if not element.isNull(): |
1074 if self.__isMediaElement(element): |
1115 if self.__isMediaElement(element): |
1075 if not menu.isEmpty(): |
1116 if not menu.isEmpty(): |
1080 paused = element.evaluateJavaScript("this.paused") |
1121 paused = element.evaluateJavaScript("this.paused") |
1081 muted = element.evaluateJavaScript("this.muted") |
1122 muted = element.evaluateJavaScript("this.muted") |
1082 videoUrl = QUrl(element.evaluateJavaScript("this.currentSrc")) |
1123 videoUrl = QUrl(element.evaluateJavaScript("this.currentSrc")) |
1083 |
1124 |
1084 if paused: |
1125 if paused: |
1085 menu.addAction(UI.PixmapCache.getIcon("mediaPlaybackStart.png"), |
1126 menu.addAction( |
|
1127 UI.PixmapCache.getIcon("mediaPlaybackStart.png"), |
1086 self.trUtf8("Play"), self.__pauseMedia) |
1128 self.trUtf8("Play"), self.__pauseMedia) |
1087 else: |
1129 else: |
1088 menu.addAction(UI.PixmapCache.getIcon("mediaPlaybackPause.png"), |
1130 menu.addAction( |
|
1131 UI.PixmapCache.getIcon("mediaPlaybackPause.png"), |
1089 self.trUtf8("Pause"), self.__pauseMedia) |
1132 self.trUtf8("Pause"), self.__pauseMedia) |
1090 if muted: |
1133 if muted: |
1091 menu.addAction(UI.PixmapCache.getIcon("audioVolumeHigh.png"), |
1134 menu.addAction( |
|
1135 UI.PixmapCache.getIcon("audioVolumeHigh.png"), |
1092 self.trUtf8("Unmute"), self.__muteMedia) |
1136 self.trUtf8("Unmute"), self.__muteMedia) |
1093 else: |
1137 else: |
1094 menu.addAction(UI.PixmapCache.getIcon("audioVolumeMuted.png"), |
1138 menu.addAction( |
|
1139 UI.PixmapCache.getIcon("audioVolumeMuted.png"), |
1095 self.trUtf8("Mute"), self.__muteMedia) |
1140 self.trUtf8("Mute"), self.__muteMedia) |
1096 menu.addSeparator() |
1141 menu.addSeparator() |
1097 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"), |
1142 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"), |
1098 self.trUtf8("Copy Media Address to Clipboard"), |
1143 self.trUtf8("Copy Media Address to Clipboard"), |
1099 self.__copyLocation).setData(videoUrl.toString()) |
1144 self.__copyLocation).setData(videoUrl.toString()) |
1105 .setData(videoUrl) |
1150 .setData(videoUrl) |
1106 |
1151 |
1107 if element.tagName().lower() in ["input", "textarea"]: |
1152 if element.tagName().lower() in ["input", "textarea"]: |
1108 if menu.isEmpty(): |
1153 if menu.isEmpty(): |
1109 pageMenu = self.page().createStandardContextMenu() |
1154 pageMenu = self.page().createStandardContextMenu() |
1110 directionFound = False # used to detect double direction entry |
1155 directionFound = False # used to detect double |
|
1156 # direction entry |
1111 for act in pageMenu.actions(): |
1157 for act in pageMenu.actions(): |
1112 if act.isSeparator(): |
1158 if act.isSeparator(): |
1113 menu.addSeparator() |
1159 menu.addSeparator() |
1114 continue |
1160 continue |
1115 if act.menu(): |
1161 if act.menu(): |
1116 if self.pageAction(QWebPage.SetTextDirectionDefault) in \ |
1162 if self.pageAction( |
1117 act.menu().actions(): |
1163 QWebPage.SetTextDirectionDefault) in \ |
|
1164 act.menu().actions(): |
1118 if directionFound: |
1165 if directionFound: |
1119 act.setVisible(False) |
1166 act.setVisible(False) |
1120 directionFound = True |
1167 directionFound = True |
1121 elif self.pageAction(QWebPage.ToggleBold) in \ |
1168 elif self.pageAction(QWebPage.ToggleBold) in \ |
1122 act.menu().actions(): |
1169 act.menu().actions(): |
1172 menu.addAction(UI.PixmapCache.getIcon("bookmark22.png"), |
1219 menu.addAction(UI.PixmapCache.getIcon("bookmark22.png"), |
1173 self.trUtf8("Bookmark this Page"), self.addBookmark) |
1220 self.trUtf8("Bookmark this Page"), self.addBookmark) |
1174 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"), |
1221 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"), |
1175 self.trUtf8("Send Page Link"), self.__sendLink).setData(self.url()) |
1222 self.trUtf8("Send Page Link"), self.__sendLink).setData(self.url()) |
1176 menu.addSeparator() |
1223 menu.addSeparator() |
1177 self.__userAgentMenu = UserAgentMenu(self.trUtf8("User Agent"), url=self.url()) |
1224 self.__userAgentMenu = UserAgentMenu(self.trUtf8("User Agent"), |
|
1225 url=self.url()) |
1178 menu.addMenu(self.__userAgentMenu) |
1226 menu.addMenu(self.__userAgentMenu) |
1179 menu.addSeparator() |
1227 menu.addSeparator() |
1180 menu.addAction(self.mw.backAct) |
1228 menu.addAction(self.mw.backAct) |
1181 menu.addAction(self.mw.forwardAct) |
1229 menu.addAction(self.mw.forwardAct) |
1182 menu.addAction(self.mw.homeAct) |
1230 menu.addAction(self.mw.homeAct) |
1185 menu.addAction(self.mw.zoomResetAct) |
1233 menu.addAction(self.mw.zoomResetAct) |
1186 menu.addAction(self.mw.zoomOutAct) |
1234 menu.addAction(self.mw.zoomOutAct) |
1187 menu.addSeparator() |
1235 menu.addSeparator() |
1188 if self.selectedText(): |
1236 if self.selectedText(): |
1189 menu.addAction(self.mw.copyAct) |
1237 menu.addAction(self.mw.copyAct) |
1190 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"), |
1238 menu.addAction( |
1191 self.trUtf8("Send Text"), self.__sendLink).setData(self.selectedText()) |
1239 UI.PixmapCache.getIcon("mailSend.png"), |
|
1240 self.trUtf8("Send Text"), |
|
1241 self.__sendLink).setData(self.selectedText()) |
1192 menu.addAction(self.mw.findAct) |
1242 menu.addAction(self.mw.findAct) |
1193 menu.addSeparator() |
1243 menu.addSeparator() |
1194 if self.selectedText(): |
1244 if self.selectedText(): |
1195 self.__searchMenu = menu.addMenu(self.trUtf8("Search with...")) |
1245 self.__searchMenu = menu.addMenu(self.trUtf8("Search with...")) |
1196 |
1246 |
1197 from .OpenSearch.OpenSearchEngineAction import OpenSearchEngineAction |
1247 from .OpenSearch.OpenSearchEngineAction import \ |
|
1248 OpenSearchEngineAction |
1198 engineNames = self.mw.openSearchManager().allEnginesNames() |
1249 engineNames = self.mw.openSearchManager().allEnginesNames() |
1199 for engineName in engineNames: |
1250 for engineName in engineNames: |
1200 engine = self.mw.openSearchManager().engine(engineName) |
1251 engine = self.mw.openSearchManager().engine(engineName) |
1201 act = OpenSearchEngineAction(engine, self.__searchMenu) |
1252 act = OpenSearchEngineAction(engine, self.__searchMenu) |
1202 act.setData(engineName) |
1253 act.setData(engineName) |
1217 langCode, self.selectedText())) |
1268 langCode, self.selectedText())) |
1218 menu.addAction(UI.PixmapCache.getIcon("translate.png"), |
1269 menu.addAction(UI.PixmapCache.getIcon("translate.png"), |
1219 self.trUtf8("Google Translate"), self.__openLinkInNewTab)\ |
1270 self.trUtf8("Google Translate"), self.__openLinkInNewTab)\ |
1220 .setData(googleTranslatorUrl) |
1271 .setData(googleTranslatorUrl) |
1221 wiktionaryUrl = QUrl( |
1272 wiktionaryUrl = QUrl( |
1222 "http://{0}.wiktionary.org/wiki/Special:Search?search={1}".format( |
1273 "http://{0}.wiktionary.org/wiki/Special:Search?search={1}" |
1223 langCode, self.selectedText())) |
1274 .format(langCode, self.selectedText())) |
1224 menu.addAction(UI.PixmapCache.getIcon("wikipedia.png"), |
1275 menu.addAction(UI.PixmapCache.getIcon("wikipedia.png"), |
1225 self.trUtf8("Dictionary"), self.__openLinkInNewTab)\ |
1276 self.trUtf8("Dictionary"), self.__openLinkInNewTab)\ |
1226 .setData(wiktionaryUrl) |
1277 .setData(wiktionaryUrl) |
1227 menu.addSeparator() |
1278 menu.addSeparator() |
1228 |
1279 |
1229 guessedUrl = QUrl.fromUserInput(self.selectedText().strip()) |
1280 guessedUrl = QUrl.fromUserInput(self.selectedText().strip()) |
1230 if self.__isUrlValid(guessedUrl): |
1281 if self.__isUrlValid(guessedUrl): |
1231 menu.addAction(self.trUtf8("Go to web address"), self.__openLinkInNewTab)\ |
1282 menu.addAction( |
1232 .setData(guessedUrl) |
1283 self.trUtf8("Go to web address"), |
|
1284 self.__openLinkInNewTab).setData(guessedUrl) |
1233 menu.addSeparator() |
1285 menu.addSeparator() |
1234 |
1286 |
1235 element = hit.element() |
1287 element = hit.element() |
1236 if not element.isNull() and \ |
1288 if not element.isNull() and \ |
1237 element.tagName().lower() == "input" and \ |
1289 element.tagName().lower() == "input" and \ |
1859 "<b>www</b>.example.org").encode("utf8")) |
1916 "<b>www</b>.example.org").encode("utf8")) |
1860 html = html.replace("@LI-2@", |
1917 html = html.replace("@LI-2@", |
1861 self.trUtf8("If the address is correct, try checking the network " |
1918 self.trUtf8("If the address is correct, try checking the network " |
1862 "connection.").encode("utf8")) |
1919 "connection.").encode("utf8")) |
1863 html = html.replace("@LI-3@", |
1920 html = html.replace("@LI-3@", |
1864 self.trUtf8("If your computer or network is protected by a firewall " |
1921 self.trUtf8( |
1865 "or proxy, make sure that the browser is permitted to " |
1922 "If your computer or network is protected by a firewall " |
1866 "access the network.").encode("utf8")) |
1923 "or proxy, make sure that the browser is permitted to " |
|
1924 "access the network.").encode("utf8")) |
1867 html = html.replace("@LI-4@", |
1925 html = html.replace("@LI-4@", |
1868 self.trUtf8("If your cache policy is set to offline browsing," |
1926 self.trUtf8("If your cache policy is set to offline browsing," |
1869 "only pages in the local cache are available.")\ |
1927 "only pages in the local cache are available.")\ |
1870 .encode("utf8")) |
1928 .encode("utf8")) |
1871 html = html.replace("@BUTTON@", self.trUtf8("Try Again").encode("utf8")) |
1929 html = html.replace( |
|
1930 "@BUTTON@", self.trUtf8("Try Again").encode("utf8")) |
1872 notFoundFrame.setHtml(bytes(html).decode("utf8"), replyUrl) |
1931 notFoundFrame.setHtml(bytes(html).decode("utf8"), replyUrl) |
1873 self.mw.historyManager().removeHistoryEntry(replyUrl, self.title()) |
1932 self.mw.historyManager().removeHistoryEntry(replyUrl, self.title()) |
1874 self.loadFinished.emit(False) |
1933 self.loadFinished.emit(False) |
1875 |
1934 |
1876 def __downloadRequested(self, request): |
1935 def __downloadRequested(self, request): |
1895 # accessed for the first time |
1954 # accessed for the first time |
1896 return |
1955 return |
1897 |
1956 |
1898 res = E5MessageBox.yesNo(self, |
1957 res = E5MessageBox.yesNo(self, |
1899 self.trUtf8("Web Database Quota"), |
1958 self.trUtf8("Web Database Quota"), |
1900 self.trUtf8("""<p>The database quota of <strong>{0}</strong> has""" |
1959 self.trUtf8( |
1901 """ been exceeded while accessing database <strong>{1}""" |
1960 """<p>The database quota of <strong>{0}</strong> has""" |
1902 """</strong>.</p><p>Shall it be changed?</p>""")\ |
1961 """ been exceeded while accessing database <strong>{1}""" |
1903 .format(self.__dataString(securityOrigin.databaseQuota()), databaseName), |
1962 """</strong>.</p><p>Shall it be changed?</p>""")\ |
|
1963 .format(self.__dataString(securityOrigin.databaseQuota()), |
|
1964 databaseName), |
1904 yesDefault=True) |
1965 yesDefault=True) |
1905 if res: |
1966 if res: |
1906 newQuota, ok = QInputDialog.getInt( |
1967 newQuota, ok = QInputDialog.getInt( |
1907 self, |
1968 self, |
1908 self.trUtf8("New Web Database Quota"), |
1969 self.trUtf8("New Web Database Quota"), |
1909 self.trUtf8("Enter the new quota in MB (current = {0}, used = {1}; " |
1970 self.trUtf8( |
1910 "step size = 5 MB):"\ |
1971 "Enter the new quota in MB (current = {0}, used = {1}; " |
1911 .format(self.__dataString(securityOrigin.databaseQuota()), |
1972 "step size = 5 MB):"\ |
1912 self.__dataString(securityOrigin.databaseUsage()))), |
1973 .format( |
1913 securityOrigin.databaseQuota() // (1024 * 1024), 0, 2147483647, 5) |
1974 self.__dataString(securityOrigin.databaseQuota()), |
|
1975 self.__dataString(securityOrigin.databaseUsage()))), |
|
1976 securityOrigin.databaseQuota() // (1024 * 1024), |
|
1977 0, 2147483647, 5) |
1914 if ok: |
1978 if ok: |
1915 securityOrigin.setDatabaseQuota(newQuota * 1024 * 1024) |
1979 securityOrigin.setDatabaseQuota(newQuota * 1024 * 1024) |
1916 |
1980 |
1917 def __dataString(self, size): |
1981 def __dataString(self, size): |
1918 """ |
1982 """ |
1976 p -= frame.scrollPosition() |
2040 p -= frame.scrollPosition() |
1977 frame = frame.parentFrame() |
2041 frame = frame.parentFrame() |
1978 while frame and frame != self.page().mainFrame(): |
2042 while frame and frame != self.page().mainFrame(): |
1979 p -= frame.scrollPosition() |
2043 p -= frame.scrollPosition() |
1980 frame = frame.parentFrame() |
2044 frame = frame.parentFrame() |
1981 pevent = QMouseEvent(QEvent.MouseButtonPress, p, Qt.LeftButton, |
2045 pevent = QMouseEvent( |
1982 Qt.MouseButtons(Qt.NoButton), Qt.KeyboardModifiers(Qt.NoModifier)) |
2046 QEvent.MouseButtonPress, p, Qt.LeftButton, |
|
2047 Qt.MouseButtons(Qt.NoButton), |
|
2048 Qt.KeyboardModifiers(Qt.NoModifier)) |
1983 qApp.sendEvent(self, pevent) |
2049 qApp.sendEvent(self, pevent) |
1984 revent = QMouseEvent(QEvent.MouseButtonRelease, p, Qt.LeftButton, |
2050 revent = QMouseEvent( |
1985 Qt.MouseButtons(Qt.NoButton), Qt.KeyboardModifiers(Qt.NoModifier)) |
2051 QEvent.MouseButtonRelease, p, Qt.LeftButton, |
|
2052 Qt.MouseButtons(Qt.NoButton), |
|
2053 Qt.KeyboardModifiers(Qt.NoModifier)) |
1986 qApp.sendEvent(self, revent) |
2054 qApp.sendEvent(self, revent) |
1987 handled = True |
2055 handled = True |
1988 |
2056 |
1989 return handled |
2057 return handled |
1990 |
2058 |
2013 viewport = QRect(self.__page.mainFrame().scrollPosition(), |
2081 viewport = QRect(self.__page.mainFrame().scrollPosition(), |
2014 self.__page.viewportSize()) |
2082 self.__page.viewportSize()) |
2015 # Priority first goes to elements with accesskey attributes |
2083 # Priority first goes to elements with accesskey attributes |
2016 alreadyLabeled = [] |
2084 alreadyLabeled = [] |
2017 for elementType in supportedElements: |
2085 for elementType in supportedElements: |
2018 result = self.page().mainFrame().findAllElements(elementType).toList() |
2086 result = self.page().mainFrame().findAllElements(elementType)\ |
|
2087 .toList() |
2019 for element in result: |
2088 for element in result: |
2020 geometry = element.geometry() |
2089 geometry = element.geometry() |
2021 if geometry.size().isEmpty() or \ |
2090 if geometry.size().isEmpty() or \ |
2022 not viewport.contains(geometry.topLeft()): |
2091 not viewport.contains(geometry.topLeft()): |
2023 continue |
2092 continue |
2037 continue |
2106 continue |
2038 unusedKeys.remove(accessKey) |
2107 unusedKeys.remove(accessKey) |
2039 self.__makeAccessLabel(accessKey, element) |
2108 self.__makeAccessLabel(accessKey, element) |
2040 alreadyLabeled.append(element) |
2109 alreadyLabeled.append(element) |
2041 |
2110 |
2042 # Pick an access key first from the letters in the text and then from the |
2111 # Pick an access key first from the letters in the text and then |
2043 # list of unused access keys |
2112 # from the list of unused access keys |
2044 for elementType in supportedElements: |
2113 for elementType in supportedElements: |
2045 result = self.page().mainFrame().findAllElements(elementType).toList() |
2114 result = self.page().mainFrame().findAllElements(elementType)\ |
|
2115 .toList() |
2046 for element in result: |
2116 for element in result: |
2047 geometry = element.geometry() |
2117 geometry = element.geometry() |
2048 if not unusedKeys or \ |
2118 if not unusedKeys or \ |
2049 element in alreadyLabeled or \ |
2119 element in alreadyLabeled or \ |
2050 geometry.size().isEmpty() or \ |
2120 geometry.size().isEmpty() or \ |
2266 try: |
2338 try: |
2267 self.__clickedFrame.print_(printer) |
2339 self.__clickedFrame.print_(printer) |
2268 except AttributeError: |
2340 except AttributeError: |
2269 E5MessageBox.critical(self, |
2341 E5MessageBox.critical(self, |
2270 self.trUtf8("eric5 Web Browser"), |
2342 self.trUtf8("eric5 Web Browser"), |
2271 self.trUtf8("""<p>Printing is not available due to a bug in PyQt4.""" |
2343 self.trUtf8( |
2272 """Please upgrade.</p>""")) |
2344 """<p>Printing is not available due to a bug in""" |
|
2345 """ PyQt4. Please upgrade.</p>""")) |
2273 return |
2346 return |
2274 |
2347 |
2275 def __zoomInClickedFrame(self): |
2348 def __zoomInClickedFrame(self): |
2276 """ |
2349 """ |
2277 Private slot to zoom into the clicked frame. |
2350 Private slot to zoom into the clicked frame. |
2278 """ |
2351 """ |
2279 index = self.__levelForZoom(int(self.__clickedFrame.zoomFactor() * 100)) |
2352 index = self.__levelForZoom( |
|
2353 int(self.__clickedFrame.zoomFactor() * 100)) |
2280 if index < len(self.__zoomLevels) - 1: |
2354 if index < len(self.__zoomLevels) - 1: |
2281 self.__clickedFrame.setZoomFactor(self.__zoomLevels[index + 1] / 100) |
2355 self.__clickedFrame.setZoomFactor( |
|
2356 self.__zoomLevels[index + 1] / 100) |
2282 |
2357 |
2283 def __zoomResetClickedFrame(self): |
2358 def __zoomResetClickedFrame(self): |
2284 """ |
2359 """ |
2285 Private slot to reset the zoom factor of the clicked frame. |
2360 Private slot to reset the zoom factor of the clicked frame. |
2286 """ |
2361 """ |