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